summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Budovski <alexbud@meta.com>2023-03-22 19:06:27 (GMT)
committerAlex Budovski <alexbud@meta.com>2023-03-24 15:19:37 (GMT)
commit6fd46e795333430d28657fbeba72b4a0232a28ce (patch)
tree693fedb9d96029b351c794289f5376badb584d2f
parenta32d9207c46fbe02ef60473598325e3b50aec006 (diff)
downloadcv2pdb-6fd46e795333430d28657fbeba72b4a0232a28ce.zip
cv2pdb-6fd46e795333430d28657fbeba72b4a0232a28ce.tar.gz
cv2pdb-6fd46e795333430d28657fbeba72b4a0232a28ce.tar.bz2
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.
-rw-r--r--src/dwarf2pdb.cpp20
-rw-r--r--src/readDwarf.cpp2
-rw-r--r--src/readDwarf.h2
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;