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