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,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); @@ -173,92 +173,104 @@ 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) { - 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; - } + 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, &shadow)) { - kind = kAddressKindShadow; + if (GetShadowAddressInformation(addr, &data.shadow)) { + data.kind = kAddressKindShadow; return; } - if (GetHeapAddressInformation(addr, 1, &heap)) { - kind = kAddressKindHeap; + if (GetHeapAddressInformation(addr, 1, &data.heap)) { + data.kind = kAddressKindHeap; return; } bool isStackMemory = false; if (shouldLockThreadRegistry) { ThreadRegistryLock l(&asanThreadRegistry()); - isStackMemory = GetStackAddressInformation(addr, &stack); + isStackMemory = GetStackAddressInformation(addr, &data.stack); } else { - isStackMemory = GetStackAddressInformation(addr, &stack); + isStackMemory = GetStackAddressInformation(addr, &data.stack); } if (isStackMemory) { - kind = kAddressKindStack; + data.kind = kAddressKindStack; return; } - if (GetGlobalAddressInformation(addr, &global)) { - kind = kAddressKindGlobal; + if (GetGlobalAddressInformation(addr, &data.global)) { + data.kind = kAddressKindGlobal; return; } - kind = kAddressKindWild; - addr = 0; + data.kind = kAddressKindWild; + data.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(); + } + } + + 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; } }; 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();