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. 10// 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 16 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" 21 22namespace __asan { 23 24void DescribeThread(AsanThreadContext *context); 25static inline void DescribeThread(AsanThread *t) { 26 if (t) DescribeThread(t->context()); 27} 28 29class AsanThreadIdAndName { 30 public: 31 explicit AsanThreadIdAndName(AsanThreadContext *t); 32 explicit AsanThreadIdAndName(u32 tid); 33 34 // Contains "T%tid (%name)" or "T%tid" if the name is empty. 35 const char *c_str() const { return &name[0]; } 36 37 private: 38 void Init(u32 tid, const char *tname); 39 40 char name[128]; 41}; 42 43class Decorator : public __sanitizer::SanitizerCommonDecorator { 44 public: 45 Decorator() : SanitizerCommonDecorator() {} 46 const char *Access() { return Blue(); } 47 const char *Location() { return Green(); } 48 const char *Allocation() { return Magenta(); } 49 50 const char *ShadowByte(u8 byte) { 51 switch (byte) { 52 case kAsanHeapLeftRedzoneMagic: 53 case kAsanArrayCookieMagic: 54 return Red(); 55 case kAsanHeapFreeMagic: 56 return Magenta(); 57 case kAsanStackLeftRedzoneMagic: 58 case kAsanStackMidRedzoneMagic: 59 case kAsanStackRightRedzoneMagic: 60 return Red(); 61 case kAsanStackAfterReturnMagic: 62 return Magenta(); 63 case kAsanInitializationOrderMagic: 64 return Cyan(); 65 case kAsanUserPoisonedMemoryMagic: 66 case kAsanContiguousContainerOOBMagic: 67 case kAsanAllocaLeftMagic: 68 case kAsanAllocaRightMagic: 69 return Blue(); 70 case kAsanStackUseAfterScopeMagic: 71 return Magenta(); 72 case kAsanGlobalRedzoneMagic: 73 return Red(); 74 case kAsanInternalHeapMagic: 75 return Yellow(); 76 case kAsanIntraObjectRedzone: 77 return Yellow(); 78 default: 79 return Default(); 80 } 81 } 82}; 83 84enum ShadowKind : u8 { 85 kShadowKindLow, 86 kShadowKindGap, 87 kShadowKindHigh, 88}; 89static const char *const ShadowNames[] = {"low shadow", "shadow gap", 90 "high shadow"}; 91 92struct ShadowAddressDescription { 93 uptr addr; 94 ShadowKind kind; 95 u8 shadow_byte; 96 97 void Print() const; 98}; 99 100bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr); 101bool DescribeAddressIfShadow(uptr addr); 102 103enum AccessType { 104 kAccessTypeLeft, 105 kAccessTypeRight, 106 kAccessTypeInside, 107 kAccessTypeUnknown, // This means we have an AddressSanitizer bug! 108}; 109 110struct ChunkAccess { 111 uptr bad_addr; 112 sptr offset; 113 uptr chunk_begin; 114 uptr chunk_size; 115 u32 user_requested_alignment : 12; 116 u32 access_type : 2; 117 u32 alloc_type : 2; 118}; 119 120struct HeapAddressDescription { 121 uptr addr; 122 uptr alloc_tid; 123 uptr free_tid; 124 u32 alloc_stack_id; 125 u32 free_stack_id; 126 ChunkAccess chunk_access; 127 128 void Print() const; 129}; 130 131bool GetHeapAddressInformation(uptr addr, uptr access_size, 132 HeapAddressDescription *descr); 133bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1); 134 135struct StackAddressDescription { 136 uptr addr; 137 uptr tid; 138 uptr offset; 139 uptr frame_pc; 140 uptr access_size; 141 const char *frame_descr; 142 143 void Print() const; 144}; 145 146bool GetStackAddressInformation(uptr addr, uptr access_size, 147 StackAddressDescription *descr); 148 149struct WildAddressDescription { 150 uptr addr; 151 uptr access_size; 152 153 void Print() const; 154}; 155 156struct GlobalAddressDescription { 157 uptr addr; 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]; 162 uptr access_size; 163 u8 size; 164 165 void Print(const char *bug_type = "") const; 166 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; 170}; 171 172bool GetGlobalAddressInformation(uptr addr, uptr access_size, 173 GlobalAddressDescription *descr); 174bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type); 175 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. 184void PrintAddressDescription(uptr addr, uptr access_size = 1, 185 const char *bug_type = ""); 186 187enum AddressKind { 188 kAddressKindWild, 189 kAddressKindShadow, 190 kAddressKindHeap, 191 kAddressKindStack, 192 kAddressKindGlobal, 193}; 194 195class AddressDescription { 196 struct AddressDescriptionData { 197 AddressKind kind; 198 union { 199 ShadowAddressDescription shadow; 200 HeapAddressDescription heap; 201 StackAddressDescription stack; 202 GlobalAddressDescription global; 203 WildAddressDescription wild; 204 }; 205 }; 206 207 AddressDescriptionData data; 208 209 public: 210 AddressDescription() = default; 211 // shouldLockThreadRegistry allows us to skip locking if we're sure we already 212 // have done it. 213 explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true) 214 : AddressDescription(addr, 1, shouldLockThreadRegistry) {} 215 AddressDescription(uptr addr, uptr access_size, 216 bool shouldLockThreadRegistry = true); 217 218 uptr Address() const { 219 switch (data.kind) { 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; 230 } 231 UNREACHABLE("AddressInformation kind is invalid"); 232 } 233 void Print(const char *bug_descr = nullptr) const { 234 switch (data.kind) { 235 case kAddressKindWild: 236 data.wild.Print(); 237 return; 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); 247 } 248 UNREACHABLE("AddressInformation kind is invalid"); 249 } 250 251 void StoreTo(AddressDescriptionData *dst) const { *dst = data; } 252 253 const ShadowAddressDescription *AsShadow() const { 254 return data.kind == kAddressKindShadow ? &data.shadow : nullptr; 255 } 256 const HeapAddressDescription *AsHeap() const { 257 return data.kind == kAddressKindHeap ? &data.heap : nullptr; 258 } 259 const StackAddressDescription *AsStack() const { 260 return data.kind == kAddressKindStack ? &data.stack : nullptr; 261 } 262 const GlobalAddressDescription *AsGlobal() const { 263 return data.kind == kAddressKindGlobal ? &data.global : nullptr; 264 } 265}; 266 267} // namespace __asan 268 269#endif // ASAN_DESCRIPTIONS_H 270