From 6fd46e795333430d28657fbeba72b4a0232a28ce Mon Sep 17 00:00:00 2001 From: Alex Budovski Date: Wed, 22 Mar 2023 14:06:27 -0500 Subject: Add support for anon types in FQN generation This fixes a bug in the fully qualified name generation we encounter a segment that has no name, such as when a proc is really a C++ lambda expression, which internally generates an anonymous class to house the function. In this case, we generate a unique name based on the DIE's offset to serve as the segment's name. --- src/dwarf2pdb.cpp | 20 ++++++++++++++++++-- src/readDwarf.cpp | 2 +- src/readDwarf.h | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index 763be85..afd062e 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -735,13 +735,29 @@ void CV2PDB::formatFullyQualifiedProcName(const DWARF_InfoData* proc, char* buf, // Format the parents in reverse order with :: operator in between. for (int i = segments.size() - 1; i >= 0; --i) { - const int nameLen = strlen(segments[i]->name); + const char* name = segments[i]->name; + char nameBuf[64] = {}; + int nameLen = 0; + if (!segments[i]->name) { + // This segment has no name. This could be because it is part of + // an anonymous class, which often happens for lambda expressions. + // Generate a unique anonymous name for it. + nameLen = sprintf_s(nameBuf, "[anon_%x]", segments[i]->entryOff); + if (nameLen < 0) { + // Formatting failed. Try a default name. + assert(false); // crash in debug builds. + name = "[anon]"; + } + name = nameBuf; + } else { + nameLen = strlen(name); + } if (remain < nameLen) { fprintf(stderr, "unable to fit full proc name: %s\n", proc->name); return; } - memcpy(p, segments[i]->name, nameLen); + memcpy(p, name, nameLen); p += nameLen; remain -= nameLen; diff --git a/src/readDwarf.cpp b/src/readDwarf.cpp index 9218f41..8e4ca4d 100644 --- a/src/readDwarf.cpp +++ b/src/readDwarf.cpp @@ -766,7 +766,7 @@ DWARF_InfoData* DIECursor::readNext(DWARF_InfoData* entry, bool stopAtNull) return nullptr; // root of the tree does not have a null terminator, but we know the length id.entryPtr = ptr; - entryOff = img->debug_info.sectOff(ptr); + entryOff = id.entryOff = img->debug_info.sectOff(ptr); id.code = LEB128(ptr); // If the previously scanned node claimed to have a child, this must be a valid DIE. diff --git a/src/readDwarf.h b/src/readDwarf.h index 06779c8..04afa38 100644 --- a/src/readDwarf.h +++ b/src/readDwarf.h @@ -191,6 +191,8 @@ struct DWARF_InfoData // Pointer into the memory-mapped image section where this DIE is located. byte* entryPtr; + unsigned int entryOff = 0; // the entry offset in the section it is in. + // Code to find the abbrev entry for this DIE, or 0 if it a sentinel marking // the end of a sibling chain. int code; -- cgit v0.12