Index: lib/asan/asan_debugging.cc =================================================================== --- lib/asan/asan_debugging.cc +++ lib/asan/asan_debugging.cc @@ -84,14 +84,14 @@ uptr region_size = 0; const char *region_kind = nullptr; if (name && name_size > 0) name[0] = 0; - switch (descr.kind) { + 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) { + switch (descr.AsShadow()->kind) { case kShadowKindLow: region_kind = "low shadow"; break; @@ -105,21 +105,22 @@ break; case kAddressKindHeap: region_kind = "heap"; - region_address = descr.heap.chunk_access.chunk_begin; - region_size = descr.heap.chunk_access.chunk_size; + region_address = descr.AsHeap()->chunk_access.chunk_begin; + region_size = descr.AsHeap()->chunk_access.chunk_size; break; case kAddressKindStack: region_kind = "stack"; - if (!descr.stack.frame_descr) { + if (!descr.AsStack()->frame_descr) { // region_{address,size} are already 0 } else { - FindInfoForStackVar(addr, descr.stack.frame_descr, descr.stack.offset, - name, name_size, region_address, region_size); + FindInfoForStackVar(addr, descr.AsStack()->frame_descr, + descr.AsStack()->offset, name, name_size, + region_address, region_size); } break; case kAddressKindGlobal: region_kind = "global"; - auto &g = descr.global.globals[0]; + auto &g = descr.AsGlobal()->globals[0]; internal_strlcpy(name, g.name, name_size); region_address = g.beg; region_size = g.size; Index: lib/asan/asan_descriptions.h =================================================================== --- lib/asan/asan_descriptions.h +++ lib/asan/asan_descriptions.h @@ -90,12 +90,9 @@ ShadowKind kind; u8 shadow_byte; - void Print(); + void Print() const; }; -bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr); -bool DescribeAddressIfShadow(uptr addr); - enum AccessType { kAccessTypeLeft, kAccessTypeRight, @@ -120,7 +117,7 @@ u32 free_stack_id; ChunkAccess chunk_access; - void Print(); + void Print() const; }; bool GetHeapAddressInformation(uptr addr, uptr access_size, @@ -134,12 +131,9 @@ 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); -bool DescribeAddressIfStack(uptr addr, uptr access_size); - struct GlobalAddressDescription { uptr addr; // Assume address is close to at most four globals. @@ -148,7 +142,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); @@ -173,92 +167,76 @@ 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; +class AddressDescription { + struct AddressDescriptionData { + AddressKind kind; + union { + ShadowAddressDescription shadow; + HeapAddressDescription heap; + StackAddressDescription stack; + GlobalAddressDescription global; + uptr addr; + }; }; - uptr Address() { - switch (kind) { + + 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); + + AddressKind kind() const { return data.kind; } + + uptr address() const { + switch (data.kind) { case kAddressKindWild: - return addr; + return data.addr; case kAddressKindShadow: - return shadow.addr; + return data.shadow.addr; case kAddressKindHeap: - return heap.addr; + return data.heap.addr; case kAddressKindStack: - return stack.addr; + return data.stack.addr; case kAddressKindGlobal: - return global.addr; + return data.global.addr; } } - void Print() { - switch (kind) { + + void Print() const { + switch (data.kind) { case kAddressKindWild: - Printf("Address %p is a wild pointer.\n", addr); + Printf("Address %p is a wild pointer.\n", data.addr); return; case kAddressKindShadow: - return shadow.Print(); + return data.shadow.Print(); case kAddressKindHeap: - return heap.Print(); + return data.heap.Print(); case kAddressKindStack: - return stack.Print(); + return data.stack.Print(); case kAddressKindGlobal: - return global.Print(); + return data.global.Print(); } } -}; -struct AddressDescription : AddressDescriptionBase { - AddressDescription() { - kind = kAddressKindWild; - addr = 0; + const ShadowAddressDescription *AsShadow() const { + return data.kind == kAddressKindShadow ? &data.shadow : nullptr; } - // 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; - } + const HeapAddressDescription *AsHeap() const { + return data.kind == kAddressKindHeap ? &data.heap : nullptr; + } - if (GetGlobalAddressInformation(addr, &global)) { - kind = kAddressKindGlobal; - return; - } - kind = kAddressKindWild; - addr = 0; + const StackAddressDescription *AsStack() const { + return data.kind == kAddressKindStack ? &data.stack : nullptr; + } + + const GlobalAddressDescription *AsGlobal() const { + return data.kind == kAddressKindGlobal ? &data.global : nullptr; } }; Index: lib/asan/asan_descriptions.cc =================================================================== --- lib/asan/asan_descriptions.cc +++ lib/asan/asan_descriptions.cc @@ -85,14 +85,8 @@ return true; } -bool DescribeAddressIfShadow(uptr addr) { - ShadowAddressDescription descr; - if (!GetShadowAddressInformation(addr, &descr)) return false; - descr.Print(); - return true; -} - -bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr) { +static bool GetShadowAddressInformation(uptr addr, + ShadowAddressDescription *descr) { if (AddrIsInMem(addr)) return false; ShadowKind shadow_kind; if (!GetShadowKind(addr, &shadow_kind)) return false; @@ -312,11 +306,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 +322,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 +377,7 @@ DescribeThread(GetThreadContextByTidLocked(tid)); } -void HeapAddressDescription::Print() { +void HeapAddressDescription::Print() const { PrintHeapChunkAccess(addr, chunk_access); asanThreadRegistry().CheckLocked(); @@ -447,4 +442,36 @@ "AddressSanitizer can not describe address in more detail " "(wild memory access suspected).\n"); } + +AddressDescription::AddressDescription(uptr addr, uptr length, + bool shouldLockThreadRegistry) { + 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; + data.addr = 0; +} + } // namespace __asan