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