1 //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of AddressSanitizer, an address sanity checker.
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
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"
25 void DescribeThread(AsanThreadContext *context);
26 static inline void DescribeThread(AsanThread *t) {
27 if (t) DescribeThread(t->context());
29 const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
31 const char *ThreadNameWithParenthesis(u32 tid, char buff[], uptr buff_len);
33 class Decorator : public __sanitizer::SanitizerCommonDecorator {
35 Decorator() : SanitizerCommonDecorator() {}
36 const char *Access() { return Blue(); }
37 const char *EndAccess() { return Default(); }
38 const char *Location() { return Green(); }
39 const char *EndLocation() { return Default(); }
40 const char *Allocation() { return Magenta(); }
41 const char *EndAllocation() { return Default(); }
43 const char *ShadowByte(u8 byte) {
45 case kAsanHeapLeftRedzoneMagic:
46 case kAsanArrayCookieMagic:
48 case kAsanHeapFreeMagic:
50 case kAsanStackLeftRedzoneMagic:
51 case kAsanStackMidRedzoneMagic:
52 case kAsanStackRightRedzoneMagic:
54 case kAsanStackAfterReturnMagic:
56 case kAsanInitializationOrderMagic:
58 case kAsanUserPoisonedMemoryMagic:
59 case kAsanContiguousContainerOOBMagic:
60 case kAsanAllocaLeftMagic:
61 case kAsanAllocaRightMagic:
63 case kAsanStackUseAfterScopeMagic:
65 case kAsanGlobalRedzoneMagic:
67 case kAsanInternalHeapMagic:
69 case kAsanIntraObjectRedzone:
75 const char *EndShadowByte() { return Default(); }
76 const char *MemoryByte() { return Magenta(); }
77 const char *EndMemoryByte() { return Default(); }
80 enum ShadowKind : u8 {
85 static const char *const ShadowNames[] = {"low shadow", "shadow gap",
88 struct ShadowAddressDescription {
96 bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
97 bool DescribeAddressIfShadow(uptr addr);
103 kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
115 struct HeapAddressDescription {
121 ChunkAccess chunk_access;
126 bool GetHeapAddressInformation(uptr addr, uptr access_size,
127 HeapAddressDescription *descr);
128 bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
130 struct StackAddressDescription {
136 const char *frame_descr;
141 bool GetStackAddressInformation(uptr addr, uptr access_size,
142 StackAddressDescription *descr);
144 struct GlobalAddressDescription {
146 // Assume address is close to at most four globals.
147 static const int kMaxGlobals = 4;
148 __asan_global globals[kMaxGlobals];
149 u32 reg_sites[kMaxGlobals];
153 void Print(const char *bug_type = "") const;
156 bool GetGlobalAddressInformation(uptr addr, uptr access_size,
157 GlobalAddressDescription *descr);
158 bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
160 // General function to describe an address. Will try to describe the address as
161 // a shadow, global (variable), stack, or heap address.
162 // bug_type is optional and is used for checking if we're reporting an
163 // initialization-order-fiasco
164 // The proper access_size should be passed for stack, global, and heap
165 // addresses. Defaults to 1.
166 // Each of the *AddressDescription functions has its own Print() member, which
167 // may take access_size and bug_type parameters if needed.
168 void PrintAddressDescription(uptr addr, uptr access_size = 1,
169 const char *bug_type = "");
179 class AddressDescription {
180 struct AddressDescriptionData {
183 ShadowAddressDescription shadow;
184 HeapAddressDescription heap;
185 StackAddressDescription stack;
186 GlobalAddressDescription global;
191 AddressDescriptionData data;
194 AddressDescription() = default;
195 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
197 AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
198 : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
199 AddressDescription(uptr addr, uptr access_size,
200 bool shouldLockThreadRegistry = true);
202 uptr Address() const {
204 case kAddressKindWild:
206 case kAddressKindShadow:
207 return data.shadow.addr;
208 case kAddressKindHeap:
209 return data.heap.addr;
210 case kAddressKindStack:
211 return data.stack.addr;
212 case kAddressKindGlobal:
213 return data.global.addr;
215 UNREACHABLE("AddressInformation kind is invalid");
217 void Print(const char *bug_descr = nullptr) const {
219 case kAddressKindWild:
220 Printf("Address %p is a wild pointer.\n", data.addr);
222 case kAddressKindShadow:
223 return data.shadow.Print();
224 case kAddressKindHeap:
225 return data.heap.Print();
226 case kAddressKindStack:
227 return data.stack.Print();
228 case kAddressKindGlobal:
229 // initialization-order-fiasco has a special Print()
230 return data.global.Print(bug_descr);
232 UNREACHABLE("AddressInformation kind is invalid");
235 void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
237 const ShadowAddressDescription *AsShadow() const {
238 return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
240 const HeapAddressDescription *AsHeap() const {
241 return data.kind == kAddressKindHeap ? &data.heap : nullptr;
243 const StackAddressDescription *AsStack() const {
244 return data.kind == kAddressKindStack ? &data.stack : nullptr;
246 const GlobalAddressDescription *AsGlobal() const {
247 return data.kind == kAddressKindGlobal ? &data.global : nullptr;
251 } // namespace __asan
253 #endif // ASAN_DESCRIPTIONS_H