xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/asan/asan_descriptions.h (revision a7c257b03e4462df2b1020128fb82716512d7856)
1 //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // ASan-private header for asan_descriptions.cc.
13 // TODO(filcab): Most struct definitions should move to the interface headers.
14 //===----------------------------------------------------------------------===//
15 #ifndef ASAN_DESCRIPTIONS_H
16 #define ASAN_DESCRIPTIONS_H
17 
18 #include "asan_allocator.h"
19 #include "asan_thread.h"
20 #include "sanitizer_common/sanitizer_common.h"
21 #include "sanitizer_common/sanitizer_report_decorator.h"
22 
23 namespace __asan {
24 
25 void DescribeThread(AsanThreadContext *context);
DescribeThread(AsanThread * t)26 static inline void DescribeThread(AsanThread *t) {
27   if (t) DescribeThread(t->context());
28 }
29 
30 class AsanThreadIdAndName {
31  public:
32   explicit AsanThreadIdAndName(AsanThreadContext *t);
33   explicit AsanThreadIdAndName(u32 tid);
34 
35   // Contains "T%tid (%name)" or "T%tid" if the name is empty.
c_str()36   const char *c_str() const { return &name[0]; }
37 
38  private:
39   void Init(u32 tid, const char *tname);
40 
41   char name[128];
42 };
43 
44 class Decorator : public __sanitizer::SanitizerCommonDecorator {
45  public:
Decorator()46   Decorator() : SanitizerCommonDecorator() {}
Access()47   const char *Access() { return Blue(); }
Location()48   const char *Location() { return Green(); }
Allocation()49   const char *Allocation() { return Magenta(); }
50 
ShadowByte(u8 byte)51   const char *ShadowByte(u8 byte) {
52     switch (byte) {
53       case kAsanHeapLeftRedzoneMagic:
54       case kAsanArrayCookieMagic:
55         return Red();
56       case kAsanHeapFreeMagic:
57         return Magenta();
58       case kAsanStackLeftRedzoneMagic:
59       case kAsanStackMidRedzoneMagic:
60       case kAsanStackRightRedzoneMagic:
61         return Red();
62       case kAsanStackAfterReturnMagic:
63         return Magenta();
64       case kAsanInitializationOrderMagic:
65         return Cyan();
66       case kAsanUserPoisonedMemoryMagic:
67       case kAsanContiguousContainerOOBMagic:
68       case kAsanAllocaLeftMagic:
69       case kAsanAllocaRightMagic:
70         return Blue();
71       case kAsanStackUseAfterScopeMagic:
72         return Magenta();
73       case kAsanGlobalRedzoneMagic:
74         return Red();
75       case kAsanInternalHeapMagic:
76         return Yellow();
77       case kAsanIntraObjectRedzone:
78         return Yellow();
79       default:
80         return Default();
81     }
82   }
83 };
84 
85 enum ShadowKind : u8 {
86   kShadowKindLow,
87   kShadowKindGap,
88   kShadowKindHigh,
89 };
90 static const char *const ShadowNames[] = {"low shadow", "shadow gap",
91                                           "high shadow"};
92 
93 struct ShadowAddressDescription {
94   uptr addr;
95   ShadowKind kind;
96   u8 shadow_byte;
97 
98   void Print() const;
99 };
100 
101 bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
102 bool DescribeAddressIfShadow(uptr addr);
103 
104 enum AccessType {
105   kAccessTypeLeft,
106   kAccessTypeRight,
107   kAccessTypeInside,
108   kAccessTypeUnknown,  // This means we have an AddressSanitizer bug!
109 };
110 
111 struct ChunkAccess {
112   uptr bad_addr;
113   sptr offset;
114   uptr chunk_begin;
115   uptr chunk_size;
116   u32 user_requested_alignment : 12;
117   u32 access_type : 2;
118   u32 alloc_type : 2;
119 };
120 
121 struct HeapAddressDescription {
122   uptr addr;
123   uptr alloc_tid;
124   uptr free_tid;
125   u32 alloc_stack_id;
126   u32 free_stack_id;
127   ChunkAccess chunk_access;
128 
129   void Print() const;
130 };
131 
132 bool GetHeapAddressInformation(uptr addr, uptr access_size,
133                                HeapAddressDescription *descr);
134 bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
135 
136 struct StackAddressDescription {
137   uptr addr;
138   uptr tid;
139   uptr offset;
140   uptr frame_pc;
141   uptr access_size;
142   const char *frame_descr;
143 
144   void Print() const;
145 };
146 
147 bool GetStackAddressInformation(uptr addr, uptr access_size,
148                                 StackAddressDescription *descr);
149 
150 struct GlobalAddressDescription {
151   uptr addr;
152   // Assume address is close to at most four globals.
153   static const int kMaxGlobals = 4;
154   __asan_global globals[kMaxGlobals];
155   u32 reg_sites[kMaxGlobals];
156   uptr access_size;
157   u8 size;
158 
159   void Print(const char *bug_type = "") const;
160 
161   // Returns true when this descriptions points inside the same global variable
162   // as other. Descriptions can have different address within the variable
163   bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
164 };
165 
166 bool GetGlobalAddressInformation(uptr addr, uptr access_size,
167                                  GlobalAddressDescription *descr);
168 bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
169 
170 // General function to describe an address. Will try to describe the address as
171 // a shadow, global (variable), stack, or heap address.
172 // bug_type is optional and is used for checking if we're reporting an
173 // initialization-order-fiasco
174 // The proper access_size should be passed for stack, global, and heap
175 // addresses. Defaults to 1.
176 // Each of the *AddressDescription functions has its own Print() member, which
177 // may take access_size and bug_type parameters if needed.
178 void PrintAddressDescription(uptr addr, uptr access_size = 1,
179                              const char *bug_type = "");
180 
181 enum AddressKind {
182   kAddressKindWild,
183   kAddressKindShadow,
184   kAddressKindHeap,
185   kAddressKindStack,
186   kAddressKindGlobal,
187 };
188 
189 class AddressDescription {
190   struct AddressDescriptionData {
191     AddressKind kind;
192     union {
193       ShadowAddressDescription shadow;
194       HeapAddressDescription heap;
195       StackAddressDescription stack;
196       GlobalAddressDescription global;
197       uptr addr;
198     };
199   };
200 
201   AddressDescriptionData data;
202 
203  public:
204   AddressDescription() = default;
205   // shouldLockThreadRegistry allows us to skip locking if we're sure we already
206   // have done it.
207   AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
208       : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
209   AddressDescription(uptr addr, uptr access_size,
210                      bool shouldLockThreadRegistry = true);
211 
Address()212   uptr Address() const {
213     switch (data.kind) {
214       case kAddressKindWild:
215         return data.addr;
216       case kAddressKindShadow:
217         return data.shadow.addr;
218       case kAddressKindHeap:
219         return data.heap.addr;
220       case kAddressKindStack:
221         return data.stack.addr;
222       case kAddressKindGlobal:
223         return data.global.addr;
224     }
225     UNREACHABLE("AddressInformation kind is invalid");
226   }
227   void Print(const char *bug_descr = nullptr) const {
228     switch (data.kind) {
229       case kAddressKindWild:
230         Printf("Address %p is a wild pointer.\n", data.addr);
231         return;
232       case kAddressKindShadow:
233         return data.shadow.Print();
234       case kAddressKindHeap:
235         return data.heap.Print();
236       case kAddressKindStack:
237         return data.stack.Print();
238       case kAddressKindGlobal:
239         // initialization-order-fiasco has a special Print()
240         return data.global.Print(bug_descr);
241     }
242     UNREACHABLE("AddressInformation kind is invalid");
243   }
244 
StoreTo(AddressDescriptionData * dst)245   void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
246 
AsShadow()247   const ShadowAddressDescription *AsShadow() const {
248     return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
249   }
AsHeap()250   const HeapAddressDescription *AsHeap() const {
251     return data.kind == kAddressKindHeap ? &data.heap : nullptr;
252   }
AsStack()253   const StackAddressDescription *AsStack() const {
254     return data.kind == kAddressKindStack ? &data.stack : nullptr;
255   }
AsGlobal()256   const GlobalAddressDescription *AsGlobal() const {
257     return data.kind == kAddressKindGlobal ? &data.global : nullptr;
258   }
259 };
260 
261 }  // namespace __asan
262 
263 #endif  // ASAN_DESCRIPTIONS_H
264