1 //===-- asan_descriptions.h -------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of AddressSanitizer, an address sanity checker. 11 // 12 // ASan-private header for asan_descriptions.cc. 13 // TODO(filcab): Most struct definitions should move to the interface headers. 14 //===----------------------------------------------------------------------===// 15 #ifndef ASAN_DESCRIPTIONS_H 16 #define ASAN_DESCRIPTIONS_H 17 18 #include "asan_allocator.h" 19 #include "asan_thread.h" 20 #include "sanitizer_common/sanitizer_common.h" 21 #include "sanitizer_common/sanitizer_report_decorator.h" 22 23 namespace __asan { 24 25 void DescribeThread(AsanThreadContext *context); 26 static inline void DescribeThread(AsanThread *t) { 27 if (t) DescribeThread(t->context()); 28 } 29 30 class AsanThreadIdAndName { 31 public: 32 explicit AsanThreadIdAndName(AsanThreadContext *t); 33 explicit AsanThreadIdAndName(u32 tid); 34 35 // Contains "T%tid (%name)" or "T%tid" if the name is empty. 36 const char *c_str() const { return &name[0]; } 37 38 private: 39 void Init(u32 tid, const char *tname); 40 41 char name[128]; 42 }; 43 44 class Decorator : public __sanitizer::SanitizerCommonDecorator { 45 public: 46 Decorator() : SanitizerCommonDecorator() {} 47 const char *Access() { return Blue(); } 48 const char *Location() { return Green(); } 49 const char *Allocation() { return Magenta(); } 50 51 const char *ShadowByte(u8 byte) { 52 switch (byte) { 53 case kAsanHeapLeftRedzoneMagic: 54 case kAsanArrayCookieMagic: 55 return Red(); 56 case kAsanHeapFreeMagic: 57 return Magenta(); 58 case kAsanStackLeftRedzoneMagic: 59 case kAsanStackMidRedzoneMagic: 60 case kAsanStackRightRedzoneMagic: 61 return Red(); 62 case kAsanStackAfterReturnMagic: 63 return Magenta(); 64 case kAsanInitializationOrderMagic: 65 return Cyan(); 66 case kAsanUserPoisonedMemoryMagic: 67 case kAsanContiguousContainerOOBMagic: 68 case kAsanAllocaLeftMagic: 69 case kAsanAllocaRightMagic: 70 return Blue(); 71 case kAsanStackUseAfterScopeMagic: 72 return Magenta(); 73 case kAsanGlobalRedzoneMagic: 74 return Red(); 75 case kAsanInternalHeapMagic: 76 return Yellow(); 77 case kAsanIntraObjectRedzone: 78 return Yellow(); 79 default: 80 return Default(); 81 } 82 } 83 }; 84 85 enum ShadowKind : u8 { 86 kShadowKindLow, 87 kShadowKindGap, 88 kShadowKindHigh, 89 }; 90 static const char *const ShadowNames[] = {"low shadow", "shadow gap", 91 "high shadow"}; 92 93 struct ShadowAddressDescription { 94 uptr addr; 95 ShadowKind kind; 96 u8 shadow_byte; 97 98 void Print() const; 99 }; 100 101 bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr); 102 bool DescribeAddressIfShadow(uptr addr); 103 104 enum AccessType { 105 kAccessTypeLeft, 106 kAccessTypeRight, 107 kAccessTypeInside, 108 kAccessTypeUnknown, // This means we have an AddressSanitizer bug! 109 }; 110 111 struct ChunkAccess { 112 uptr bad_addr; 113 sptr offset; 114 uptr chunk_begin; 115 uptr chunk_size; 116 u32 user_requested_alignment : 12; 117 u32 access_type : 2; 118 u32 alloc_type : 2; 119 }; 120 121 struct HeapAddressDescription { 122 uptr addr; 123 uptr alloc_tid; 124 uptr free_tid; 125 u32 alloc_stack_id; 126 u32 free_stack_id; 127 ChunkAccess chunk_access; 128 129 void Print() const; 130 }; 131 132 bool GetHeapAddressInformation(uptr addr, uptr access_size, 133 HeapAddressDescription *descr); 134 bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1); 135 136 struct StackAddressDescription { 137 uptr addr; 138 uptr tid; 139 uptr offset; 140 uptr frame_pc; 141 uptr access_size; 142 const char *frame_descr; 143 144 void Print() const; 145 }; 146 147 bool GetStackAddressInformation(uptr addr, uptr access_size, 148 StackAddressDescription *descr); 149 150 struct GlobalAddressDescription { 151 uptr addr; 152 // Assume address is close to at most four globals. 153 static const int kMaxGlobals = 4; 154 __asan_global globals[kMaxGlobals]; 155 u32 reg_sites[kMaxGlobals]; 156 uptr access_size; 157 u8 size; 158 159 void Print(const char *bug_type = "") const; 160 161 // Returns true when this descriptions points inside the same global variable 162 // as other. Descriptions can have different address within the variable 163 bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const; 164 }; 165 166 bool GetGlobalAddressInformation(uptr addr, uptr access_size, 167 GlobalAddressDescription *descr); 168 bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type); 169 170 // General function to describe an address. Will try to describe the address as 171 // a shadow, global (variable), stack, or heap address. 172 // bug_type is optional and is used for checking if we're reporting an 173 // initialization-order-fiasco 174 // The proper access_size should be passed for stack, global, and heap 175 // addresses. Defaults to 1. 176 // Each of the *AddressDescription functions has its own Print() member, which 177 // may take access_size and bug_type parameters if needed. 178 void PrintAddressDescription(uptr addr, uptr access_size = 1, 179 const char *bug_type = ""); 180 181 enum AddressKind { 182 kAddressKindWild, 183 kAddressKindShadow, 184 kAddressKindHeap, 185 kAddressKindStack, 186 kAddressKindGlobal, 187 }; 188 189 class AddressDescription { 190 struct AddressDescriptionData { 191 AddressKind kind; 192 union { 193 ShadowAddressDescription shadow; 194 HeapAddressDescription heap; 195 StackAddressDescription stack; 196 GlobalAddressDescription global; 197 uptr addr; 198 }; 199 }; 200 201 AddressDescriptionData data; 202 203 public: 204 AddressDescription() = default; 205 // shouldLockThreadRegistry allows us to skip locking if we're sure we already 206 // have done it. 207 AddressDescription(uptr addr, bool shouldLockThreadRegistry = true) 208 : AddressDescription(addr, 1, shouldLockThreadRegistry) {} 209 AddressDescription(uptr addr, uptr access_size, 210 bool shouldLockThreadRegistry = true); 211 212 uptr Address() const { 213 switch (data.kind) { 214 case kAddressKindWild: 215 return data.addr; 216 case kAddressKindShadow: 217 return data.shadow.addr; 218 case kAddressKindHeap: 219 return data.heap.addr; 220 case kAddressKindStack: 221 return data.stack.addr; 222 case kAddressKindGlobal: 223 return data.global.addr; 224 } 225 UNREACHABLE("AddressInformation kind is invalid"); 226 } 227 void Print(const char *bug_descr = nullptr) const { 228 switch (data.kind) { 229 case kAddressKindWild: 230 Printf("Address %p is a wild pointer.\n", data.addr); 231 return; 232 case kAddressKindShadow: 233 return data.shadow.Print(); 234 case kAddressKindHeap: 235 return data.heap.Print(); 236 case kAddressKindStack: 237 return data.stack.Print(); 238 case kAddressKindGlobal: 239 // initialization-order-fiasco has a special Print() 240 return data.global.Print(bug_descr); 241 } 242 UNREACHABLE("AddressInformation kind is invalid"); 243 } 244 245 void StoreTo(AddressDescriptionData *dst) const { *dst = data; } 246 247 const ShadowAddressDescription *AsShadow() const { 248 return data.kind == kAddressKindShadow ? &data.shadow : nullptr; 249 } 250 const HeapAddressDescription *AsHeap() const { 251 return data.kind == kAddressKindHeap ? &data.heap : nullptr; 252 } 253 const StackAddressDescription *AsStack() const { 254 return data.kind == kAddressKindStack ? &data.stack : nullptr; 255 } 256 const GlobalAddressDescription *AsGlobal() const { 257 return data.kind == kAddressKindGlobal ? &data.global : nullptr; 258 } 259 }; 260 261 } // namespace __asan 262 263 #endif // ASAN_DESCRIPTIONS_H 264