xref: /freebsd/contrib/llvm-project/compiler-rt/lib/hwasan/hwasan_globals.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- hwasan_globals.cpp ------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This file is a part of HWAddressSanitizer.
105ffd83dbSDimitry Andric //
115ffd83dbSDimitry Andric // HWAddressSanitizer globals-specific runtime.
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "hwasan_globals.h"
155ffd83dbSDimitry Andric 
16*06c3fb27SDimitry Andric #include "sanitizer_common/sanitizer_array_ref.h"
17*06c3fb27SDimitry Andric 
185ffd83dbSDimitry Andric namespace __hwasan {
195ffd83dbSDimitry Andric 
205ffd83dbSDimitry Andric enum { NT_LLVM_HWASAN_GLOBALS = 3 };
215ffd83dbSDimitry Andric struct hwasan_global_note {
225ffd83dbSDimitry Andric   s32 begin_relptr;
235ffd83dbSDimitry Andric   s32 end_relptr;
245ffd83dbSDimitry Andric };
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric // Check that the given library meets the code model requirements for tagged
275ffd83dbSDimitry Andric // globals. These properties are not checked at link time so they need to be
285ffd83dbSDimitry Andric // checked at runtime.
CheckCodeModel(ElfW (Addr)base,const ElfW (Phdr)* phdr,ElfW (Half)phnum)295ffd83dbSDimitry Andric static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr,
305ffd83dbSDimitry Andric                            ElfW(Half) phnum) {
315ffd83dbSDimitry Andric   ElfW(Addr) min_addr = -1ull, max_addr = 0;
325ffd83dbSDimitry Andric   for (unsigned i = 0; i != phnum; ++i) {
335ffd83dbSDimitry Andric     if (phdr[i].p_type != PT_LOAD)
345ffd83dbSDimitry Andric       continue;
355ffd83dbSDimitry Andric     ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz;
365ffd83dbSDimitry Andric     if (min_addr > lo)
375ffd83dbSDimitry Andric       min_addr = lo;
385ffd83dbSDimitry Andric     if (max_addr < hi)
395ffd83dbSDimitry Andric       max_addr = hi;
405ffd83dbSDimitry Andric   }
415ffd83dbSDimitry Andric 
425ffd83dbSDimitry Andric   if (max_addr - min_addr > 1ull << 32) {
435ffd83dbSDimitry Andric     Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n");
445ffd83dbSDimitry Andric     Die();
455ffd83dbSDimitry Andric   }
465ffd83dbSDimitry Andric   if (max_addr > 1ull << 48) {
475ffd83dbSDimitry Andric     Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n");
485ffd83dbSDimitry Andric     Die();
495ffd83dbSDimitry Andric   }
505ffd83dbSDimitry Andric }
515ffd83dbSDimitry Andric 
HwasanGlobalsFor(ElfW (Addr)base,const ElfW (Phdr)* phdr,ElfW (Half)phnum)525ffd83dbSDimitry Andric ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
535ffd83dbSDimitry Andric                                                const ElfW(Phdr) * phdr,
545ffd83dbSDimitry Andric                                                ElfW(Half) phnum) {
555ffd83dbSDimitry Andric   // Read the phdrs from this DSO.
565ffd83dbSDimitry Andric   for (unsigned i = 0; i != phnum; ++i) {
575ffd83dbSDimitry Andric     if (phdr[i].p_type != PT_NOTE)
585ffd83dbSDimitry Andric       continue;
595ffd83dbSDimitry Andric 
605ffd83dbSDimitry Andric     const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr);
615ffd83dbSDimitry Andric     const char *nend = note + phdr[i].p_memsz;
625ffd83dbSDimitry Andric 
635ffd83dbSDimitry Andric     // Traverse all the notes until we find a HWASan note.
645ffd83dbSDimitry Andric     while (note < nend) {
655ffd83dbSDimitry Andric       auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note);
665ffd83dbSDimitry Andric       const char *name = note + sizeof(ElfW(Nhdr));
675ffd83dbSDimitry Andric       const char *desc = name + RoundUpTo(nhdr->n_namesz, 4);
685ffd83dbSDimitry Andric 
695ffd83dbSDimitry Andric       // Discard non-HWASan-Globals notes.
705ffd83dbSDimitry Andric       if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS ||
715ffd83dbSDimitry Andric           internal_strcmp(name, "LLVM") != 0) {
725ffd83dbSDimitry Andric         note = desc + RoundUpTo(nhdr->n_descsz, 4);
735ffd83dbSDimitry Andric         continue;
745ffd83dbSDimitry Andric       }
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric       // Only libraries with instrumented globals need to be checked against the
775ffd83dbSDimitry Andric       // code model since they use relocations that aren't checked at link time.
785ffd83dbSDimitry Andric       CheckCodeModel(base, phdr, phnum);
795ffd83dbSDimitry Andric 
805ffd83dbSDimitry Andric       auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc);
815ffd83dbSDimitry Andric       auto *globals_begin = reinterpret_cast<const hwasan_global *>(
825ffd83dbSDimitry Andric           note + global_note->begin_relptr);
835ffd83dbSDimitry Andric       auto *globals_end = reinterpret_cast<const hwasan_global *>(
845ffd83dbSDimitry Andric           note + global_note->end_relptr);
855ffd83dbSDimitry Andric 
865ffd83dbSDimitry Andric       return {globals_begin, globals_end};
875ffd83dbSDimitry Andric     }
885ffd83dbSDimitry Andric   }
895ffd83dbSDimitry Andric 
905ffd83dbSDimitry Andric   return {};
915ffd83dbSDimitry Andric }
925ffd83dbSDimitry Andric 
935ffd83dbSDimitry Andric }  // namespace __hwasan
94