Index: lib/asan/asan_debugging.cc =================================================================== --- lib/asan/asan_debugging.cc +++ lib/asan/asan_debugging.cc @@ -28,19 +28,19 @@ descr->region_size = 0; descr->region_kind = "stack"; - uptr offset = 0; - uptr frame_pc = 0; - const char *frame_descr = t->GetFrameNameByAddr(addr, &offset, &frame_pc); + AsanThread::StackFrameAccess access; + if (!t->GetStackFrameAccessByAddr(addr, &access)) + return; InternalMmapVector vars(16); - if (!ParseFrameDescription(frame_descr, &vars)) { + if (!ParseFrameDescription(access.frame_descr, &vars)) { return; } for (uptr i = 0; i < vars.size(); i++) { - if (offset <= vars[i].beg + vars[i].size) { + if (access.offset <= vars[i].beg + vars[i].size) { internal_strncat(descr->name, vars[i].name_pos, Min(descr->name_size, vars[i].name_len)); - descr->region_address = addr - (offset - vars[i].beg); + descr->region_address = addr - (access.offset - vars[i].beg); descr->region_size = vars[i].size; return; } Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -381,9 +381,14 @@ bool ParseFrameDescription(const char *frame_descr, InternalMmapVector *vars) { + CHECK(frame_descr); char *p; + // This string is created by the compiler and has the following form: + // "n alloc_1 alloc_2 ... alloc_n" + // where alloc_i looks like "offset size len ObjectName". uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10); - CHECK_GT(n_objects, 0); + if (n_objects == 0) + return false; for (uptr i = 0; i < n_objects; i++) { uptr beg = (uptr)internal_simple_strtoll(p, &p, 10); @@ -404,31 +409,21 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) { AsanThread *t = FindThreadByStackAddress(addr); if (!t) return false; - const uptr kBufSize = 4095; - char buf[kBufSize]; - uptr offset = 0; - uptr frame_pc = 0; - char tname[128]; - const char *frame_descr = t->GetFrameNameByAddr(addr, &offset, &frame_pc); -#ifdef __powerpc64__ - // On PowerPC64, the address of a function actually points to a - // three-doubleword data structure with the first field containing - // the address of the function's code. - frame_pc = *reinterpret_cast(frame_pc); -#endif - - // This string is created by the compiler and has the following form: - // "n alloc_1 alloc_2 ... alloc_n" - // where alloc_i looks like "offset size len ObjectName ". - CHECK(frame_descr); Decorator d; + char tname[128]; Printf("%s", d.Location()); - Printf("Address %p is located in stack of thread T%d%s " - "at offset %zu in frame\n", - addr, t->tid(), - ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname)), - offset); + Printf("Address %p is located in stack of thread T%d%s", addr, t->tid(), + ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname))); + + // Try to fetch precise stack frame for this access. + AsanThread::StackFrameAccess access; + if (!t->GetStackFrameAccessByAddr(addr, &access)) { + Printf("%s\n", d.EndLocation()); + return true; + } + Printf(" at offset %zu in frame%s\n", access.offset, d.EndLocation()); + // Now we print the frame where the alloca has happened. // We print this frame as a stack trace with one element. // The symbolizer may print more than one frame if inlining was involved. @@ -437,15 +432,21 @@ // especially given that the alloca may be from entirely different place // (e.g. use-after-scope, or different thread's stack). StackTrace alloca_stack; - alloca_stack.trace[0] = frame_pc + 16; +#ifdef __powerpc64__ + // On PowerPC64, the address of a function actually points to a + // three-doubleword data structure with the first field containing + // the address of the function's code. + access.frame_pc = *reinterpret_cast(access.frame_pc); +#endif + alloca_stack.trace[0] = access.frame_pc + 16; alloca_stack.size = 1; Printf("%s", d.EndLocation()); alloca_stack.Print(); InternalMmapVector vars(16); - if (!ParseFrameDescription(frame_descr, &vars)) { + if (!ParseFrameDescription(access.frame_descr, &vars)) { Printf("AddressSanitizer can't parse the stack frame " - "descriptor: |%s|\n", frame_descr); + "descriptor: |%s|\n", access.frame_descr); // 'addr' is a stack address, so return true even if we can't parse frame return true; } @@ -454,15 +455,16 @@ Printf(" This frame has %zu object(s):\n", n_objects); // Report all objects in this frame. + const uptr kBufSize = 4095; + char buf[kBufSize]; for (uptr i = 0; i < n_objects; i++) { buf[0] = 0; internal_strncat(buf, vars[i].name_pos, static_cast(Min(kBufSize, vars[i].name_len))); uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); - PrintAccessAndVarIntersection(buf, vars[i].beg, vars[i].size, - offset, access_size, - prev_var_end, next_var_beg); + PrintAccessAndVarIntersection(buf, vars[i].beg, vars[i].size, access.offset, + access_size, prev_var_end, next_var_beg); } Printf("HINT: this may be a false positive if your program uses " "some custom stack unwind mechanism or swapcontext\n"); Index: lib/asan/asan_thread.h =================================================================== --- lib/asan/asan_thread.h +++ lib/asan/asan_thread.h @@ -71,7 +71,12 @@ AsanThreadContext *context() { return context_; } void set_context(AsanThreadContext *context) { context_ = context; } - const char *GetFrameNameByAddr(uptr addr, uptr *offset, uptr *frame_pc); + struct StackFrameAccess { + uptr offset; + uptr frame_pc; + const char *frame_descr; + }; + bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access); bool AddrIsInStack(uptr addr) { return addr >= stack_bottom_ && addr < stack_top_; Index: lib/asan/asan_thread.cc =================================================================== --- lib/asan/asan_thread.cc +++ lib/asan/asan_thread.cc @@ -198,17 +198,18 @@ PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0); } -const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset, - uptr *frame_pc) { +bool AsanThread::GetStackFrameAccessByAddr(uptr addr, + StackFrameAccess *access) { uptr bottom = 0; if (AddrIsInStack(addr)) { bottom = stack_bottom(); } else if (has_fake_stack()) { bottom = fake_stack()->AddrIsInFakeStack(addr); CHECK(bottom); - *offset = addr - bottom; - *frame_pc = ((uptr*)bottom)[2]; - return (const char *)((uptr*)bottom)[1]; + access->offset = addr - bottom; + access->frame_pc = ((uptr*)bottom)[2]; + access->frame_descr = (const char *)((uptr*)bottom)[1]; + return true; } uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr. u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); @@ -225,15 +226,15 @@ } if (shadow_ptr < shadow_bottom) { - *offset = 0; - return "UNKNOWN"; + return false; } uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); CHECK(ptr[0] == kCurrentStackFrameMagic); - *offset = addr - (uptr)ptr; - *frame_pc = ptr[2]; - return (const char*)ptr[1]; + access->offset = addr - (uptr)ptr; + access->frame_pc = ptr[2]; + access->frame_descr = (const char*)ptr[1]; + return true; } static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,