Index: lib/asan/asan_debugging.cc =================================================================== --- lib/asan/asan_debugging.cc +++ lib/asan/asan_debugging.cc @@ -24,8 +24,9 @@ namespace { using namespace __asan; -void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset, - AddressDescription *descr) { +static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset, + char *name, uptr name_size, + uptr ®ion_address, uptr ®ion_size) { InternalMmapVector vars(16); if (!ParseFrameDescription(frame_descr, &vars)) { return; @@ -36,62 +37,15 @@ // We use name_len + 1 because strlcpy will guarantee a \0 at the end, so // if we're limiting the copy due to name_len, we add 1 to ensure we copy // the whole name and then terminate with '\0'. - internal_strlcpy(descr->name, vars[i].name_pos, - Min(descr->name_size, vars[i].name_len + 1)); - descr->region_address = addr - (offset - vars[i].beg); - descr->region_size = vars[i].size; + internal_strlcpy(name, vars[i].name_pos, + Min(name_size, vars[i].name_len + 1)); + region_address = addr - (offset - vars[i].beg); + region_size = vars[i].size; return; } } } -void AsanLocateAddress(uptr addr, AddressDescription *descr) { - ShadowAddressDescription shadow_descr; - if (GetShadowAddressInformation(addr, &shadow_descr)) { - descr->region_kind = ShadowNames[shadow_descr.kind]; - return; - } - GlobalAddressDescription global_descr; - if (GetGlobalAddressInformation(addr, &global_descr)) { - descr->region_kind = "global"; - auto &g = global_descr.globals[0]; - internal_strlcpy(descr->name, g.name, descr->name_size); - descr->region_address = g.beg; - descr->region_size = g.size; - return; - } - - StackAddressDescription stack_descr; - asanThreadRegistry().Lock(); - if (GetStackAddressInformation(addr, &stack_descr)) { - asanThreadRegistry().Unlock(); - descr->region_kind = "stack"; - if (!stack_descr.frame_descr) { - descr->name[0] = 0; - descr->region_address = 0; - descr->region_size = 0; - } else { - FindInfoForStackVar(addr, stack_descr.frame_descr, stack_descr.offset, - descr); - } - return; - } - asanThreadRegistry().Unlock(); - - descr->name[0] = 0; - HeapAddressDescription heap_descr; - if (GetHeapAddressInformation(addr, 1, &heap_descr)) { - descr->region_address = heap_descr.chunk_access.chunk_begin; - descr->region_size = heap_descr.chunk_access.chunk_size; - descr->region_kind = "heap"; - return; - } - - descr->region_address = 0; - descr->region_size = 0; - descr->region_kind = "heap-invalid"; -} - uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id, bool alloc_stack) { AsanChunkView chunk = FindHeapChunkByAddress(addr); @@ -123,12 +77,54 @@ SANITIZER_INTERFACE_ATTRIBUTE const char *__asan_locate_address(uptr addr, char *name, uptr name_size, - uptr *region_address, uptr *region_size) { - AddressDescription descr = { name, name_size, 0, 0, nullptr }; - AsanLocateAddress(addr, &descr); - if (region_address) *region_address = descr.region_address; - if (region_size) *region_size = descr.region_size; - return descr.region_kind; + uptr *region_address_ptr, + uptr *region_size_ptr) { + AddressDescription descr(addr); + uptr region_address = 0; + uptr region_size = 0; + const char *region_kind = nullptr; + if (name && name_size > 0) name[0] = 0; + + if (auto shadow = descr.AsShadow()) { + // region_{address,size} are already 0 + switch (shadow->kind) { + case kShadowKindLow: + region_kind = "low shadow"; + break; + case kShadowKindGap: + region_kind = "shadow gap"; + break; + case kShadowKindHigh: + region_kind = "high shadow"; + break; + } + } else if (auto heap = descr.AsHeap()) { + region_kind = "heap"; + region_address = heap->chunk_access.chunk_begin; + region_size = heap->chunk_access.chunk_size; + } else if (auto stack = descr.AsStack()) { + region_kind = "stack"; + if (!stack->frame_descr) { + // region_{address,size} are already 0 + } else { + FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name, + name_size, region_address, region_size); + } + } else if (auto global = descr.AsGlobal()) { + region_kind = "global"; + auto &g = global->globals[0]; + internal_strlcpy(name, g.name, name_size); + region_address = g.beg; + region_size = g.size; + } else { + // region_{address,size} are already 0 + region_kind = "heap-invalid"; + } + + CHECK(region_kind); + if (region_address_ptr) *region_address_ptr = region_address; + if (region_size_ptr) *region_size_ptr = region_size; + return region_kind; } SANITIZER_INTERFACE_ATTRIBUTE Index: lib/asan/asan_descriptions.h =================================================================== --- lib/asan/asan_descriptions.h +++ lib/asan/asan_descriptions.h @@ -90,7 +90,7 @@ ShadowKind kind; u8 shadow_byte; - void Print(); + void Print() const; }; bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr); @@ -120,7 +120,7 @@ u32 free_stack_id; ChunkAccess chunk_access; - void Print(); + void Print() const; }; bool GetHeapAddressInformation(uptr addr, uptr access_size, @@ -134,7 +134,7 @@ uptr frame_pc; const char *frame_descr; - void Print(uptr access_size = 1); + void Print(uptr access_size = 1) const; }; bool GetStackAddressInformation(uptr addr, StackAddressDescription *descr); @@ -148,7 +148,7 @@ u32 reg_sites[kMaxGlobals]; u8 size; - void Print(uptr access_size = 1, const char *bug_type = ""); + void Print(uptr access_size = 1, const char *bug_type = "") const; }; bool GetGlobalAddressInformation(uptr addr, GlobalAddressDescription *descr); @@ -165,6 +165,112 @@ void PrintAddressDescription(uptr addr, uptr access_size = 1, const char *bug_type = ""); +enum AddressKind { + kAddressKindWild, + kAddressKindShadow, + kAddressKindHeap, + kAddressKindStack, + kAddressKindGlobal, +}; + +class AddressDescription { + struct AddressDescriptionData { + AddressKind kind; + union { + ShadowAddressDescription shadow; + HeapAddressDescription heap; + StackAddressDescription stack; + GlobalAddressDescription global; + uptr addr; + }; + }; + + AddressDescriptionData data = {}; + + public: + AddressDescription() = default; + // shouldLockThreadRegistry allows us to skip locking if we're sure we already + // have done it. + AddressDescription(uptr addr, bool shouldLockThreadRegistry = true) + : AddressDescription(addr, 1, shouldLockThreadRegistry) {} + AddressDescription(uptr addr, uptr length, + bool shouldLockThreadRegistry = true) { + if (GetShadowAddressInformation(addr, &data.shadow)) { + data.kind = kAddressKindShadow; + return; + } + if (GetHeapAddressInformation(addr, 1, &data.heap)) { + data.kind = kAddressKindHeap; + return; + } + + bool isStackMemory = false; + if (shouldLockThreadRegistry) { + ThreadRegistryLock l(&asanThreadRegistry()); + isStackMemory = GetStackAddressInformation(addr, &data.stack); + } else { + isStackMemory = GetStackAddressInformation(addr, &data.stack); + } + if (isStackMemory) { + data.kind = kAddressKindStack; + return; + } + + if (GetGlobalAddressInformation(addr, &data.global)) { + data.kind = kAddressKindGlobal; + return; + } + data.kind = kAddressKindWild; + addr = 0; + } + + // AddressKind Kind() const { return data.kind; } + uptr Address() const { + switch (data.kind) { + case kAddressKindWild: + return data.addr; + case kAddressKindShadow: + return data.shadow.addr; + case kAddressKindHeap: + return data.heap.addr; + case kAddressKindStack: + return data.stack.addr; + case kAddressKindGlobal: + return data.global.addr; + } + } + void Print() const { + switch (data.kind) { + case kAddressKindWild: + Printf("Address %p is a wild pointer.\n", data.addr); + return; + case kAddressKindShadow: + return data.shadow.Print(); + case kAddressKindHeap: + return data.heap.Print(); + case kAddressKindStack: + return data.stack.Print(); + case kAddressKindGlobal: + return data.global.Print(); + } + } + + void StoreTo(AddressDescriptionData *dst) const { *dst = data; } + + const ShadowAddressDescription *AsShadow() const { + return data.kind == kAddressKindShadow ? &data.shadow : nullptr; + } + const HeapAddressDescription *AsHeap() const { + return data.kind == kAddressKindHeap ? &data.heap : nullptr; + } + const StackAddressDescription *AsStack() const { + return data.kind == kAddressKindStack ? &data.stack : nullptr; + } + const GlobalAddressDescription *AsGlobal() const { + return data.kind == kAddressKindGlobal ? &data.global : nullptr; + } +}; + } // namespace __asan #endif // ASAN_DESCRIPTIONS_H Index: lib/asan/asan_descriptions.cc =================================================================== --- lib/asan/asan_descriptions.cc +++ lib/asan/asan_descriptions.cc @@ -312,11 +312,12 @@ return true; } -void ShadowAddressDescription::Print() { +void ShadowAddressDescription::Print() const { Printf("Address %p is located in the %s area.\n", addr, ShadowNames[kind]); } -void GlobalAddressDescription::Print(uptr access_size, const char *bug_type) { +void GlobalAddressDescription::Print(uptr access_size, + const char *bug_type) const { for (int i = 0; i < size; i++) { DescribeAddressRelativeToGlobal(addr, access_size, globals[i]); if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") && @@ -327,7 +328,7 @@ } } -void StackAddressDescription::Print(uptr access_size) { +void StackAddressDescription::Print(uptr access_size) const { Decorator d; char tname[128]; Printf("%s", d.Location()); @@ -382,7 +383,7 @@ DescribeThread(GetThreadContextByTidLocked(tid)); } -void HeapAddressDescription::Print() { +void HeapAddressDescription::Print() const { PrintHeapChunkAccess(addr, chunk_access); asanThreadRegistry().CheckLocked(); Index: lib/asan/asan_report.h =================================================================== --- lib/asan/asan_report.h +++ lib/asan/asan_report.h @@ -25,14 +25,6 @@ uptr name_len; }; -struct AddressDescription { - char *name; - uptr name_size; - uptr region_address; - uptr region_size; - const char *region_kind; -}; - // Returns the number of globals close to the provided address and copies // them to "globals" array. int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,