[LV] Remove hard-coded VPValue numbers in test check lines. (NFC)
[llvm-project.git] / compiler-rt / lib / asan / asan_descriptions.h
bloba614f47d461bbdd9291b3c9bb25a48c30d0474fb
1 //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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"
22 namespace __asan {
24 void DescribeThread(AsanThreadContext *context);
25 static inline void DescribeThread(AsanThread *t) {
26 if (t) DescribeThread(t->context());
29 class AsanThreadIdAndName {
30 public:
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]; }
37 private:
38 char name[128];
41 class Decorator : public __sanitizer::SanitizerCommonDecorator {
42 public:
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) {
49 switch (byte) {
50 case kAsanHeapLeftRedzoneMagic:
51 case kAsanArrayCookieMagic:
52 return Red();
53 case kAsanHeapFreeMagic:
54 return Magenta();
55 case kAsanStackLeftRedzoneMagic:
56 case kAsanStackMidRedzoneMagic:
57 case kAsanStackRightRedzoneMagic:
58 return Red();
59 case kAsanStackAfterReturnMagic:
60 return Magenta();
61 case kAsanInitializationOrderMagic:
62 return Cyan();
63 case kAsanUserPoisonedMemoryMagic:
64 case kAsanContiguousContainerOOBMagic:
65 case kAsanAllocaLeftMagic:
66 case kAsanAllocaRightMagic:
67 return Blue();
68 case kAsanStackUseAfterScopeMagic:
69 return Magenta();
70 case kAsanGlobalRedzoneMagic:
71 return Red();
72 case kAsanInternalHeapMagic:
73 return Yellow();
74 case kAsanIntraObjectRedzone:
75 return Yellow();
76 default:
77 return Default();
82 enum ShadowKind : u8 {
83 kShadowKindLow,
84 kShadowKindGap,
85 kShadowKindHigh,
87 static const char *const ShadowNames[] = {"low shadow", "shadow gap",
88 "high shadow"};
90 struct ShadowAddressDescription {
91 uptr addr;
92 ShadowKind kind;
93 u8 shadow_byte;
95 void Print() const;
98 bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
99 bool DescribeAddressIfShadow(uptr addr);
101 enum AccessType {
102 kAccessTypeLeft,
103 kAccessTypeRight,
104 kAccessTypeInside,
105 kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
108 struct ChunkAccess {
109 uptr bad_addr;
110 sptr offset;
111 uptr chunk_begin;
112 uptr chunk_size;
113 u32 user_requested_alignment : 12;
114 u32 access_type : 2;
115 u32 alloc_type : 2;
118 struct HeapAddressDescription {
119 uptr addr;
120 uptr alloc_tid;
121 uptr free_tid;
122 u32 alloc_stack_id;
123 u32 free_stack_id;
124 ChunkAccess chunk_access;
126 void Print() const;
129 bool GetHeapAddressInformation(uptr addr, uptr access_size,
130 HeapAddressDescription *descr);
131 bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
133 struct StackAddressDescription {
134 uptr addr;
135 uptr tid;
136 uptr offset;
137 uptr frame_pc;
138 uptr access_size;
139 const char *frame_descr;
141 void Print() const;
144 bool GetStackAddressInformation(uptr addr, uptr access_size,
145 StackAddressDescription *descr);
147 struct WildAddressDescription {
148 uptr addr;
149 uptr access_size;
151 void Print() const;
154 struct GlobalAddressDescription {
155 uptr addr;
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];
160 uptr access_size;
161 u8 size;
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 = "");
185 enum AddressKind {
186 kAddressKindWild,
187 kAddressKindShadow,
188 kAddressKindHeap,
189 kAddressKindStack,
190 kAddressKindGlobal,
193 class AddressDescription {
194 struct AddressDescriptionData {
195 AddressKind kind;
196 union {
197 ShadowAddressDescription shadow;
198 HeapAddressDescription heap;
199 StackAddressDescription stack;
200 GlobalAddressDescription global;
201 WildAddressDescription wild;
205 AddressDescriptionData data;
207 public:
208 AddressDescription() = default;
209 // shouldLockThreadRegistry allows us to skip locking if we're sure we already
210 // have done it.
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 {
217 switch (data.kind) {
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 {
232 switch (data.kind) {
233 case kAddressKindWild:
234 data.wild.Print();
235 return;
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