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