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