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