1 1.1 kamil //===-- asan_descriptions.cc ------------------------------------*- 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 functions for getting information about an address and/or printing it. 13 1.1 kamil //===----------------------------------------------------------------------===// 14 1.1 kamil 15 1.1 kamil #include "asan_descriptions.h" 16 1.1 kamil #include "asan_mapping.h" 17 1.1 kamil #include "asan_report.h" 18 1.1 kamil #include "asan_stack.h" 19 1.1 kamil #include "sanitizer_common/sanitizer_stackdepot.h" 20 1.1 kamil 21 1.1 kamil namespace __asan { 22 1.1 kamil 23 1.1 kamil AsanThreadIdAndName::AsanThreadIdAndName(AsanThreadContext *t) { 24 1.1 kamil Init(t->tid, t->name); 25 1.1 kamil } 26 1.1 kamil 27 1.1 kamil AsanThreadIdAndName::AsanThreadIdAndName(u32 tid) { 28 1.1 kamil if (tid == kInvalidTid) { 29 1.1 kamil Init(tid, ""); 30 1.1 kamil } else { 31 1.1 kamil asanThreadRegistry().CheckLocked(); 32 1.1 kamil AsanThreadContext *t = GetThreadContextByTidLocked(tid); 33 1.1 kamil Init(tid, t->name); 34 1.1 kamil } 35 1.1 kamil } 36 1.1 kamil 37 1.1 kamil void AsanThreadIdAndName::Init(u32 tid, const char *tname) { 38 1.1 kamil int len = internal_snprintf(name, sizeof(name), "T%d", tid); 39 1.1 kamil CHECK(((unsigned int)len) < sizeof(name)); 40 1.1 kamil if (tname[0] != '\0') 41 1.1 kamil internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname); 42 1.1 kamil } 43 1.1 kamil 44 1.1 kamil void DescribeThread(AsanThreadContext *context) { 45 1.1 kamil CHECK(context); 46 1.1 kamil asanThreadRegistry().CheckLocked(); 47 1.1 kamil // No need to announce the main thread. 48 1.1 kamil if (context->tid == 0 || context->announced) { 49 1.1 kamil return; 50 1.1 kamil } 51 1.1 kamil context->announced = true; 52 1.1 kamil InternalScopedString str(1024); 53 1.1 kamil str.append("Thread %s", AsanThreadIdAndName(context).c_str()); 54 1.1 kamil if (context->parent_tid == kInvalidTid) { 55 1.1 kamil str.append(" created by unknown thread\n"); 56 1.1 kamil Printf("%s", str.data()); 57 1.1 kamil return; 58 1.1 kamil } 59 1.1 kamil str.append(" created by %s here:\n", 60 1.1 kamil AsanThreadIdAndName(context->parent_tid).c_str()); 61 1.1 kamil Printf("%s", str.data()); 62 1.1 kamil StackDepotGet(context->stack_id).Print(); 63 1.1 kamil // Recursively described parent thread if needed. 64 1.1 kamil if (flags()->print_full_thread_history) { 65 1.1 kamil AsanThreadContext *parent_context = 66 1.1 kamil GetThreadContextByTidLocked(context->parent_tid); 67 1.1 kamil DescribeThread(parent_context); 68 1.1 kamil } 69 1.1 kamil } 70 1.1 kamil 71 1.1 kamil // Shadow descriptions 72 1.1 kamil static bool GetShadowKind(uptr addr, ShadowKind *shadow_kind) { 73 1.1 kamil CHECK(!AddrIsInMem(addr)); 74 1.1 kamil if (AddrIsInShadowGap(addr)) { 75 1.1 kamil *shadow_kind = kShadowKindGap; 76 1.1 kamil } else if (AddrIsInHighShadow(addr)) { 77 1.1 kamil *shadow_kind = kShadowKindHigh; 78 1.1 kamil } else if (AddrIsInLowShadow(addr)) { 79 1.1 kamil *shadow_kind = kShadowKindLow; 80 1.1 kamil } else { 81 1.1 kamil CHECK(0 && "Address is not in memory and not in shadow?"); 82 1.1 kamil return false; 83 1.1 kamil } 84 1.1 kamil return true; 85 1.1 kamil } 86 1.1 kamil 87 1.1 kamil bool DescribeAddressIfShadow(uptr addr) { 88 1.1 kamil ShadowAddressDescription descr; 89 1.1 kamil if (!GetShadowAddressInformation(addr, &descr)) return false; 90 1.1 kamil descr.Print(); 91 1.1 kamil return true; 92 1.1 kamil } 93 1.1 kamil 94 1.1 kamil bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr) { 95 1.1 kamil if (AddrIsInMem(addr)) return false; 96 1.1 kamil ShadowKind shadow_kind; 97 1.1 kamil if (!GetShadowKind(addr, &shadow_kind)) return false; 98 1.1 kamil if (shadow_kind != kShadowKindGap) descr->shadow_byte = *(u8 *)addr; 99 1.1 kamil descr->addr = addr; 100 1.1 kamil descr->kind = shadow_kind; 101 1.1 kamil return true; 102 1.1 kamil } 103 1.1 kamil 104 1.1 kamil // Heap descriptions 105 1.1 kamil static void GetAccessToHeapChunkInformation(ChunkAccess *descr, 106 1.1 kamil AsanChunkView chunk, uptr addr, 107 1.1 kamil uptr access_size) { 108 1.1 kamil descr->bad_addr = addr; 109 1.1 kamil if (chunk.AddrIsAtLeft(addr, access_size, &descr->offset)) { 110 1.1 kamil descr->access_type = kAccessTypeLeft; 111 1.1 kamil } else if (chunk.AddrIsAtRight(addr, access_size, &descr->offset)) { 112 1.1 kamil descr->access_type = kAccessTypeRight; 113 1.1 kamil if (descr->offset < 0) { 114 1.1 kamil descr->bad_addr -= descr->offset; 115 1.1 kamil descr->offset = 0; 116 1.1 kamil } 117 1.1 kamil } else if (chunk.AddrIsInside(addr, access_size, &descr->offset)) { 118 1.1 kamil descr->access_type = kAccessTypeInside; 119 1.1 kamil } else { 120 1.1 kamil descr->access_type = kAccessTypeUnknown; 121 1.1 kamil } 122 1.1 kamil descr->chunk_begin = chunk.Beg(); 123 1.1 kamil descr->chunk_size = chunk.UsedSize(); 124 1.1 kamil descr->user_requested_alignment = chunk.UserRequestedAlignment(); 125 1.1 kamil descr->alloc_type = chunk.GetAllocType(); 126 1.1 kamil } 127 1.1 kamil 128 1.1 kamil static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) { 129 1.1 kamil Decorator d; 130 1.1 kamil InternalScopedString str(4096); 131 1.1 kamil str.append("%s", d.Location()); 132 1.1 kamil switch (descr.access_type) { 133 1.1 kamil case kAccessTypeLeft: 134 1.1 kamil str.append("%p is located %zd bytes to the left of", 135 1.1 kamil (void *)descr.bad_addr, descr.offset); 136 1.1 kamil break; 137 1.1 kamil case kAccessTypeRight: 138 1.1 kamil str.append("%p is located %zd bytes to the right of", 139 1.1 kamil (void *)descr.bad_addr, descr.offset); 140 1.1 kamil break; 141 1.1 kamil case kAccessTypeInside: 142 1.1 kamil str.append("%p is located %zd bytes inside of", (void *)descr.bad_addr, 143 1.1 kamil descr.offset); 144 1.1 kamil break; 145 1.1 kamil case kAccessTypeUnknown: 146 1.1 kamil str.append( 147 1.1 kamil "%p is located somewhere around (this is AddressSanitizer bug!)", 148 1.1 kamil (void *)descr.bad_addr); 149 1.1 kamil } 150 1.1 kamil str.append(" %zu-byte region [%p,%p)\n", descr.chunk_size, 151 1.1 kamil (void *)descr.chunk_begin, 152 1.1 kamil (void *)(descr.chunk_begin + descr.chunk_size)); 153 1.1 kamil str.append("%s", d.Default()); 154 1.1 kamil Printf("%s", str.data()); 155 1.1 kamil } 156 1.1 kamil 157 1.1 kamil bool GetHeapAddressInformation(uptr addr, uptr access_size, 158 1.1 kamil HeapAddressDescription *descr) { 159 1.1 kamil AsanChunkView chunk = FindHeapChunkByAddress(addr); 160 1.1 kamil if (!chunk.IsValid()) { 161 1.1 kamil return false; 162 1.1 kamil } 163 1.1 kamil descr->addr = addr; 164 1.1 kamil GetAccessToHeapChunkInformation(&descr->chunk_access, chunk, addr, 165 1.1 kamil access_size); 166 1.1 kamil CHECK_NE(chunk.AllocTid(), kInvalidTid); 167 1.1 kamil descr->alloc_tid = chunk.AllocTid(); 168 1.1 kamil descr->alloc_stack_id = chunk.GetAllocStackId(); 169 1.1 kamil descr->free_tid = chunk.FreeTid(); 170 1.1 kamil if (descr->free_tid != kInvalidTid) 171 1.1 kamil descr->free_stack_id = chunk.GetFreeStackId(); 172 1.1 kamil return true; 173 1.1 kamil } 174 1.1 kamil 175 1.1 kamil static StackTrace GetStackTraceFromId(u32 id) { 176 1.1 kamil CHECK(id); 177 1.1 kamil StackTrace res = StackDepotGet(id); 178 1.1 kamil CHECK(res.trace); 179 1.1 kamil return res; 180 1.1 kamil } 181 1.1 kamil 182 1.1 kamil bool DescribeAddressIfHeap(uptr addr, uptr access_size) { 183 1.1 kamil HeapAddressDescription descr; 184 1.1 kamil if (!GetHeapAddressInformation(addr, access_size, &descr)) { 185 1.1 kamil Printf( 186 1.1 kamil "AddressSanitizer can not describe address in more detail " 187 1.1 kamil "(wild memory access suspected).\n"); 188 1.1 kamil return false; 189 1.1 kamil } 190 1.1 kamil descr.Print(); 191 1.1 kamil return true; 192 1.1 kamil } 193 1.1 kamil 194 1.1 kamil // Stack descriptions 195 1.1 kamil bool GetStackAddressInformation(uptr addr, uptr access_size, 196 1.1 kamil StackAddressDescription *descr) { 197 1.1 kamil AsanThread *t = FindThreadByStackAddress(addr); 198 1.1 kamil if (!t) return false; 199 1.1 kamil 200 1.1 kamil descr->addr = addr; 201 1.1 kamil descr->tid = t->tid(); 202 1.1 kamil // Try to fetch precise stack frame for this access. 203 1.1 kamil AsanThread::StackFrameAccess access; 204 1.1 kamil if (!t->GetStackFrameAccessByAddr(addr, &access)) { 205 1.1 kamil descr->frame_descr = nullptr; 206 1.1 kamil return true; 207 1.1 kamil } 208 1.1 kamil 209 1.1 kamil descr->offset = access.offset; 210 1.1 kamil descr->access_size = access_size; 211 1.1 kamil descr->frame_pc = access.frame_pc; 212 1.1 kamil descr->frame_descr = access.frame_descr; 213 1.1 kamil 214 1.1 kamil #if SANITIZER_PPC64V1 215 1.1 kamil // On PowerPC64 ELFv1, the address of a function actually points to a 216 1.1 kamil // three-doubleword data structure with the first field containing 217 1.1 kamil // the address of the function's code. 218 1.1 kamil descr->frame_pc = *reinterpret_cast<uptr *>(descr->frame_pc); 219 1.1 kamil #endif 220 1.1 kamil descr->frame_pc += 16; 221 1.1 kamil 222 1.1 kamil return true; 223 1.1 kamil } 224 1.1 kamil 225 1.1 kamil static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr, 226 1.1 kamil uptr access_size, uptr prev_var_end, 227 1.1 kamil uptr next_var_beg) { 228 1.1 kamil uptr var_end = var.beg + var.size; 229 1.1 kamil uptr addr_end = addr + access_size; 230 1.1 kamil const char *pos_descr = nullptr; 231 1.1 kamil // If the variable [var.beg, var_end) is the nearest variable to the 232 1.1 kamil // current memory access, indicate it in the log. 233 1.1 kamil if (addr >= var.beg) { 234 1.1 kamil if (addr_end <= var_end) 235 1.1 kamil pos_descr = "is inside"; // May happen if this is a use-after-return. 236 1.1 kamil else if (addr < var_end) 237 1.1 kamil pos_descr = "partially overflows"; 238 1.1 kamil else if (addr_end <= next_var_beg && 239 1.1 kamil next_var_beg - addr_end >= addr - var_end) 240 1.1 kamil pos_descr = "overflows"; 241 1.1 kamil } else { 242 1.1 kamil if (addr_end > var.beg) 243 1.1 kamil pos_descr = "partially underflows"; 244 1.1 kamil else if (addr >= prev_var_end && addr - prev_var_end >= var.beg - addr_end) 245 1.1 kamil pos_descr = "underflows"; 246 1.1 kamil } 247 1.1 kamil InternalScopedString str(1024); 248 1.1 kamil str.append(" [%zd, %zd)", var.beg, var_end); 249 1.1 kamil // Render variable name. 250 1.1 kamil str.append(" '"); 251 1.1 kamil for (uptr i = 0; i < var.name_len; ++i) { 252 1.1 kamil str.append("%c", var.name_pos[i]); 253 1.1 kamil } 254 1.1 kamil str.append("'"); 255 1.1 kamil if (var.line > 0) { 256 1.1 kamil str.append(" (line %d)", var.line); 257 1.1 kamil } 258 1.1 kamil if (pos_descr) { 259 1.1 kamil Decorator d; 260 1.1 kamil // FIXME: we may want to also print the size of the access here, 261 1.1 kamil // but in case of accesses generated by memset it may be confusing. 262 1.1 kamil str.append("%s <== Memory access at offset %zd %s this variable%s\n", 263 1.1 kamil d.Location(), addr, pos_descr, d.Default()); 264 1.1 kamil } else { 265 1.1 kamil str.append("\n"); 266 1.1 kamil } 267 1.1 kamil Printf("%s", str.data()); 268 1.1 kamil } 269 1.1 kamil 270 1.1 kamil bool DescribeAddressIfStack(uptr addr, uptr access_size) { 271 1.1 kamil StackAddressDescription descr; 272 1.1 kamil if (!GetStackAddressInformation(addr, access_size, &descr)) return false; 273 1.1 kamil descr.Print(); 274 1.1 kamil return true; 275 1.1 kamil } 276 1.1 kamil 277 1.1 kamil // Global descriptions 278 1.1 kamil static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size, 279 1.1 kamil const __asan_global &g) { 280 1.1 kamil InternalScopedString str(4096); 281 1.1 kamil Decorator d; 282 1.1 kamil str.append("%s", d.Location()); 283 1.1 kamil if (addr < g.beg) { 284 1.1 kamil str.append("%p is located %zd bytes to the left", (void *)addr, 285 1.1 kamil g.beg - addr); 286 1.1 kamil } else if (addr + access_size > g.beg + g.size) { 287 1.1 kamil if (addr < g.beg + g.size) addr = g.beg + g.size; 288 1.1 kamil str.append("%p is located %zd bytes to the right", (void *)addr, 289 1.1 kamil addr - (g.beg + g.size)); 290 1.1 kamil } else { 291 1.1 kamil // Can it happen? 292 1.1 kamil str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg); 293 1.1 kamil } 294 1.1 kamil str.append(" of global variable '%s' defined in '", 295 1.1 kamil MaybeDemangleGlobalName(g.name)); 296 1.1 kamil PrintGlobalLocation(&str, g); 297 1.1 kamil str.append("' (0x%zx) of size %zu\n", g.beg, g.size); 298 1.1 kamil str.append("%s", d.Default()); 299 1.1 kamil PrintGlobalNameIfASCII(&str, g); 300 1.1 kamil Printf("%s", str.data()); 301 1.1 kamil } 302 1.1 kamil 303 1.1 kamil bool GetGlobalAddressInformation(uptr addr, uptr access_size, 304 1.1 kamil GlobalAddressDescription *descr) { 305 1.1 kamil descr->addr = addr; 306 1.1 kamil int globals_num = GetGlobalsForAddress(addr, descr->globals, descr->reg_sites, 307 1.1 kamil ARRAY_SIZE(descr->globals)); 308 1.1 kamil descr->size = globals_num; 309 1.1 kamil descr->access_size = access_size; 310 1.1 kamil return globals_num != 0; 311 1.1 kamil } 312 1.1 kamil 313 1.1 kamil bool DescribeAddressIfGlobal(uptr addr, uptr access_size, 314 1.1 kamil const char *bug_type) { 315 1.1 kamil GlobalAddressDescription descr; 316 1.1 kamil if (!GetGlobalAddressInformation(addr, access_size, &descr)) return false; 317 1.1 kamil 318 1.1 kamil descr.Print(bug_type); 319 1.1 kamil return true; 320 1.1 kamil } 321 1.1 kamil 322 1.1 kamil void ShadowAddressDescription::Print() const { 323 1.1 kamil Printf("Address %p is located in the %s area.\n", addr, ShadowNames[kind]); 324 1.1 kamil } 325 1.1 kamil 326 1.1 kamil void GlobalAddressDescription::Print(const char *bug_type) const { 327 1.1 kamil for (int i = 0; i < size; i++) { 328 1.1 kamil DescribeAddressRelativeToGlobal(addr, access_size, globals[i]); 329 1.1 kamil if (bug_type && 330 1.1 kamil 0 == internal_strcmp(bug_type, "initialization-order-fiasco") && 331 1.1 kamil reg_sites[i]) { 332 1.1 kamil Printf(" registered at:\n"); 333 1.1 kamil StackDepotGet(reg_sites[i]).Print(); 334 1.1 kamil } 335 1.1 kamil } 336 1.1 kamil } 337 1.1 kamil 338 1.1 kamil bool GlobalAddressDescription::PointsInsideTheSameVariable( 339 1.1 kamil const GlobalAddressDescription &other) const { 340 1.1 kamil if (size == 0 || other.size == 0) return false; 341 1.1 kamil 342 1.1 kamil for (uptr i = 0; i < size; i++) { 343 1.1 kamil const __asan_global &a = globals[i]; 344 1.1 kamil for (uptr j = 0; j < other.size; j++) { 345 1.1 kamil const __asan_global &b = other.globals[j]; 346 1.1 kamil if (a.beg == b.beg && 347 1.1 kamil a.beg <= addr && 348 1.1 kamil b.beg <= other.addr && 349 1.1 kamil (addr + access_size) < (a.beg + a.size) && 350 1.1 kamil (other.addr + other.access_size) < (b.beg + b.size)) 351 1.1 kamil return true; 352 1.1 kamil } 353 1.1 kamil } 354 1.1 kamil 355 1.1 kamil return false; 356 1.1 kamil } 357 1.1 kamil 358 1.1 kamil void StackAddressDescription::Print() const { 359 1.1 kamil Decorator d; 360 1.1 kamil Printf("%s", d.Location()); 361 1.1 kamil Printf("Address %p is located in stack of thread %s", addr, 362 1.1 kamil AsanThreadIdAndName(tid).c_str()); 363 1.1 kamil 364 1.1 kamil if (!frame_descr) { 365 1.1 kamil Printf("%s\n", d.Default()); 366 1.1 kamil return; 367 1.1 kamil } 368 1.1 kamil Printf(" at offset %zu in frame%s\n", offset, d.Default()); 369 1.1 kamil 370 1.1 kamil // Now we print the frame where the alloca has happened. 371 1.1 kamil // We print this frame as a stack trace with one element. 372 1.1 kamil // The symbolizer may print more than one frame if inlining was involved. 373 1.1 kamil // The frame numbers may be different than those in the stack trace printed 374 1.1 kamil // previously. That's unfortunate, but I have no better solution, 375 1.1 kamil // especially given that the alloca may be from entirely different place 376 1.1 kamil // (e.g. use-after-scope, or different thread's stack). 377 1.1 kamil Printf("%s", d.Default()); 378 1.1 kamil StackTrace alloca_stack(&frame_pc, 1); 379 1.1 kamil alloca_stack.Print(); 380 1.1 kamil 381 1.1 kamil InternalMmapVector<StackVarDescr> vars; 382 1.1 kamil vars.reserve(16); 383 1.1 kamil if (!ParseFrameDescription(frame_descr, &vars)) { 384 1.1 kamil Printf( 385 1.1 kamil "AddressSanitizer can't parse the stack frame " 386 1.1 kamil "descriptor: |%s|\n", 387 1.1 kamil frame_descr); 388 1.1 kamil // 'addr' is a stack address, so return true even if we can't parse frame 389 1.1 kamil return; 390 1.1 kamil } 391 1.1 kamil uptr n_objects = vars.size(); 392 1.1 kamil // Report the number of stack objects. 393 1.1 kamil Printf(" This frame has %zu object(s):\n", n_objects); 394 1.1 kamil 395 1.1 kamil // Report all objects in this frame. 396 1.1 kamil for (uptr i = 0; i < n_objects; i++) { 397 1.1 kamil uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; 398 1.1 kamil uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); 399 1.1 kamil PrintAccessAndVarIntersection(vars[i], offset, access_size, prev_var_end, 400 1.1 kamil next_var_beg); 401 1.1 kamil } 402 1.1 kamil Printf( 403 1.1 kamil "HINT: this may be a false positive if your program uses " 404 1.1 kamil "some custom stack unwind mechanism, swapcontext or vfork\n"); 405 1.1 kamil if (SANITIZER_WINDOWS) 406 1.1 kamil Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n"); 407 1.1 kamil else 408 1.1 kamil Printf(" (longjmp and C++ exceptions *are* supported)\n"); 409 1.1 kamil 410 1.1 kamil DescribeThread(GetThreadContextByTidLocked(tid)); 411 1.1 kamil } 412 1.1 kamil 413 1.1 kamil void HeapAddressDescription::Print() const { 414 1.1 kamil PrintHeapChunkAccess(addr, chunk_access); 415 1.1 kamil 416 1.1 kamil asanThreadRegistry().CheckLocked(); 417 1.1 kamil AsanThreadContext *alloc_thread = GetThreadContextByTidLocked(alloc_tid); 418 1.1 kamil StackTrace alloc_stack = GetStackTraceFromId(alloc_stack_id); 419 1.1 kamil 420 1.1 kamil Decorator d; 421 1.1 kamil AsanThreadContext *free_thread = nullptr; 422 1.1 kamil if (free_tid != kInvalidTid) { 423 1.1 kamil free_thread = GetThreadContextByTidLocked(free_tid); 424 1.1 kamil Printf("%sfreed by thread %s here:%s\n", d.Allocation(), 425 1.1 kamil AsanThreadIdAndName(free_thread).c_str(), d.Default()); 426 1.1 kamil StackTrace free_stack = GetStackTraceFromId(free_stack_id); 427 1.1 kamil free_stack.Print(); 428 1.1 kamil Printf("%spreviously allocated by thread %s here:%s\n", d.Allocation(), 429 1.1 kamil AsanThreadIdAndName(alloc_thread).c_str(), d.Default()); 430 1.1 kamil } else { 431 1.1 kamil Printf("%sallocated by thread %s here:%s\n", d.Allocation(), 432 1.1 kamil AsanThreadIdAndName(alloc_thread).c_str(), d.Default()); 433 1.1 kamil } 434 1.1 kamil alloc_stack.Print(); 435 1.1 kamil DescribeThread(GetCurrentThread()); 436 1.1 kamil if (free_thread) DescribeThread(free_thread); 437 1.1 kamil DescribeThread(alloc_thread); 438 1.1 kamil } 439 1.1 kamil 440 1.1 kamil AddressDescription::AddressDescription(uptr addr, uptr access_size, 441 1.1 kamil bool shouldLockThreadRegistry) { 442 1.1 kamil if (GetShadowAddressInformation(addr, &data.shadow)) { 443 1.1 kamil data.kind = kAddressKindShadow; 444 1.1 kamil return; 445 1.1 kamil } 446 1.1 kamil if (GetHeapAddressInformation(addr, access_size, &data.heap)) { 447 1.1 kamil data.kind = kAddressKindHeap; 448 1.1 kamil return; 449 1.1 kamil } 450 1.1 kamil 451 1.1 kamil bool isStackMemory = false; 452 1.1 kamil if (shouldLockThreadRegistry) { 453 1.1 kamil ThreadRegistryLock l(&asanThreadRegistry()); 454 1.1 kamil isStackMemory = GetStackAddressInformation(addr, access_size, &data.stack); 455 1.1 kamil } else { 456 1.1 kamil isStackMemory = GetStackAddressInformation(addr, access_size, &data.stack); 457 1.1 kamil } 458 1.1 kamil if (isStackMemory) { 459 1.1 kamil data.kind = kAddressKindStack; 460 1.1 kamil return; 461 1.1 kamil } 462 1.1 kamil 463 1.1 kamil if (GetGlobalAddressInformation(addr, access_size, &data.global)) { 464 1.1 kamil data.kind = kAddressKindGlobal; 465 1.1 kamil return; 466 1.1 kamil } 467 1.1 kamil data.kind = kAddressKindWild; 468 1.1 kamil addr = 0; 469 1.1 kamil } 470 1.1 kamil 471 1.1 kamil void PrintAddressDescription(uptr addr, uptr access_size, 472 1.1 kamil const char *bug_type) { 473 1.1 kamil ShadowAddressDescription shadow_descr; 474 1.1 kamil if (GetShadowAddressInformation(addr, &shadow_descr)) { 475 1.1 kamil shadow_descr.Print(); 476 1.1 kamil return; 477 1.1 kamil } 478 1.1 kamil 479 1.1 kamil GlobalAddressDescription global_descr; 480 1.1 kamil if (GetGlobalAddressInformation(addr, access_size, &global_descr)) { 481 1.1 kamil global_descr.Print(bug_type); 482 1.1 kamil return; 483 1.1 kamil } 484 1.1 kamil 485 1.1 kamil StackAddressDescription stack_descr; 486 1.1 kamil if (GetStackAddressInformation(addr, access_size, &stack_descr)) { 487 1.1 kamil stack_descr.Print(); 488 1.1 kamil return; 489 1.1 kamil } 490 1.1 kamil 491 1.1 kamil HeapAddressDescription heap_descr; 492 1.1 kamil if (GetHeapAddressInformation(addr, access_size, &heap_descr)) { 493 1.1 kamil heap_descr.Print(); 494 1.1 kamil return; 495 1.1 kamil } 496 1.1 kamil 497 1.1 kamil // We exhausted our possibilities. Bail out. 498 1.1 kamil Printf( 499 1.1 kamil "AddressSanitizer can not describe address in more detail " 500 1.1 kamil "(wild memory access suspected).\n"); 501 1.1 kamil } 502 1.1 kamil } // namespace __asan 503