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]; }
41 class Decorator
: public __sanitizer::SanitizerCommonDecorator
{
43 Decorator() : SanitizerCommonDecorator() {}
44 const char *Access() { return Blue(); }
45 const char *Location() { return Green(); }
46 const char *Allocation() { return Magenta(); }
48 const char *ShadowByte(u8 byte
) {
50 case kAsanHeapLeftRedzoneMagic
:
51 case kAsanArrayCookieMagic
:
53 case kAsanHeapFreeMagic
:
55 case kAsanStackLeftRedzoneMagic
:
56 case kAsanStackMidRedzoneMagic
:
57 case kAsanStackRightRedzoneMagic
:
59 case kAsanStackAfterReturnMagic
:
61 case kAsanInitializationOrderMagic
:
63 case kAsanUserPoisonedMemoryMagic
:
64 case kAsanContiguousContainerOOBMagic
:
65 case kAsanAllocaLeftMagic
:
66 case kAsanAllocaRightMagic
:
68 case kAsanStackUseAfterScopeMagic
:
70 case kAsanGlobalRedzoneMagic
:
72 case kAsanInternalHeapMagic
:
74 case kAsanIntraObjectRedzone
:
82 enum ShadowKind
: u8
{
87 static const char *const ShadowNames
[] = {"low shadow", "shadow gap",
90 struct ShadowAddressDescription
{
98 bool GetShadowAddressInformation(uptr addr
, ShadowAddressDescription
*descr
);
99 bool DescribeAddressIfShadow(uptr addr
);
105 kAccessTypeUnknown
, // This means we have an AddressSanitizer bug!
113 u32 user_requested_alignment
: 12;
118 struct HeapAddressDescription
{
124 ChunkAccess chunk_access
;
129 bool GetHeapAddressInformation(uptr addr
, uptr access_size
,
130 HeapAddressDescription
*descr
);
131 bool DescribeAddressIfHeap(uptr addr
, uptr access_size
= 1);
133 struct StackAddressDescription
{
139 const char *frame_descr
;
144 bool GetStackAddressInformation(uptr addr
, uptr access_size
,
145 StackAddressDescription
*descr
);
147 struct WildAddressDescription
{
154 struct GlobalAddressDescription
{
156 // Assume address is close to at most four globals.
157 static const int kMaxGlobals
= 4;
158 __asan_global globals
[kMaxGlobals
];
159 u32 reg_sites
[kMaxGlobals
];
163 void Print(const char *bug_type
= "") const;
165 // Returns true when this descriptions points inside the same global variable
166 // as other. Descriptions can have different address within the variable
167 bool PointsInsideTheSameVariable(const GlobalAddressDescription
&other
) const;
170 bool GetGlobalAddressInformation(uptr addr
, uptr access_size
,
171 GlobalAddressDescription
*descr
);
172 bool DescribeAddressIfGlobal(uptr addr
, uptr access_size
, const char *bug_type
);
174 // General function to describe an address. Will try to describe the address as
175 // a shadow, global (variable), stack, or heap address.
176 // bug_type is optional and is used for checking if we're reporting an
177 // initialization-order-fiasco
178 // The proper access_size should be passed for stack, global, and heap
179 // addresses. Defaults to 1.
180 // Each of the *AddressDescription functions has its own Print() member, which
181 // may take access_size and bug_type parameters if needed.
182 void PrintAddressDescription(uptr addr
, uptr access_size
= 1,
183 const char *bug_type
= "");
193 class AddressDescription
{
194 struct AddressDescriptionData
{
197 ShadowAddressDescription shadow
;
198 HeapAddressDescription heap
;
199 StackAddressDescription stack
;
200 GlobalAddressDescription global
;
201 WildAddressDescription wild
;
205 AddressDescriptionData data
;
208 AddressDescription() = default;
209 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
211 explicit AddressDescription(uptr addr
, bool shouldLockThreadRegistry
= true)
212 : AddressDescription(addr
, 1, shouldLockThreadRegistry
) {}
213 AddressDescription(uptr addr
, uptr access_size
,
214 bool shouldLockThreadRegistry
= true);
216 uptr
Address() const {
218 case kAddressKindWild
:
219 return data
.wild
.addr
;
220 case kAddressKindShadow
:
221 return data
.shadow
.addr
;
222 case kAddressKindHeap
:
223 return data
.heap
.addr
;
224 case kAddressKindStack
:
225 return data
.stack
.addr
;
226 case kAddressKindGlobal
:
227 return data
.global
.addr
;
229 UNREACHABLE("AddressInformation kind is invalid");
231 void Print(const char *bug_descr
= nullptr) const {
233 case kAddressKindWild
:
236 case kAddressKindShadow
:
237 return data
.shadow
.Print();
238 case kAddressKindHeap
:
239 return data
.heap
.Print();
240 case kAddressKindStack
:
241 return data
.stack
.Print();
242 case kAddressKindGlobal
:
243 // initialization-order-fiasco has a special Print()
244 return data
.global
.Print(bug_descr
);
246 UNREACHABLE("AddressInformation kind is invalid");
249 void StoreTo(AddressDescriptionData
*dst
) const { *dst
= data
; }
251 const ShadowAddressDescription
*AsShadow() const {
252 return data
.kind
== kAddressKindShadow
? &data
.shadow
: nullptr;
254 const HeapAddressDescription
*AsHeap() const {
255 return data
.kind
== kAddressKindHeap
? &data
.heap
: nullptr;
257 const StackAddressDescription
*AsStack() const {
258 return data
.kind
== kAddressKindStack
? &data
.stack
: nullptr;
260 const GlobalAddressDescription
*AsGlobal() const {
261 return data
.kind
== kAddressKindGlobal
? &data
.global
: nullptr;
265 } // namespace __asan
267 #endif // ASAN_DESCRIPTIONS_H