diff options
| author | Mason Reed <mason@vector35.com> | 2025-02-28 23:48:55 -0500 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-02-28 23:48:55 -0500 |
| commit | 394757a1c8eabcdc121a549d40c2987aac304c8c (patch) | |
| tree | 79f02367ef8cb5fabb74225e2eca870c671d500f /plugins/dwarf | |
| parent | d5d34cf691dc7fd0cc4580ed4a30e8c38c5dc51f (diff) | |
Handle base structures in DWARF import
Diffstat (limited to 'plugins/dwarf')
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/types.rs | 137 |
1 files changed, 88 insertions, 49 deletions
diff --git a/plugins/dwarf/dwarf_import/src/types.rs b/plugins/dwarf/dwarf_import/src/types.rs index f5d5a444..ca5a20da 100644 --- a/plugins/dwarf/dwarf_import/src/types.rs +++ b/plugins/dwarf/dwarf_import/src/types.rs @@ -19,7 +19,8 @@ use crate::{die_handlers::*, ReaderType}; use binaryninja::{ rc::*, types::{ - MemberAccess, MemberScope, ReferenceType, StructureBuilder, StructureType, Type, TypeClass, + BaseStructure, MemberAccess, MemberScope, ReferenceType, StructureBuilder, StructureType, + Type, TypeClass, }, }; @@ -172,63 +173,101 @@ fn do_structure_parse<R: ReaderType>( debug_info_builder.add_type(get_uid(dwarf, unit, entry), full_name, ntr, false); } - // Get all the children and populate + // Get all the children and base classes to populate + let mut base_structures = Vec::new(); let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); let mut children = tree.root().unwrap().children(); while let Ok(Some(child)) = children.next() { - if child.entry().tag() == constants::DW_TAG_member { - if let Some(child_type_id) = get_type( - dwarf, - unit, - child.entry(), - debug_info_builder_context, - debug_info_builder, - ) { - if let Some(t) = debug_info_builder.get_type(child_type_id) { - let child_type = t.get_type(); - if let Some(child_name) = debug_info_builder_context - .get_name(dwarf, unit, child.entry()) - .map_or( - if child_type.type_class() == TypeClass::StructureTypeClass { - Some("".to_string()) - } else { - None - }, - Some, - ) - { - // TODO : support DW_AT_data_bit_offset for offset as well - if let Ok(Some(raw_struct_offset)) = - child.entry().attr(constants::DW_AT_data_member_location) - { - // TODO : Let this fail; don't unwrap_or_default get_expr_value - let struct_offset = - get_attr_as_u64(&raw_struct_offset).unwrap_or_else(|| { - get_expr_value(unit, raw_struct_offset).unwrap_or_default() - }); + match child.entry().tag() { + constants::DW_TAG_member => { + let Some(child_type_id) = get_type( + dwarf, + unit, + child.entry(), + debug_info_builder_context, + debug_info_builder, + ) else { + continue; + }; + + let Some(child_dbg_ty) = debug_info_builder.get_type(child_type_id) else { + continue; + }; + let child_type = child_dbg_ty.get_type(); + + let Some(child_name) = debug_info_builder_context + .get_name(dwarf, unit, child.entry()) + .or_else(|| match child_type.type_class() { + TypeClass::StructureTypeClass => Some(String::new()), + _ => None, + }) + else { + continue; + }; + + // TODO : support DW_AT_data_bit_offset for offset as well + if let Ok(Some(raw_struct_offset)) = + child.entry().attr(constants::DW_AT_data_member_location) + { + // TODO : Let this fail; don't unwrap_or_default get_expr_value + let struct_offset = get_attr_as_u64(&raw_struct_offset).unwrap_or_else(|| { + get_expr_value(unit, raw_struct_offset).unwrap_or_default() + }); + + structure_builder.insert( + child_type.as_ref(), + child_name, + struct_offset, + false, + MemberAccess::NoAccess, // TODO : Resolve actual scopes, if possible + MemberScope::NoScope, + ); + } else { + structure_builder.append( + child_type.as_ref(), + child_name, + MemberAccess::NoAccess, + MemberScope::NoScope, + ); + } + } + constants::DW_TAG_inheritance => { + let Some(base_type_id) = get_type( + dwarf, + unit, + child.entry(), + debug_info_builder_context, + debug_info_builder, + ) else { + warn!("Failed to get base type for inheritance"); + continue; + }; + let Some(base_dbg_ty) = debug_info_builder.get_type(base_type_id) else { + continue; + }; + let base_type = base_dbg_ty.get_type(); + + let Ok(Some(raw_data_member_location)) = + child.entry().attr(constants::DW_AT_data_member_location) + else { + warn!("Failed to get DW_AT_data_member_location for inheritance"); + continue; + }; + + let base_offset = get_attr_as_u64(&raw_data_member_location).unwrap_or_else(|| { + get_expr_value(unit, raw_data_member_location).unwrap_or_default() + }); - structure_builder.insert( - child_type.as_ref(), - child_name, - struct_offset, - false, - MemberAccess::NoAccess, // TODO : Resolve actual scopes, if possible - MemberScope::NoScope, - ); - } else { - structure_builder.append( - child_type.as_ref(), - child_name, - MemberAccess::NoAccess, - MemberScope::NoScope, - ); - } - } + if let Some(ntr) = base_type.get_named_type_reference() { + let base_struct = BaseStructure::new(ntr, base_offset, 0); + base_structures.push(base_struct); } } + _ => {} } } + 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( |
