padlock_dwarf/
type_resolver.rs1use gimli::{Reader, Unit, UnitOffset};
4use padlock_core::ir::TypeInfo;
5
6use crate::extractor::Extractor;
7
8impl<'a, R: Reader> Extractor<'a, R> {
9 pub fn resolve_type(
11 &self,
12 unit: &Unit<R>,
13 offset: UnitOffset<R::Offset>,
14 ) -> anyhow::Result<(usize, usize, TypeInfo)> {
15 let mut entries = unit.entries_at_offset(offset)?;
16 let (_, entry) = entries
17 .next_dfs()?
18 .ok_or_else(|| anyhow::anyhow!("no DIE at offset"))?;
19
20 match entry.tag() {
21 gimli::DW_TAG_base_type => {
22 let name = self
23 .attr_string(unit, entry, gimli::DW_AT_name)?
24 .unwrap_or_default();
25 let size = self.attr_usize(entry, gimli::DW_AT_byte_size)?.unwrap_or(0);
26 let align = self
27 .attr_usize(entry, gimli::DW_AT_alignment)?
28 .unwrap_or(size);
29
30 Ok((size, align, TypeInfo::Primitive { name, size, align }))
31 }
32
33 gimli::DW_TAG_pointer_type | gimli::DW_TAG_reference_type => {
34 let size = self.arch.pointer_size;
35 Ok((size, size, TypeInfo::Pointer { size, align: size }))
36 }
37
38 gimli::DW_TAG_typedef => {
39 let inner_offset = match entry.attr_value(gimli::DW_AT_type)? {
40 Some(gimli::AttributeValue::UnitRef(off)) => off,
41 _ => return Err(anyhow::anyhow!("typedef with no type")),
42 };
43 self.resolve_type(unit, inner_offset)
44 }
45
46 gimli::DW_TAG_const_type
47 | gimli::DW_TAG_volatile_type
48 | gimli::DW_TAG_restrict_type => {
49 let inner_offset = match entry.attr_value(gimli::DW_AT_type)? {
50 Some(gimli::AttributeValue::UnitRef(off)) => off,
51 _ => return Err(anyhow::anyhow!("qualifier with no type")),
52 };
53 self.resolve_type(unit, inner_offset)
54 }
55
56 gimli::DW_TAG_array_type => {
57 let elem_offset = match entry.attr_value(gimli::DW_AT_type)? {
58 Some(gimli::AttributeValue::UnitRef(off)) => off,
59 _ => return Err(anyhow::anyhow!("array with no element type")),
60 };
61 let (elem_size, elem_align, elem_ty) = self.resolve_type(unit, elem_offset)?;
62
63 let count = self.extract_array_count(unit, entry)?;
64 let total = elem_size * count;
65
66 Ok((
67 total,
68 elem_align,
69 TypeInfo::Array {
70 element: Box::new(elem_ty),
71 count,
72 size: total,
73 align: elem_align,
74 },
75 ))
76 }
77
78 gimli::DW_TAG_structure_type => {
79 if let Some(layout) = self.extract_struct(unit, entry)? {
80 let size = layout.total_size;
81 let align = layout.align;
82 Ok((size, align, TypeInfo::Struct(Box::new(layout))))
83 } else {
84 let size = self.attr_usize(entry, gimli::DW_AT_byte_size)?.unwrap_or(0);
85 Ok((
86 size,
87 size,
88 TypeInfo::Opaque {
89 name: "<incomplete>".to_string(),
90 size,
91 align: size,
92 },
93 ))
94 }
95 }
96
97 gimli::DW_TAG_enumeration_type => {
98 let size = self.attr_usize(entry, gimli::DW_AT_byte_size)?.unwrap_or(4);
99 let name = self
100 .attr_string(unit, entry, gimli::DW_AT_name)?
101 .unwrap_or_default();
102 Ok((
103 size,
104 size,
105 TypeInfo::Opaque {
106 name,
107 size,
108 align: size,
109 },
110 ))
111 }
112
113 _ => {
114 let size = self.attr_usize(entry, gimli::DW_AT_byte_size)?.unwrap_or(0);
115 Ok((
116 size,
117 size,
118 TypeInfo::Opaque {
119 name: format!("<{:?}>", entry.tag()),
120 size,
121 align: size,
122 },
123 ))
124 }
125 }
126 }
127}