1 //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 // ASan-private header for asan_descriptions.cpp.
12 // TODO(filcab): Most struct definitions should move to the interface headers.
13 //===----------------------------------------------------------------------===//
14 #ifndef ASAN_DESCRIPTIONS_H
15 #define ASAN_DESCRIPTIONS_H
17 #include "asan_allocator.h"
18 #include "asan_thread.h"
19 #include "sanitizer_common/sanitizer_common.h"
20 #include "sanitizer_common/sanitizer_report_decorator.h"
24 void DescribeThread(AsanThreadContext
*context
);
25 static inline void DescribeThread(AsanThread
*t
) {
26 if (t
) DescribeThread(t
->context());
29 class AsanThreadIdAndName
{
31 explicit AsanThreadIdAndName(AsanThreadContext
*t
);
32 explicit AsanThreadIdAndName(u32 tid
);
34 // Contains "T%tid (%name)" or "T%tid" if the name is empty.
35 const char *c_str() const { return &name
[0]; }
38 void Init(u32 tid
, const char *tname
);
43 class Decorator
: public __sanitizer::SanitizerCommonDecorator
{
45 Decorator() : SanitizerCommonDecorator() {}
46 const char *Access() { return Blue(); }
47 const char *Location() { return Green(); }
48 const char *Allocation() { return Magenta(); }
50 const char *ShadowByte(u8 byte
) {
52 case kAsanHeapLeftRedzoneMagic
:
53 case kAsanArrayCookieMagic
:
55 case kAsanHeapFreeMagic
:
57 case kAsanStackLeftRedzoneMagic
:
58 case kAsanStackMidRedzoneMagic
:
59 case kAsanStackRightRedzoneMagic
:
61 case kAsanStackAfterReturnMagic
:
63 case kAsanInitializationOrderMagic
:
65 case kAsanUserPoisonedMemoryMagic
:
66 case kAsanContiguousContainerOOBMagic
:
67 case kAsanAllocaLeftMagic
:
68 case kAsanAllocaRightMagic
:
70 case kAsanStackUseAfterScopeMagic
:
72 case kAsanGlobalRedzoneMagic
:
74 case kAsanInternalHeapMagic
:
76 case kAsanIntraObjectRedzone
:
84 enum ShadowKind
: u8
{
89 static const char *const ShadowNames
[] = {"low shadow", "shadow gap",
92 struct ShadowAddressDescription
{
100 bool GetShadowAddressInformation(uptr addr
, ShadowAddressDescription
*descr
);
101 bool DescribeAddressIfShadow(uptr addr
);
107 kAccessTypeUnknown
, // This means we have an AddressSanitizer bug!
115 u32 user_requested_alignment
: 12;
120 struct HeapAddressDescription
{
126 ChunkAccess chunk_access
;
131 bool GetHeapAddressInformation(uptr addr
, uptr access_size
,
132 HeapAddressDescription
*descr
);
133 bool DescribeAddressIfHeap(uptr addr
, uptr access_size
= 1);
135 struct StackAddressDescription
{
141 const char *frame_descr
;
146 bool GetStackAddressInformation(uptr addr
, uptr access_size
,
147 StackAddressDescription
*descr
);
149 struct WildAddressDescription
{
156 struct GlobalAddressDescription
{
158 // Assume address is close to at most four globals.
159 static const int kMaxGlobals
= 4;
160 __asan_global globals
[kMaxGlobals
];
161 u32 reg_sites
[kMaxGlobals
];
165 void Print(const char *bug_type
= "") const;
167 // Returns true when this descriptions points inside the same global variable
168 // as other. Descriptions can have different address within the variable
169 bool PointsInsideTheSameVariable(const GlobalAddressDescription
&other
) const;
172 bool GetGlobalAddressInformation(uptr addr
, uptr access_size
,
173 GlobalAddressDescription
*descr
);
174 bool DescribeAddressIfGlobal(uptr addr
, uptr access_size
, const char *bug_type
);
176 // General function to describe an address. Will try to describe the address as
177 // a shadow, global (variable), stack, or heap address.
178 // bug_type is optional and is used for checking if we're reporting an
179 // initialization-order-fiasco
180 // The proper access_size should be passed for stack, global, and heap
181 // addresses. Defaults to 1.
182 // Each of the *AddressDescription functions has its own Print() member, which
183 // may take access_size and bug_type parameters if needed.
184 void PrintAddressDescription(uptr addr
, uptr access_size
= 1,
185 const char *bug_type
= "");
195 class AddressDescription
{
196 struct AddressDescriptionData
{
199 ShadowAddressDescription shadow
;
200 HeapAddressDescription heap
;
201 StackAddressDescription stack
;
202 GlobalAddressDescription global
;
203 WildAddressDescription wild
;
207 AddressDescriptionData data
;
210 AddressDescription() = default;
211 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
213 explicit AddressDescription(uptr addr
, bool shouldLockThreadRegistry
= true)
214 : AddressDescription(addr
, 1, shouldLockThreadRegistry
) {}
215 AddressDescription(uptr addr
, uptr access_size
,
216 bool shouldLockThreadRegistry
= true);
218 uptr
Address() const {
220 case kAddressKindWild
:
221 return data
.wild
.addr
;
222 case kAddressKindShadow
:
223 return data
.shadow
.addr
;
224 case kAddressKindHeap
:
225 return data
.heap
.addr
;
226 case kAddressKindStack
:
227 return data
.stack
.addr
;
228 case kAddressKindGlobal
:
229 return data
.global
.addr
;
231 UNREACHABLE("AddressInformation kind is invalid");
233 void Print(const char *bug_descr
= nullptr) const {
235 case kAddressKindWild
:
238 case kAddressKindShadow
:
239 return data
.shadow
.Print();
240 case kAddressKindHeap
:
241 return data
.heap
.Print();
242 case kAddressKindStack
:
243 return data
.stack
.Print();
244 case kAddressKindGlobal
:
245 // initialization-order-fiasco has a special Print()
246 return data
.global
.Print(bug_descr
);
248 UNREACHABLE("AddressInformation kind is invalid");
251 void StoreTo(AddressDescriptionData
*dst
) const { *dst
= data
; }
253 const ShadowAddressDescription
*AsShadow() const {
254 return data
.kind
== kAddressKindShadow
? &data
.shadow
: nullptr;
256 const HeapAddressDescription
*AsHeap() const {
257 return data
.kind
== kAddressKindHeap
? &data
.heap
: nullptr;
259 const StackAddressDescription
*AsStack() const {
260 return data
.kind
== kAddressKindStack
? &data
.stack
: nullptr;
262 const GlobalAddressDescription
*AsGlobal() const {
263 return data
.kind
== kAddressKindGlobal
? &data
.global
: nullptr;
267 } // namespace __asan
269 #endif // ASAN_DESCRIPTIONS_H