From c1100bd691588c50fdd626e1747f746c5b9eb4f5 Mon Sep 17 00:00:00 2001 From: Daniel Thaler Date: Thu, 26 Sep 2024 00:10:07 +0200 Subject: [PATCH] Add handling for incomplete types in DWARF debug data C allows incomplete type declarations. For example "struct foo;" only tells the compiler that his type exists, and results in a stub type entry with the attribute DW_AT_declaration in the DWARF data. The DWARF typereader can now handle this case. Fixes issue #38 --- src/dwarf/attributes.rs | 12 ++++++++++++ src/dwarf/typereader.rs | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/dwarf/attributes.rs b/src/dwarf/attributes.rs index 11410ea..77c5447 100644 --- a/src/dwarf/attributes.rs +++ b/src/dwarf/attributes.rs @@ -421,3 +421,15 @@ pub(crate) fn get_type_attribute( _ => Err("failed to get DIE tree".to_string()), } } + +// get the DW_AT_declaration attribute +pub(crate) fn get_declaration_attribute( + entry: &DebuggingInformationEntry, +) -> Option { + let decl_attr = get_attr_value(entry, gimli::constants::DW_AT_declaration)?; + if let gimli::AttributeValue::Flag(flag) = decl_attr { + Some(flag) + } else { + None + } +} diff --git a/src/dwarf/typereader.rs b/src/dwarf/typereader.rs index d2d9580..f2d84d5 100644 --- a/src/dwarf/typereader.rs +++ b/src/dwarf/typereader.rs @@ -114,6 +114,21 @@ impl DebugDataReader<'_> { let entries_tree_node = entries_tree.root().map_err(|err| err.to_string())?; let entry = entries_tree_node.entry(); let typename = get_name_attribute(entry, &self.dwarf, unit).ok(); + let is_declaration = get_declaration_attribute(entry).unwrap_or(false); + + if is_declaration { + // This is a declaration, not a definition. This happens when a type is declared but not defined + // e.g. "struct foo;" in a header file. + // We can't do anything with this - return a dummy type, and don't store it in the types map. + return Ok(TypeInfo { + datatype: DwarfDataType::Other(0), + name: typename, + unit_idx: current_unit, + dbginfo_offset: dbginfo_offset.0, + }); + } + + // track in-progress items to prevent infinite recursion typereader_data.wip_items.push(WipItemInfo::new( dbginfo_offset.0, typename.clone(),