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,59 @@ 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; + switch (descr.kind) { + case kAddressKindWild: + // region_{address,size} are already 0 + region_kind = "heap-invalid"; + break; + case kAddressKindShadow: + // region_{address,size} are already 0 + switch (descr.shadow.kind) { + case kShadowKindLow: + region_kind = "low shadow"; + break; + case kShadowKindGap: + region_kind = "shadow gap"; + break; + case kShadowKindHigh: + region_kind = "high shadow"; + break; + } + break; + case kAddressKindHeap: + region_kind = "heap"; + if (name && name_size > 0) name[0] = 0; + region_address = descr.heap.chunk_access.chunk_begin; + region_size = descr.heap.chunk_access.chunk_size; + break; + case kAddressKindStack: + region_kind = "stack"; + if (!descr.stack.frame_descr) { + if (name && name_size > 0) name[0] = 0; + // region_{address,size} are already 0 + } else { + FindInfoForStackVar(addr, descr.stack.frame_descr, descr.stack.offset, + name, name_size, region_address, region_size); + } + break; + case kAddressKindGlobal: + region_kind = "global"; + auto &g = descr.global.globals[0]; + internal_strlcpy(name, g.name, name_size); + region_address = g.beg; + region_size = g.size; + break; + } + 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 @@ -165,6 +165,103 @@ void PrintAddressDescription(uptr addr, uptr access_size = 1, const char *bug_type = ""); +enum AddressKind { + kAddressKindWild, + kAddressKindShadow, + kAddressKindHeap, + kAddressKindStack, + kAddressKindGlobal, +}; + +struct AddressDescriptionBase { + // Split between *Base and the "proper" object with constructors, because + // VS2013 doesn't allow us to include objects without a trivial default + // constructor in an enum, and I'd like to be sure that an AddressDescription + // object is always valid, so we need initialization. + // Use AddressDescriptionBase for objects which need to be stored in unions, + // like in the Error* objects, use AddressDescription otherwise, since it + // guarantees initialization. + // We should be able to do without this struct after we deprecate VS2013. + AddressKind kind; + union { + ShadowAddressDescription shadow; + HeapAddressDescription heap; + StackAddressDescription stack; + GlobalAddressDescription global; + uptr addr; + }; + uptr Address() { + switch (kind) { + case kAddressKindWild: + return addr; + case kAddressKindShadow: + return shadow.addr; + case kAddressKindHeap: + return heap.addr; + case kAddressKindStack: + return stack.addr; + case kAddressKindGlobal: + return global.addr; + } + } + void Print() { + switch (kind) { + case kAddressKindWild: + Printf("Address %p is a wild pointer.\n", addr); + return; + case kAddressKindShadow: + return shadow.Print(); + case kAddressKindHeap: + return heap.Print(); + case kAddressKindStack: + return stack.Print(); + case kAddressKindGlobal: + return global.Print(); + } + } +}; + +struct AddressDescription : AddressDescriptionBase { + AddressDescription() { + kind = kAddressKindWild; + addr = 0; + } + // 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, &shadow)) { + kind = kAddressKindShadow; + return; + } + if (GetHeapAddressInformation(addr, 1, &heap)) { + kind = kAddressKindHeap; + return; + } + + bool isStackMemory = false; + if (shouldLockThreadRegistry) { + ThreadRegistryLock l(&asanThreadRegistry()); + isStackMemory = GetStackAddressInformation(addr, &stack); + } else { + isStackMemory = GetStackAddressInformation(addr, &stack); + } + if (isStackMemory) { + kind = kAddressKindStack; + return; + } + + if (GetGlobalAddressInformation(addr, &global)) { + kind = kAddressKindGlobal; + return; + } + kind = kAddressKindWild; + addr = 0; + } +}; + } // namespace __asan #endif // ASAN_DESCRIPTIONS_H 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,