summaryrefslogtreecommitdiff
path: root/plugins/dwarf
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2025-10-20 12:01:27 -0400
committerJosh Ferrell <josh@vector35.com>2025-10-20 12:02:53 -0400
commit98f9bae4c7d2dc636ab0a7fe61741e7f9fccba70 (patch)
tree5b573fcde21abae852ea913980a3bb15d0fedec8 /plugins/dwarf
parent432984039635733d2a5bf7b561e17014a6b93084 (diff)
[DWARF] Greatly improve handling of typedefs
Diffstat (limited to 'plugins/dwarf')
-rw-r--r--plugins/dwarf/dwarf_import/src/die_handlers.rs71
-rw-r--r--plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs35
-rw-r--r--plugins/dwarf/dwarf_import/src/types.rs9
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