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 *Location() { return Green(); }
38 const char *Allocation() { return Magenta(); }
40 const char *ShadowByte(u8 byte) {
42 case kAsanHeapLeftRedzoneMagic:
43 case kAsanArrayCookieMagic:
45 case kAsanHeapFreeMagic:
47 case kAsanStackLeftRedzoneMagic:
48 case kAsanStackMidRedzoneMagic:
49 case kAsanStackRightRedzoneMagic:
51 case kAsanStackAfterReturnMagic:
53 case kAsanInitializationOrderMagic:
55 case kAsanUserPoisonedMemoryMagic:
56 case kAsanContiguousContainerOOBMagic:
57 case kAsanAllocaLeftMagic:
58 case kAsanAllocaRightMagic:
60 case kAsanStackUseAfterScopeMagic:
62 case kAsanGlobalRedzoneMagic:
64 case kAsanInternalHeapMagic:
66 case kAsanIntraObjectRedzone:
74 enum ShadowKind : u8 {
79 static const char *const ShadowNames[] = {"low shadow", "shadow gap",
82 struct ShadowAddressDescription {
90 bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
91 bool DescribeAddressIfShadow(uptr addr);
97 kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
105 u32 user_requested_alignment : 12;
110 struct HeapAddressDescription {
116 ChunkAccess chunk_access;
121 bool GetHeapAddressInformation(uptr addr, uptr access_size,
122 HeapAddressDescription *descr);
123 bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
125 struct StackAddressDescription {
131 const char *frame_descr;
136 bool GetStackAddressInformation(uptr addr, uptr access_size,
137 StackAddressDescription *descr);
139 struct GlobalAddressDescription {
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];
148 void Print(const char *bug_type = "") const;
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;
155 bool GetGlobalAddressInformation(uptr addr, uptr access_size,
156 GlobalAddressDescription *descr);
157 bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
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 = "");
178 class AddressDescription {
179 struct AddressDescriptionData {
182 ShadowAddressDescription shadow;
183 HeapAddressDescription heap;
184 StackAddressDescription stack;
185 GlobalAddressDescription global;
190 AddressDescriptionData data;
193 AddressDescription() = default;
194 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
196 AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
197 : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
198 AddressDescription(uptr addr, uptr access_size,
199 bool shouldLockThreadRegistry = true);
201 uptr Address() const {
203 case kAddressKindWild:
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;
214 UNREACHABLE("AddressInformation kind is invalid");
216 void Print(const char *bug_descr = nullptr) const {
218 case kAddressKindWild:
219 Printf("Address %p is a wild pointer.\n", data.addr);
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);
231 UNREACHABLE("AddressInformation kind is invalid");
234 void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
236 const ShadowAddressDescription *AsShadow() const {
237 return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
239 const HeapAddressDescription *AsHeap() const {
240 return data.kind == kAddressKindHeap ? &data.heap : nullptr;
242 const StackAddressDescription *AsStack() const {
243 return data.kind == kAddressKindStack ? &data.stack : nullptr;
245 const GlobalAddressDescription *AsGlobal() const {
246 return data.kind == kAddressKindGlobal ? &data.global : nullptr;
250 } // namespace __asan
252 #endif // ASAN_DESCRIPTIONS_H