1 //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
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"
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
[],
29 const char *ThreadNameWithParenthesis(u32 tid
, char buff
[], uptr buff_len
);
31 class Decorator
: public __sanitizer::SanitizerCommonDecorator
{
33 Decorator() : SanitizerCommonDecorator() {}
34 const char *Access() { return Blue(); }
35 const char *Location() { return Green(); }
36 const char *Allocation() { return Magenta(); }
38 const char *ShadowByte(u8 byte
) {
40 case kAsanHeapLeftRedzoneMagic
:
41 case kAsanArrayCookieMagic
:
43 case kAsanHeapFreeMagic
:
45 case kAsanStackLeftRedzoneMagic
:
46 case kAsanStackMidRedzoneMagic
:
47 case kAsanStackRightRedzoneMagic
:
49 case kAsanStackAfterReturnMagic
:
51 case kAsanInitializationOrderMagic
:
53 case kAsanUserPoisonedMemoryMagic
:
54 case kAsanContiguousContainerOOBMagic
:
55 case kAsanAllocaLeftMagic
:
56 case kAsanAllocaRightMagic
:
58 case kAsanStackUseAfterScopeMagic
:
60 case kAsanGlobalRedzoneMagic
:
62 case kAsanInternalHeapMagic
:
64 case kAsanIntraObjectRedzone
:
72 enum ShadowKind
: u8
{
77 static const char *const ShadowNames
[] = {"low shadow", "shadow gap",
80 struct ShadowAddressDescription
{
88 bool GetShadowAddressInformation(uptr addr
, ShadowAddressDescription
*descr
);
89 bool DescribeAddressIfShadow(uptr addr
);
95 kAccessTypeUnknown
, // This means we have an AddressSanitizer bug!
107 struct HeapAddressDescription
{
113 ChunkAccess chunk_access
;
118 bool GetHeapAddressInformation(uptr addr
, uptr access_size
,
119 HeapAddressDescription
*descr
);
120 bool DescribeAddressIfHeap(uptr addr
, uptr access_size
= 1);
122 struct StackAddressDescription
{
128 const char *frame_descr
;
133 bool GetStackAddressInformation(uptr addr
, uptr access_size
,
134 StackAddressDescription
*descr
);
136 struct GlobalAddressDescription
{
138 // Assume address is close to at most four globals.
139 static const int kMaxGlobals
= 4;
140 __asan_global globals
[kMaxGlobals
];
141 u32 reg_sites
[kMaxGlobals
];
145 void Print(const char *bug_type
= "") const;
148 bool GetGlobalAddressInformation(uptr addr
, uptr access_size
,
149 GlobalAddressDescription
*descr
);
150 bool DescribeAddressIfGlobal(uptr addr
, uptr access_size
, const char *bug_type
);
152 // General function to describe an address. Will try to describe the address as
153 // a shadow, global (variable), stack, or heap address.
154 // bug_type is optional and is used for checking if we're reporting an
155 // initialization-order-fiasco
156 // The proper access_size should be passed for stack, global, and heap
157 // addresses. Defaults to 1.
158 // Each of the *AddressDescription functions has its own Print() member, which
159 // may take access_size and bug_type parameters if needed.
160 void PrintAddressDescription(uptr addr
, uptr access_size
= 1,
161 const char *bug_type
= "");
171 class AddressDescription
{
172 struct AddressDescriptionData
{
175 ShadowAddressDescription shadow
;
176 HeapAddressDescription heap
;
177 StackAddressDescription stack
;
178 GlobalAddressDescription global
;
183 AddressDescriptionData data
;
186 AddressDescription() = default;
187 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
189 AddressDescription(uptr addr
, bool shouldLockThreadRegistry
= true)
190 : AddressDescription(addr
, 1, shouldLockThreadRegistry
) {}
191 AddressDescription(uptr addr
, uptr access_size
,
192 bool shouldLockThreadRegistry
= true);
194 uptr
Address() const {
196 case kAddressKindWild
:
198 case kAddressKindShadow
:
199 return data
.shadow
.addr
;
200 case kAddressKindHeap
:
201 return data
.heap
.addr
;
202 case kAddressKindStack
:
203 return data
.stack
.addr
;
204 case kAddressKindGlobal
:
205 return data
.global
.addr
;
207 UNREACHABLE("AddressInformation kind is invalid");
209 void Print(const char *bug_descr
= nullptr) const {
211 case kAddressKindWild
:
212 Printf("Address %p is a wild pointer.\n", data
.addr
);
214 case kAddressKindShadow
:
215 return data
.shadow
.Print();
216 case kAddressKindHeap
:
217 return data
.heap
.Print();
218 case kAddressKindStack
:
219 return data
.stack
.Print();
220 case kAddressKindGlobal
:
221 // initialization-order-fiasco has a special Print()
222 return data
.global
.Print(bug_descr
);
224 UNREACHABLE("AddressInformation kind is invalid");
227 void StoreTo(AddressDescriptionData
*dst
) const { *dst
= data
; }
229 const ShadowAddressDescription
*AsShadow() const {
230 return data
.kind
== kAddressKindShadow
? &data
.shadow
: nullptr;
232 const HeapAddressDescription
*AsHeap() const {
233 return data
.kind
== kAddressKindHeap
? &data
.heap
: nullptr;
235 const StackAddressDescription
*AsStack() const {
236 return data
.kind
== kAddressKindStack
? &data
.stack
: nullptr;
238 const GlobalAddressDescription
*AsGlobal() const {
239 return data
.kind
== kAddressKindGlobal
? &data
.global
: nullptr;
243 } // namespace __asan
245 #endif // ASAN_DESCRIPTIONS_H