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.cc.
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 GlobalAddressDescription {
151 // Assume address is close to at most four globals.
152 static const int kMaxGlobals = 4;
153 __asan_global globals[kMaxGlobals];
154 u32 reg_sites[kMaxGlobals];
158 void Print(const char *bug_type = "") const;
160 // Returns true when this descriptions points inside the same global variable
161 // as other. Descriptions can have different address within the variable
162 bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
165 bool GetGlobalAddressInformation(uptr addr, uptr access_size,
166 GlobalAddressDescription *descr);
167 bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
169 // General function to describe an address. Will try to describe the address as
170 // a shadow, global (variable), stack, or heap address.
171 // bug_type is optional and is used for checking if we're reporting an
172 // initialization-order-fiasco
173 // The proper access_size should be passed for stack, global, and heap
174 // addresses. Defaults to 1.
175 // Each of the *AddressDescription functions has its own Print() member, which
176 // may take access_size and bug_type parameters if needed.
177 void PrintAddressDescription(uptr addr, uptr access_size = 1,
178 const char *bug_type = "");
188 class AddressDescription {
189 struct AddressDescriptionData {
192 ShadowAddressDescription shadow;
193 HeapAddressDescription heap;
194 StackAddressDescription stack;
195 GlobalAddressDescription global;
200 AddressDescriptionData data;
203 AddressDescription() = default;
204 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
206 AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
207 : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
208 AddressDescription(uptr addr, uptr access_size,
209 bool shouldLockThreadRegistry = true);
211 uptr Address() const {
213 case kAddressKindWild:
215 case kAddressKindShadow:
216 return data.shadow.addr;
217 case kAddressKindHeap:
218 return data.heap.addr;
219 case kAddressKindStack:
220 return data.stack.addr;
221 case kAddressKindGlobal:
222 return data.global.addr;
224 UNREACHABLE("AddressInformation kind is invalid");
226 void Print(const char *bug_descr = nullptr) const {
228 case kAddressKindWild:
229 Printf("Address %p is a wild pointer.\n", data.addr);
231 case kAddressKindShadow:
232 return data.shadow.Print();
233 case kAddressKindHeap:
234 return data.heap.Print();
235 case kAddressKindStack:
236 return data.stack.Print();
237 case kAddressKindGlobal:
238 // initialization-order-fiasco has a special Print()
239 return data.global.Print(bug_descr);
241 UNREACHABLE("AddressInformation kind is invalid");
244 void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
246 const ShadowAddressDescription *AsShadow() const {
247 return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
249 const HeapAddressDescription *AsHeap() const {
250 return data.kind == kAddressKindHeap ? &data.heap : nullptr;
252 const StackAddressDescription *AsStack() const {
253 return data.kind == kAddressKindStack ? &data.stack : nullptr;
255 const GlobalAddressDescription *AsGlobal() const {
256 return data.kind == kAddressKindGlobal ? &data.global : nullptr;
260 } // namespace __asan
262 #endif // ASAN_DESCRIPTIONS_H