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