diff options
| author | Josh Ferrell <josh@vector35.com> | 2025-10-20 12:01:27 -0400 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2025-10-20 12:02:53 -0400 |
| commit | 98f9bae4c7d2dc636ab0a7fe61741e7f9fccba70 (patch) | |
| tree | 5b573fcde21abae852ea913980a3bb15d0fedec8 /plugins/dwarf | |
| parent | 432984039635733d2a5bf7b561e17014a6b93084 (diff) | |
[DWARF] Greatly improve handling of typedefs
Diffstat (limited to 'plugins/dwarf')
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/die_handlers.rs | 71 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs | 35 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/types.rs | 9 |
3 files changed, 84 insertions, 31 deletions
diff --git a/plugins/dwarf/dwarf_import/src/die_handlers.rs b/plugins/dwarf/dwarf_import/src/die_handlers.rs index dbc1491a..dda47956 100644 --- a/plugins/dwarf/dwarf_import/src/die_handlers.rs +++ b/plugins/dwarf/dwarf_import/src/die_handlers.rs @@ -173,7 +173,8 @@ pub(crate) fn handle_typedef( // This will fail in the case where we have a typedef to a type that doesn't exist (failed to parse, incomplete, etc) if let Some(entry_type_offset) = entry_type { if let Some(t) = debug_info_builder.get_type(entry_type_offset) { - return (Some(t.get_type()), typedef_name != t.name); + let typedef_type = Type::named_type_from_type(typedef_name, &t.get_type()); + return (Some(typedef_type), typedef_name != t.name); } } @@ -204,16 +205,22 @@ pub(crate) fn handle_pointer<R: ReaderType>( }; let target_type = match entry_type { - Some(entry_type_offset) => debug_info_builder - .get_type(entry_type_offset) - .or_else(|| { - log::error!( - "Failed to get pointer target type at entry offset {}", - entry_type_offset - ); - None - })? - .get_type(), + Some(entry_type_offset) => { + let debug_target_type = + debug_info_builder.get_type(entry_type_offset).or_else(|| { + log::error!( + "Failed to get pointer target type at entry offset {}", + entry_type_offset + ); + None + })?; + + if let Some(ntr) = debug_target_type.get_type().get_named_type_reference() { + Type::named_type_from_type(ntr.name(), &debug_target_type.get_type()) + } else { + debug_target_type.get_type() + } + } None => Type::void(), }; @@ -335,7 +342,7 @@ pub(crate) fn handle_function<R: ReaderType>( .unwrap_or("_unnamed_func".to_string()); let ntr = Type::named_type_from_type(&name, &Type::function(return_type.as_ref(), vec![], false)); - debug_info_builder.add_type(get_uid(dwarf, unit, entry), name, ntr, false); + debug_info_builder.add_type(get_uid(dwarf, unit, entry), name, ntr, false, None); let mut parameters: Vec<FunctionParameter> = vec![]; let mut variable_arguments = false; @@ -376,21 +383,31 @@ pub(crate) fn handle_function<R: ReaderType>( }; let name = debug_info_builder_context.get_name(dwarf, unit, child.entry()); - let child_type = debug_info_builder - .get_type(child_uid) - .or_else(|| { - log::error!( - "Failed to get function parameter type with uid {}", - child_uid - ); - None - })? - .get_type(); - parameters.push(FunctionParameter::new( - child_type, - name.unwrap_or_default(), - None, - )); + let child_debug_type = debug_info_builder.get_type(child_uid).or_else(|| { + log::error!( + "Failed to get function parameter type with uid {}", + child_uid + ); + None + })?; + let child_type = child_debug_type.get_type(); + + // If this is a typedef, make sure we reference it instead of resolving to the underlying type + if let Some(ntr) = child_type.get_named_type_reference() { + let typedef_type = Type::named_type_from_type(ntr.name(), &child_type); + + parameters.push(FunctionParameter::new( + typedef_type, + name.unwrap_or_default(), + None, + )); + } else { + parameters.push(FunctionParameter::new( + child_type, + name.unwrap_or_default(), + None, + )); + } } else if child.entry().tag() == constants::DW_TAG_unspecified_parameters { variable_arguments = true; } diff --git a/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs b/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs index 94f370a1..eda641ca 100644 --- a/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs +++ b/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs @@ -107,6 +107,7 @@ pub(crate) struct DebugType { pub name: String, pub ty: Ref<Type>, pub commit: bool, + pub target_type_uid: Option<TypeUID>, } impl DebugType { @@ -363,17 +364,26 @@ impl DebugInfoBuilder { self.types.values() } - pub(crate) fn add_type(&mut self, type_uid: TypeUID, name: String, t: Ref<Type>, commit: bool) { + pub(crate) fn add_type( + &mut self, + type_uid: TypeUID, + name: String, + t: Ref<Type>, + commit: bool, + target_type_uid: Option<TypeUID>, + ) { if let Some(DebugType { name: existing_name, ty: existing_type, commit: _, + target_type_uid: _, }) = self.types.insert( type_uid, DebugType { name: name.clone(), ty: t.clone(), commit, + target_type_uid, }, ) { if existing_type != t && commit { @@ -608,7 +618,28 @@ impl DebugInfoBuilder { }; // TODO : Components - debug_info.add_type(&debug_type_name, &debug_type.ty, &[]); + // If it's a typedef resolve one layer down since we'd technically be defining it as a typedef to itself otherwise + if let Some(ntr) = debug_type.get_type().get_named_type_reference() { + if let Some(target_uid) = debug_type.target_type_uid { + if let Some(target_type) = self.get_type(target_uid) { + debug_info.add_type(&debug_type_name, &target_type.get_type(), &[]); + } else { + error!( + "Failed to find typedef {} target for uid {}", + debug_type_name, + ntr.name() + ); + } + } else { + error!( + "Failed to find typedef {} target uid for {}", + debug_type_name, + ntr.name() + ); + } + } else { + debug_info.add_type(&debug_type_name, &debug_type.ty, &[]); + } type_uids_by_name.insert(debug_type_name, *debug_type_uid); } } diff --git a/plugins/dwarf/dwarf_import/src/types.rs b/plugins/dwarf/dwarf_import/src/types.rs index e692e8ca..38f0dbc0 100644 --- a/plugins/dwarf/dwarf_import/src/types.rs +++ b/plugins/dwarf/dwarf_import/src/types.rs @@ -162,6 +162,7 @@ fn do_structure_parse<R: ReaderType>( full_name.to_owned(), ntr, false, + None, ); } else { // We _need_ to have initial typedefs or else we can enter infinite parsing loops @@ -170,7 +171,7 @@ fn do_structure_parse<R: ReaderType>( let full_name = format!("anonymous_structure_{:x}", get_uid(dwarf, unit, entry)); let ntr = Type::named_type_from_type(&full_name, &Type::structure(&structure_builder.finalize())); - debug_info_builder.add_type(get_uid(dwarf, unit, entry), full_name, ntr, false); + debug_info_builder.add_type(get_uid(dwarf, unit, entry), full_name, ntr, false, None); } // Get all the children and base classes to populate @@ -248,6 +249,7 @@ fn do_structure_parse<R: ReaderType>( } else if let Ok(Some(raw_struct_offset_bits)) = child_entry.attr(constants::DW_AT_data_bit_offset) { + //TODO: support misaligned offsets when bitwise data structures get in let Some(struct_offset_bits) = get_attr_as_u64(&raw_struct_offset_bits) .or_else(|| get_expr_value(unit, raw_struct_offset_bits)) else { @@ -314,12 +316,14 @@ fn do_structure_parse<R: ReaderType>( structure_builder.base_structures(&base_structures); let finalized_structure = Type::structure(&structure_builder.finalize()); + if let Some(full_name) = full_name { debug_info_builder.add_type( get_uid(dwarf, unit, entry) + 1, // TODO : This is super broke (uid + 1 is not guaranteed to be unique) full_name, finalized_structure, true, + None, ); } else { debug_info_builder.add_type( @@ -327,6 +331,7 @@ fn do_structure_parse<R: ReaderType>( finalized_structure.to_string(), finalized_structure, false, // Don't commit anonymous unions (because I think it'll break things) + None, ); } Some(get_uid(dwarf, unit, entry)) @@ -586,7 +591,7 @@ pub(crate) fn get_type<R: ReaderType>( type_def.to_string() }); - debug_info_builder.add_type(entry_uid, name, type_def, commit); + debug_info_builder.add_type(entry_uid, name, type_def, commit, entry_type); Some(entry_uid) } else { None |
