Skip to content

Commit 394757a

Browse files
committed
Handle base structures in DWARF import
1 parent d5d34cf commit 394757a

File tree

1 file changed

+89
-50
lines changed

1 file changed

+89
-50
lines changed

plugins/dwarf/dwarf_import/src/types.rs

Lines changed: 89 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use crate::{die_handlers::*, ReaderType};
1919
use binaryninja::{
2020
rc::*,
2121
types::{
22-
MemberAccess, MemberScope, ReferenceType, StructureBuilder, StructureType, Type, TypeClass,
22+
BaseStructure, MemberAccess, MemberScope, ReferenceType, StructureBuilder, StructureType,
23+
Type, TypeClass,
2324
},
2425
};
2526

@@ -172,63 +173,101 @@ fn do_structure_parse<R: ReaderType>(
172173
debug_info_builder.add_type(get_uid(dwarf, unit, entry), full_name, ntr, false);
173174
}
174175

175-
// Get all the children and populate
176+
// Get all the children and base classes to populate
177+
let mut base_structures = Vec::new();
176178
let mut tree = unit.entries_tree(Some(entry.offset())).unwrap();
177179
let mut children = tree.root().unwrap().children();
178180
while let Ok(Some(child)) = children.next() {
179-
if child.entry().tag() == constants::DW_TAG_member {
180-
if let Some(child_type_id) = get_type(
181-
dwarf,
182-
unit,
183-
child.entry(),
184-
debug_info_builder_context,
185-
debug_info_builder,
186-
) {
187-
if let Some(t) = debug_info_builder.get_type(child_type_id) {
188-
let child_type = t.get_type();
189-
if let Some(child_name) = debug_info_builder_context
190-
.get_name(dwarf, unit, child.entry())
191-
.map_or(
192-
if child_type.type_class() == TypeClass::StructureTypeClass {
193-
Some("".to_string())
194-
} else {
195-
None
196-
},
197-
Some,
198-
)
199-
{
200-
// TODO : support DW_AT_data_bit_offset for offset as well
201-
if let Ok(Some(raw_struct_offset)) =
202-
child.entry().attr(constants::DW_AT_data_member_location)
203-
{
204-
// TODO : Let this fail; don't unwrap_or_default get_expr_value
205-
let struct_offset =
206-
get_attr_as_u64(&raw_struct_offset).unwrap_or_else(|| {
207-
get_expr_value(unit, raw_struct_offset).unwrap_or_default()
208-
});
209-
210-
structure_builder.insert(
211-
child_type.as_ref(),
212-
child_name,
213-
struct_offset,
214-
false,
215-
MemberAccess::NoAccess, // TODO : Resolve actual scopes, if possible
216-
MemberScope::NoScope,
217-
);
218-
} else {
219-
structure_builder.append(
220-
child_type.as_ref(),
221-
child_name,
222-
MemberAccess::NoAccess,
223-
MemberScope::NoScope,
224-
);
225-
}
226-
}
181+
match child.entry().tag() {
182+
constants::DW_TAG_member => {
183+
let Some(child_type_id) = get_type(
184+
dwarf,
185+
unit,
186+
child.entry(),
187+
debug_info_builder_context,
188+
debug_info_builder,
189+
) else {
190+
continue;
191+
};
192+
193+
let Some(child_dbg_ty) = debug_info_builder.get_type(child_type_id) else {
194+
continue;
195+
};
196+
let child_type = child_dbg_ty.get_type();
197+
198+
let Some(child_name) = debug_info_builder_context
199+
.get_name(dwarf, unit, child.entry())
200+
.or_else(|| match child_type.type_class() {
201+
TypeClass::StructureTypeClass => Some(String::new()),
202+
_ => None,
203+
})
204+
else {
205+
continue;
206+
};
207+
208+
// TODO : support DW_AT_data_bit_offset for offset as well
209+
if let Ok(Some(raw_struct_offset)) =
210+
child.entry().attr(constants::DW_AT_data_member_location)
211+
{
212+
// TODO : Let this fail; don't unwrap_or_default get_expr_value
213+
let struct_offset = get_attr_as_u64(&raw_struct_offset).unwrap_or_else(|| {
214+
get_expr_value(unit, raw_struct_offset).unwrap_or_default()
215+
});
216+
217+
structure_builder.insert(
218+
child_type.as_ref(),
219+
child_name,
220+
struct_offset,
221+
false,
222+
MemberAccess::NoAccess, // TODO : Resolve actual scopes, if possible
223+
MemberScope::NoScope,
224+
);
225+
} else {
226+
structure_builder.append(
227+
child_type.as_ref(),
228+
child_name,
229+
MemberAccess::NoAccess,
230+
MemberScope::NoScope,
231+
);
232+
}
233+
}
234+
constants::DW_TAG_inheritance => {
235+
let Some(base_type_id) = get_type(
236+
dwarf,
237+
unit,
238+
child.entry(),
239+
debug_info_builder_context,
240+
debug_info_builder,
241+
) else {
242+
warn!("Failed to get base type for inheritance");
243+
continue;
244+
};
245+
let Some(base_dbg_ty) = debug_info_builder.get_type(base_type_id) else {
246+
continue;
247+
};
248+
let base_type = base_dbg_ty.get_type();
249+
250+
let Ok(Some(raw_data_member_location)) =
251+
child.entry().attr(constants::DW_AT_data_member_location)
252+
else {
253+
warn!("Failed to get DW_AT_data_member_location for inheritance");
254+
continue;
255+
};
256+
257+
let base_offset = get_attr_as_u64(&raw_data_member_location).unwrap_or_else(|| {
258+
get_expr_value(unit, raw_data_member_location).unwrap_or_default()
259+
});
260+
261+
if let Some(ntr) = base_type.get_named_type_reference() {
262+
let base_struct = BaseStructure::new(ntr, base_offset, 0);
263+
base_structures.push(base_struct);
227264
}
228265
}
266+
_ => {}
229267
}
230268
}
231269

270+
structure_builder.base_structures(&base_structures);
232271
let finalized_structure = Type::structure(&structure_builder.finalize());
233272
if let Some(full_name) = full_name {
234273
debug_info_builder.add_type(

0 commit comments

Comments
 (0)