Skip to content

Commit 2c05201

Browse files
committed
[lldb] Add a heuristic for handling DW_AT_specification
in sized containers. Due to a limitation of LLVM, the Swift frontend cannot add a DW_AT_specification attribute to a forward declaration, so it attaches it to the outer, anonymous, sized container. LLDB dutyfully follows specification attributes and collects everything into one list of attributes, which results in the anonymous container inheriting the names of the DIE linked by DW_AT_specification. This patch adds a heuristic to detect this situation. The correct thing to do here would be to fix LLVM to allow a forward declaration to have a specification, or potentially even better designate a new attribute for this.
1 parent c34071e commit 2c05201

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
7777

7878
if (num_attributes > 0) {
7979
uint32_t i;
80+
bool has_specification_of = false;
8081
for (i = 0; i < num_attributes; ++i) {
8182
const dw_attr_t attr = attributes.AttributeAtIndex(i);
8283
DWARFFormValue form_value;
@@ -95,9 +96,38 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
9596
case DW_AT_name:
9697
name.SetCString(form_value.AsCString());
9798
break;
99+
case DW_AT_specification:
100+
has_specification_of = true;
101+
break;
98102
case DW_AT_linkage_name:
99-
case DW_AT_MIPS_linkage_name:
103+
case DW_AT_MIPS_linkage_name: {
100104
mangled_name.SetCString(form_value.AsCString());
105+
auto HasSpecificationOf = [&](){
106+
if (has_specification_of)
107+
return true;
108+
for (uint32_t j = i+1; j < num_attributes; ++j)
109+
if (attributes.AttributeAtIndex(j) == DW_AT_specification)
110+
return true;
111+
return false;
112+
};
113+
// Is this a sized container with a specification? If yes,
114+
// the linkage name we just got is the one of the
115+
// specification die, which would be the unsubsituted
116+
// type. The child contains the linkage name of the
117+
// specialized type. We should define appropriate DWARF for
118+
// this instead of relying on this heuristic.
119+
if (die.Tag() == DW_TAG_structure_type && die.HasChildren() &&
120+
HasSpecificationOf()) {
121+
DWARFDIE member_die = die.GetFirstChild();
122+
if (member_die.Tag() != DW_TAG_member || member_die.GetName())
123+
break;
124+
if (DWARFDIE inner_type_die =
125+
member_die.GetAttributeValueAsReferenceDIE(DW_AT_type))
126+
if (const char *s = inner_type_die.GetAttributeValueAsString(
127+
DW_AT_name, nullptr))
128+
mangled_name.SetCString(s);
129+
}
130+
}
101131
break;
102132
case DW_AT_byte_size:
103133
dwarf_byte_size = form_value.Unsigned();
@@ -106,7 +136,7 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
106136
if (die.Tag() == DW_TAG_const_type)
107137
// This is how let bindings are represented. This doesn't
108138
// change the underlying Swift type.
109-
return ParseTypeFromDWARF(sc, die.GetReferencedDIE(attr),
139+
return ParseTypeFromDWARF(sc, form_value.Reference(),
110140
type_is_new_ptr);
111141
break;
112142
default:

lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ def implementation(self):
2727
)
2828
frame = thread.frames[0]
2929
self.assertTrue(frame, "Frame 0 is valid.")
30+
if self.TraceOn():
31+
self.expect("frame variable")
3032

3133
varB = frame.FindVariable("varB")
3234
field = varB.GetChildMemberWithName("a").GetChildMemberWithName("field")

0 commit comments

Comments
 (0)