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