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;
147 // Returns true when this descriptions points inside the same global variable
148 // as other. Descriptions can have different address within the variable
149 bool PointsInsideTheSameVariable(const GlobalAddressDescription
&other
) const;
152 bool GetGlobalAddressInformation(uptr addr
, uptr access_size
,
153 GlobalAddressDescription
*descr
);
154 bool DescribeAddressIfGlobal(uptr addr
, uptr access_size
, const char *bug_type
);
156 // General function to describe an address. Will try to describe the address as
157 // a shadow, global (variable), stack, or heap address.
158 // bug_type is optional and is used for checking if we're reporting an
159 // initialization-order-fiasco
160 // The proper access_size should be passed for stack, global, and heap
161 // addresses. Defaults to 1.
162 // Each of the *AddressDescription functions has its own Print() member, which
163 // may take access_size and bug_type parameters if needed.
164 void PrintAddressDescription(uptr addr
, uptr access_size
= 1,
165 const char *bug_type
= "");
175 class AddressDescription
{
176 struct AddressDescriptionData
{
179 ShadowAddressDescription shadow
;
180 HeapAddressDescription heap
;
181 StackAddressDescription stack
;
182 GlobalAddressDescription global
;
187 AddressDescriptionData data
;
190 AddressDescription() = default;
191 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
193 AddressDescription(uptr addr
, bool shouldLockThreadRegistry
= true)
194 : AddressDescription(addr
, 1, shouldLockThreadRegistry
) {}
195 AddressDescription(uptr addr
, uptr access_size
,
196 bool shouldLockThreadRegistry
= true);
198 uptr
Address() const {
200 case kAddressKindWild
:
202 case kAddressKindShadow
:
203 return data
.shadow
.addr
;
204 case kAddressKindHeap
:
205 return data
.heap
.addr
;
206 case kAddressKindStack
:
207 return data
.stack
.addr
;
208 case kAddressKindGlobal
:
209 return data
.global
.addr
;
211 UNREACHABLE("AddressInformation kind is invalid");
213 void Print(const char *bug_descr
= nullptr) const {
215 case kAddressKindWild
:
216 Printf("Address %p is a wild pointer.\n", data
.addr
);
218 case kAddressKindShadow
:
219 return data
.shadow
.Print();
220 case kAddressKindHeap
:
221 return data
.heap
.Print();
222 case kAddressKindStack
:
223 return data
.stack
.Print();
224 case kAddressKindGlobal
:
225 // initialization-order-fiasco has a special Print()
226 return data
.global
.Print(bug_descr
);
228 UNREACHABLE("AddressInformation kind is invalid");
231 void StoreTo(AddressDescriptionData
*dst
) const { *dst
= data
; }
233 const ShadowAddressDescription
*AsShadow() const {
234 return data
.kind
== kAddressKindShadow
? &data
.shadow
: nullptr;
236 const HeapAddressDescription
*AsHeap() const {
237 return data
.kind
== kAddressKindHeap
? &data
.heap
: nullptr;
239 const StackAddressDescription
*AsStack() const {
240 return data
.kind
== kAddressKindStack
? &data
.stack
: nullptr;
242 const GlobalAddressDescription
*AsGlobal() const {
243 return data
.kind
== kAddressKindGlobal
? &data
.global
: nullptr;
247 } // namespace __asan
249 #endif // ASAN_DESCRIPTIONS_H