mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
libdrgn: dwarf_info: fix resolving incomplete type in wrong scope
find_namespace_containing_die() only looks for DW_TAG_namespace DIEs containing the target DIE, but it also needs to look fo nested classes/structs/unions. Consider the following program: namespace ns { class Bar { ... }; class Foo { class Bar { ... }; ... }; }; If we encounter a declaration DIE for ns::Foo::Bar, we'll end up looking for the definition directly in ns and finding ns::Bar instead, which is a completely different type. Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
6840f10b03
commit
bc8514512f
@ -4830,16 +4830,21 @@ find_namespace_containing_die(struct drgn_debug_info *dbinfo,
|
||||
return err;
|
||||
|
||||
for (size_t i = 0; i < num_ancestors; i++) {
|
||||
if (dwarf_tag(&ancestors[i]) != DW_TAG_namespace)
|
||||
switch (dwarf_tag(&ancestors[i])) {
|
||||
#define X(name) case DW_TAG_##name: break;
|
||||
DRGN_DWARF_INDEX_NAMESPACE_TAGS
|
||||
#undef X
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
Dwarf_Attribute attr_mem, *attr;
|
||||
if (!(attr = dwarf_attr_integrate(&ancestors[i], DW_AT_name,
|
||||
&attr_mem)))
|
||||
continue;
|
||||
const char *name = dwarf_formstring(attr);
|
||||
if (!name) {
|
||||
err = drgn_error_create(DRGN_ERROR_OTHER,
|
||||
"DW_TAG_namespace has invalid DW_AT_name");
|
||||
err = drgn_error_libdw();
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1013,6 +1013,120 @@ class TestTypes(TestCase):
|
||||
),
|
||||
)
|
||||
|
||||
def test_incomplete_to_complete_nested(self):
|
||||
prog = dwarf_program(
|
||||
wrap_test_type_dies(
|
||||
DwarfDie(
|
||||
DW_TAG.pointer_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 8),
|
||||
DwarfAttrib(DW_AT.type, DW_FORM.ref4, "incomplete_class_die"),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Foo"),
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 0),
|
||||
),
|
||||
(
|
||||
DwarfLabel("incomplete_class_die"),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Bar"),
|
||||
DwarfAttrib(
|
||||
DW_AT.declaration, DW_FORM.flag_present, True
|
||||
),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Bar"),
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Bar"),
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 1),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.subprogram,
|
||||
(DwarfAttrib(DW_AT.name, DW_FORM.string, "main"),),
|
||||
),
|
||||
),
|
||||
lang=DW_LANG.C_plus_plus,
|
||||
)
|
||||
self.assertIdentical(
|
||||
prog.type("TEST").type.type,
|
||||
prog.class_type("Bar", 0, ()),
|
||||
)
|
||||
|
||||
def test_incomplete_to_complete_nested_specification(self):
|
||||
prog = dwarf_program(
|
||||
wrap_test_type_dies(
|
||||
DwarfDie(
|
||||
DW_TAG.pointer_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 8),
|
||||
DwarfAttrib(DW_AT.type, DW_FORM.ref4, "incomplete_class_die"),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Foo"),
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 0),
|
||||
),
|
||||
(
|
||||
DwarfLabel("incomplete_class_die"),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Bar"),
|
||||
DwarfAttrib(
|
||||
DW_AT.declaration, DW_FORM.flag_present, True
|
||||
),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(
|
||||
DW_AT.specification,
|
||||
DW_FORM.ref4,
|
||||
"incomplete_class_die",
|
||||
),
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.class_type,
|
||||
(
|
||||
DwarfAttrib(DW_AT.name, DW_FORM.string, "Bar"),
|
||||
DwarfAttrib(DW_AT.byte_size, DW_FORM.data1, 1),
|
||||
),
|
||||
),
|
||||
DwarfDie(
|
||||
DW_TAG.subprogram,
|
||||
(DwarfAttrib(DW_AT.name, DW_FORM.string, "main"),),
|
||||
),
|
||||
),
|
||||
lang=DW_LANG.C_plus_plus,
|
||||
)
|
||||
self.assertIdentical(
|
||||
prog.type("TEST").type.type,
|
||||
prog.class_type("Bar", 0, ()),
|
||||
)
|
||||
|
||||
def test_filename(self):
|
||||
dies = (
|
||||
DwarfDie(
|
||||
|
Loading…
Reference in New Issue
Block a user