Skip to content

Commit 98f9bae

Browse files
committed
[DWARF] Greatly improve handling of typedefs
1 parent 4329840 commit 98f9bae

File tree

3 files changed

+84
-31
lines changed

3 files changed

+84
-31
lines changed

plugins/dwarf/dwarf_import/src/die_handlers.rs

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ pub(crate) fn handle_typedef(
173173
// This will fail in the case where we have a typedef to a type that doesn't exist (failed to parse, incomplete, etc)
174174
if let Some(entry_type_offset) = entry_type {
175175
if let Some(t) = debug_info_builder.get_type(entry_type_offset) {
176-
return (Some(t.get_type()), typedef_name != t.name);
176+
let typedef_type = Type::named_type_from_type(typedef_name, &t.get_type());
177+
return (Some(typedef_type), typedef_name != t.name);
177178
}
178179
}
179180

@@ -204,16 +205,22 @@ pub(crate) fn handle_pointer<R: ReaderType>(
204205
};
205206

206207
let target_type = match entry_type {
207-
Some(entry_type_offset) => debug_info_builder
208-
.get_type(entry_type_offset)
209-
.or_else(|| {
210-
log::error!(
211-
"Failed to get pointer target type at entry offset {}",
212-
entry_type_offset
213-
);
214-
None
215-
})?
216-
.get_type(),
208+
Some(entry_type_offset) => {
209+
let debug_target_type =
210+
debug_info_builder.get_type(entry_type_offset).or_else(|| {
211+
log::error!(
212+
"Failed to get pointer target type at entry offset {}",
213+
entry_type_offset
214+
);
215+
None
216+
})?;
217+
218+
if let Some(ntr) = debug_target_type.get_type().get_named_type_reference() {
219+
Type::named_type_from_type(ntr.name(), &debug_target_type.get_type())
220+
} else {
221+
debug_target_type.get_type()
222+
}
223+
}
217224
None => Type::void(),
218225
};
219226

@@ -335,7 +342,7 @@ pub(crate) fn handle_function<R: ReaderType>(
335342
.unwrap_or("_unnamed_func".to_string());
336343
let ntr =
337344
Type::named_type_from_type(&name, &Type::function(return_type.as_ref(), vec![], false));
338-
debug_info_builder.add_type(get_uid(dwarf, unit, entry), name, ntr, false);
345+
debug_info_builder.add_type(get_uid(dwarf, unit, entry), name, ntr, false, None);
339346

340347
let mut parameters: Vec<FunctionParameter> = vec![];
341348
let mut variable_arguments = false;
@@ -376,21 +383,31 @@ pub(crate) fn handle_function<R: ReaderType>(
376383
};
377384
let name = debug_info_builder_context.get_name(dwarf, unit, child.entry());
378385

379-
let child_type = debug_info_builder
380-
.get_type(child_uid)
381-
.or_else(|| {
382-
log::error!(
383-
"Failed to get function parameter type with uid {}",
384-
child_uid
385-
);
386-
None
387-
})?
388-
.get_type();
389-
parameters.push(FunctionParameter::new(
390-
child_type,
391-
name.unwrap_or_default(),
392-
None,
393-
));
386+
let child_debug_type = debug_info_builder.get_type(child_uid).or_else(|| {
387+
log::error!(
388+
"Failed to get function parameter type with uid {}",
389+
child_uid
390+
);
391+
None
392+
})?;
393+
let child_type = child_debug_type.get_type();
394+
395+
// If this is a typedef, make sure we reference it instead of resolving to the underlying type
396+
if let Some(ntr) = child_type.get_named_type_reference() {
397+
let typedef_type = Type::named_type_from_type(ntr.name(), &child_type);
398+
399+
parameters.push(FunctionParameter::new(
400+
typedef_type,
401+
name.unwrap_or_default(),
402+
None,
403+
));
404+
} else {
405+
parameters.push(FunctionParameter::new(
406+
child_type,
407+
name.unwrap_or_default(),
408+
None,
409+
));
410+
}
394411
} else if child.entry().tag() == constants::DW_TAG_unspecified_parameters {
395412
variable_arguments = true;
396413
}

plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub(crate) struct DebugType {
107107
pub name: String,
108108
pub ty: Ref<Type>,
109109
pub commit: bool,
110+
pub target_type_uid: Option<TypeUID>,
110111
}
111112

112113
impl DebugType {
@@ -363,17 +364,26 @@ impl DebugInfoBuilder {
363364
self.types.values()
364365
}
365366

366-
pub(crate) fn add_type(&mut self, type_uid: TypeUID, name: String, t: Ref<Type>, commit: bool) {
367+
pub(crate) fn add_type(
368+
&mut self,
369+
type_uid: TypeUID,
370+
name: String,
371+
t: Ref<Type>,
372+
commit: bool,
373+
target_type_uid: Option<TypeUID>,
374+
) {
367375
if let Some(DebugType {
368376
name: existing_name,
369377
ty: existing_type,
370378
commit: _,
379+
target_type_uid: _,
371380
}) = self.types.insert(
372381
type_uid,
373382
DebugType {
374383
name: name.clone(),
375384
ty: t.clone(),
376385
commit,
386+
target_type_uid,
377387
},
378388
) {
379389
if existing_type != t && commit {
@@ -608,7 +618,28 @@ impl DebugInfoBuilder {
608618
};
609619

610620
// TODO : Components
611-
debug_info.add_type(&debug_type_name, &debug_type.ty, &[]);
621+
// If it's a typedef resolve one layer down since we'd technically be defining it as a typedef to itself otherwise
622+
if let Some(ntr) = debug_type.get_type().get_named_type_reference() {
623+
if let Some(target_uid) = debug_type.target_type_uid {
624+
if let Some(target_type) = self.get_type(target_uid) {
625+
debug_info.add_type(&debug_type_name, &target_type.get_type(), &[]);
626+
} else {
627+
error!(
628+
"Failed to find typedef {} target for uid {}",
629+
debug_type_name,
630+
ntr.name()
631+
);
632+
}
633+
} else {
634+
error!(
635+
"Failed to find typedef {} target uid for {}",
636+
debug_type_name,
637+
ntr.name()
638+
);
639+
}
640+
} else {
641+
debug_info.add_type(&debug_type_name, &debug_type.ty, &[]);
642+
}
612643
type_uids_by_name.insert(debug_type_name, *debug_type_uid);
613644
}
614645
}

plugins/dwarf/dwarf_import/src/types.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ fn do_structure_parse<R: ReaderType>(
162162
full_name.to_owned(),
163163
ntr,
164164
false,
165+
None,
165166
);
166167
} else {
167168
// We _need_ to have initial typedefs or else we can enter infinite parsing loops
@@ -170,7 +171,7 @@ fn do_structure_parse<R: ReaderType>(
170171
let full_name = format!("anonymous_structure_{:x}", get_uid(dwarf, unit, entry));
171172
let ntr =
172173
Type::named_type_from_type(&full_name, &Type::structure(&structure_builder.finalize()));
173-
debug_info_builder.add_type(get_uid(dwarf, unit, entry), full_name, ntr, false);
174+
debug_info_builder.add_type(get_uid(dwarf, unit, entry), full_name, ntr, false, None);
174175
}
175176

176177
// Get all the children and base classes to populate
@@ -248,6 +249,7 @@ fn do_structure_parse<R: ReaderType>(
248249
} else if let Ok(Some(raw_struct_offset_bits)) =
249250
child_entry.attr(constants::DW_AT_data_bit_offset)
250251
{
252+
//TODO: support misaligned offsets when bitwise data structures get in
251253
let Some(struct_offset_bits) = get_attr_as_u64(&raw_struct_offset_bits)
252254
.or_else(|| get_expr_value(unit, raw_struct_offset_bits))
253255
else {
@@ -314,19 +316,22 @@ fn do_structure_parse<R: ReaderType>(
314316

315317
structure_builder.base_structures(&base_structures);
316318
let finalized_structure = Type::structure(&structure_builder.finalize());
319+
317320
if let Some(full_name) = full_name {
318321
debug_info_builder.add_type(
319322
get_uid(dwarf, unit, entry) + 1, // TODO : This is super broke (uid + 1 is not guaranteed to be unique)
320323
full_name,
321324
finalized_structure,
322325
true,
326+
None,
323327
);
324328
} else {
325329
debug_info_builder.add_type(
326330
get_uid(dwarf, unit, entry),
327331
finalized_structure.to_string(),
328332
finalized_structure,
329333
false, // Don't commit anonymous unions (because I think it'll break things)
334+
None,
330335
);
331336
}
332337
Some(get_uid(dwarf, unit, entry))
@@ -586,7 +591,7 @@ pub(crate) fn get_type<R: ReaderType>(
586591
type_def.to_string()
587592
});
588593

589-
debug_info_builder.add_type(entry_uid, name, type_def, commit);
594+
debug_info_builder.add_type(entry_uid, name, type_def, commit, entry_type);
590595
Some(entry_uid)
591596
} else {
592597
None

0 commit comments

Comments
 (0)