xref: /openbsd-src/gnu/llvm/compiler-rt/lib/hwasan/hwasan_globals.cpp (revision 1f9cb04fc6f537ca6cf5a53c28927340cba218a2)
1*1f9cb04fSpatrick //===-- hwasan_globals.cpp ------------------------------------------------===//
2*1f9cb04fSpatrick //
3*1f9cb04fSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*1f9cb04fSpatrick // See https://llvm.org/LICENSE.txt for license information.
5*1f9cb04fSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*1f9cb04fSpatrick //
7*1f9cb04fSpatrick //===----------------------------------------------------------------------===//
8*1f9cb04fSpatrick //
9*1f9cb04fSpatrick // This file is a part of HWAddressSanitizer.
10*1f9cb04fSpatrick //
11*1f9cb04fSpatrick // HWAddressSanitizer globals-specific runtime.
12*1f9cb04fSpatrick //===----------------------------------------------------------------------===//
13*1f9cb04fSpatrick 
14*1f9cb04fSpatrick #include "hwasan_globals.h"
15*1f9cb04fSpatrick 
16*1f9cb04fSpatrick namespace __hwasan {
17*1f9cb04fSpatrick 
18*1f9cb04fSpatrick enum { NT_LLVM_HWASAN_GLOBALS = 3 };
19*1f9cb04fSpatrick struct hwasan_global_note {
20*1f9cb04fSpatrick   s32 begin_relptr;
21*1f9cb04fSpatrick   s32 end_relptr;
22*1f9cb04fSpatrick };
23*1f9cb04fSpatrick 
24*1f9cb04fSpatrick // Check that the given library meets the code model requirements for tagged
25*1f9cb04fSpatrick // globals. These properties are not checked at link time so they need to be
26*1f9cb04fSpatrick // checked at runtime.
CheckCodeModel(ElfW (Addr)base,const ElfW (Phdr)* phdr,ElfW (Half)phnum)27*1f9cb04fSpatrick static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr,
28*1f9cb04fSpatrick                            ElfW(Half) phnum) {
29*1f9cb04fSpatrick   ElfW(Addr) min_addr = -1ull, max_addr = 0;
30*1f9cb04fSpatrick   for (unsigned i = 0; i != phnum; ++i) {
31*1f9cb04fSpatrick     if (phdr[i].p_type != PT_LOAD)
32*1f9cb04fSpatrick       continue;
33*1f9cb04fSpatrick     ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz;
34*1f9cb04fSpatrick     if (min_addr > lo)
35*1f9cb04fSpatrick       min_addr = lo;
36*1f9cb04fSpatrick     if (max_addr < hi)
37*1f9cb04fSpatrick       max_addr = hi;
38*1f9cb04fSpatrick   }
39*1f9cb04fSpatrick 
40*1f9cb04fSpatrick   if (max_addr - min_addr > 1ull << 32) {
41*1f9cb04fSpatrick     Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n");
42*1f9cb04fSpatrick     Die();
43*1f9cb04fSpatrick   }
44*1f9cb04fSpatrick   if (max_addr > 1ull << 48) {
45*1f9cb04fSpatrick     Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n");
46*1f9cb04fSpatrick     Die();
47*1f9cb04fSpatrick   }
48*1f9cb04fSpatrick }
49*1f9cb04fSpatrick 
HwasanGlobalsFor(ElfW (Addr)base,const ElfW (Phdr)* phdr,ElfW (Half)phnum)50*1f9cb04fSpatrick ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
51*1f9cb04fSpatrick                                                const ElfW(Phdr) * phdr,
52*1f9cb04fSpatrick                                                ElfW(Half) phnum) {
53*1f9cb04fSpatrick   // Read the phdrs from this DSO.
54*1f9cb04fSpatrick   for (unsigned i = 0; i != phnum; ++i) {
55*1f9cb04fSpatrick     if (phdr[i].p_type != PT_NOTE)
56*1f9cb04fSpatrick       continue;
57*1f9cb04fSpatrick 
58*1f9cb04fSpatrick     const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr);
59*1f9cb04fSpatrick     const char *nend = note + phdr[i].p_memsz;
60*1f9cb04fSpatrick 
61*1f9cb04fSpatrick     // Traverse all the notes until we find a HWASan note.
62*1f9cb04fSpatrick     while (note < nend) {
63*1f9cb04fSpatrick       auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note);
64*1f9cb04fSpatrick       const char *name = note + sizeof(ElfW(Nhdr));
65*1f9cb04fSpatrick       const char *desc = name + RoundUpTo(nhdr->n_namesz, 4);
66*1f9cb04fSpatrick 
67*1f9cb04fSpatrick       // Discard non-HWASan-Globals notes.
68*1f9cb04fSpatrick       if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS ||
69*1f9cb04fSpatrick           internal_strcmp(name, "LLVM") != 0) {
70*1f9cb04fSpatrick         note = desc + RoundUpTo(nhdr->n_descsz, 4);
71*1f9cb04fSpatrick         continue;
72*1f9cb04fSpatrick       }
73*1f9cb04fSpatrick 
74*1f9cb04fSpatrick       // Only libraries with instrumented globals need to be checked against the
75*1f9cb04fSpatrick       // code model since they use relocations that aren't checked at link time.
76*1f9cb04fSpatrick       CheckCodeModel(base, phdr, phnum);
77*1f9cb04fSpatrick 
78*1f9cb04fSpatrick       auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc);
79*1f9cb04fSpatrick       auto *globals_begin = reinterpret_cast<const hwasan_global *>(
80*1f9cb04fSpatrick           note + global_note->begin_relptr);
81*1f9cb04fSpatrick       auto *globals_end = reinterpret_cast<const hwasan_global *>(
82*1f9cb04fSpatrick           note + global_note->end_relptr);
83*1f9cb04fSpatrick 
84*1f9cb04fSpatrick       return {globals_begin, globals_end};
85*1f9cb04fSpatrick     }
86*1f9cb04fSpatrick   }
87*1f9cb04fSpatrick 
88*1f9cb04fSpatrick   return {};
89*1f9cb04fSpatrick }
90*1f9cb04fSpatrick 
91*1f9cb04fSpatrick }  // namespace __hwasan
92