|
1 | 1 | use crate::debug::Reader; |
2 | 2 | use crate::debug::transform::AddressTransform; |
3 | | -use gimli::UnitSectionOffset; |
4 | 3 | use gimli::constants; |
5 | 4 | use gimli::read; |
6 | | -use std::collections::{HashMap, HashSet}; |
7 | | - |
8 | | -#[derive(Debug)] |
9 | | -pub struct Dependencies { |
10 | | - edges: HashMap<UnitSectionOffset, HashSet<UnitSectionOffset>>, |
11 | | - roots: HashSet<UnitSectionOffset>, |
12 | | -} |
13 | | - |
14 | | -impl Dependencies { |
15 | | - fn new() -> Dependencies { |
16 | | - Dependencies { |
17 | | - edges: HashMap::new(), |
18 | | - roots: HashSet::new(), |
19 | | - } |
20 | | - } |
21 | | - |
22 | | - fn add_edge(&mut self, a: UnitSectionOffset, b: UnitSectionOffset) { |
23 | | - use std::collections::hash_map::Entry; |
24 | | - match self.edges.entry(a) { |
25 | | - Entry::Occupied(mut o) => { |
26 | | - o.get_mut().insert(b); |
27 | | - } |
28 | | - Entry::Vacant(v) => { |
29 | | - let mut set = HashSet::new(); |
30 | | - set.insert(b); |
31 | | - v.insert(set); |
32 | | - } |
33 | | - } |
34 | | - } |
35 | | - |
36 | | - fn add_root(&mut self, root: UnitSectionOffset) { |
37 | | - self.roots.insert(root); |
38 | | - } |
39 | | - |
40 | | - pub fn get_reachable(&self) -> HashSet<UnitSectionOffset> { |
41 | | - let mut reachable = self.roots.clone(); |
42 | | - let mut queue = Vec::new(); |
43 | | - for i in self.roots.iter() { |
44 | | - if let Some(deps) = self.edges.get(i) { |
45 | | - for j in deps { |
46 | | - if reachable.contains(j) { |
47 | | - continue; |
48 | | - } |
49 | | - reachable.insert(*j); |
50 | | - queue.push(*j); |
51 | | - } |
52 | | - } |
53 | | - } |
54 | | - while let Some(i) = queue.pop() { |
55 | | - if let Some(deps) = self.edges.get(&i) { |
56 | | - for j in deps { |
57 | | - if reachable.contains(j) { |
58 | | - continue; |
59 | | - } |
60 | | - reachable.insert(*j); |
61 | | - queue.push(*j); |
62 | | - } |
63 | | - } |
64 | | - } |
65 | | - reachable |
66 | | - } |
67 | | -} |
| 5 | +use gimli::write; |
68 | 6 |
|
69 | 7 | pub fn build_dependencies( |
70 | | - dwarf: &read::Dwarf<Reader<'_>>, |
| 8 | + filter: &mut write::FilterUnitSection<'_, Reader<'_>>, |
71 | 9 | at: &AddressTransform, |
72 | | -) -> read::Result<Dependencies> { |
73 | | - let mut deps = Dependencies::new(); |
74 | | - let mut units = dwarf.units(); |
75 | | - while let Some(unit) = units.next()? { |
76 | | - build_unit_dependencies(unit, dwarf, at, &mut deps)?; |
| 10 | +) -> write::ConvertResult<()> { |
| 11 | + while let Some(mut unit) = filter.read_unit()? { |
| 12 | + build_die_dependencies(&mut unit, at)?; |
77 | 13 | } |
78 | | - Ok(deps) |
79 | | -} |
80 | | - |
81 | | -fn build_unit_dependencies( |
82 | | - header: read::UnitHeader<Reader<'_>>, |
83 | | - dwarf: &read::Dwarf<Reader<'_>>, |
84 | | - at: &AddressTransform, |
85 | | - deps: &mut Dependencies, |
86 | | -) -> read::Result<()> { |
87 | | - let unit = dwarf.unit(header)?; |
88 | | - let unit = unit.unit_ref(dwarf); |
89 | | - let mut tree = unit.entries_tree(None)?; |
90 | | - let root = tree.root()?; |
91 | | - build_die_dependencies(root, unit, at, deps)?; |
92 | 14 | Ok(()) |
93 | 15 | } |
94 | 16 |
|
95 | | -fn has_die_back_edge(die: &read::DebuggingInformationEntry<Reader<'_>>) -> read::Result<bool> { |
96 | | - // DIEs can be broadly divided into three categories: |
97 | | - // 1. Extensions of their parents; effectively attributes: DW_TAG_variable, DW_TAG_member, etc. |
98 | | - // 2. Standalone entities referred to by other DIEs via 'reference' class attributes: types. |
99 | | - // 3. Structural entities that organize how the above relate to each other: namespaces. |
100 | | - // Here, we must make sure to return 'true' for DIEs in the first category since stripping them, |
101 | | - // provided their parent is alive, is always wrong. To be conservatively correct in the face |
102 | | - // of new/vendor tags, we maintain a "(mostly) known good" list of tags of the latter categories. |
103 | | - let result = match die.tag() { |
104 | | - constants::DW_TAG_array_type |
105 | | - | constants::DW_TAG_atomic_type |
106 | | - | constants::DW_TAG_base_type |
107 | | - | constants::DW_TAG_class_type |
108 | | - | constants::DW_TAG_const_type |
109 | | - | constants::DW_TAG_dwarf_procedure |
110 | | - | constants::DW_TAG_entry_point |
111 | | - | constants::DW_TAG_enumeration_type |
112 | | - | constants::DW_TAG_pointer_type |
113 | | - | constants::DW_TAG_ptr_to_member_type |
114 | | - | constants::DW_TAG_reference_type |
115 | | - | constants::DW_TAG_restrict_type |
116 | | - | constants::DW_TAG_rvalue_reference_type |
117 | | - | constants::DW_TAG_string_type |
118 | | - | constants::DW_TAG_structure_type |
119 | | - | constants::DW_TAG_typedef |
120 | | - | constants::DW_TAG_union_type |
121 | | - | constants::DW_TAG_unspecified_type |
122 | | - | constants::DW_TAG_volatile_type |
123 | | - | constants::DW_TAG_coarray_type |
124 | | - | constants::DW_TAG_common_block |
125 | | - | constants::DW_TAG_dynamic_type |
126 | | - | constants::DW_TAG_file_type |
127 | | - | constants::DW_TAG_immutable_type |
128 | | - | constants::DW_TAG_interface_type |
129 | | - | constants::DW_TAG_set_type |
130 | | - | constants::DW_TAG_shared_type |
131 | | - | constants::DW_TAG_subroutine_type |
132 | | - | constants::DW_TAG_packed_type |
133 | | - | constants::DW_TAG_template_alias |
134 | | - | constants::DW_TAG_namelist |
135 | | - | constants::DW_TAG_namespace |
136 | | - | constants::DW_TAG_imported_unit |
137 | | - | constants::DW_TAG_imported_declaration |
138 | | - | constants::DW_TAG_imported_module |
139 | | - | constants::DW_TAG_module => false, |
140 | | - constants::DW_TAG_subprogram => die.attr(constants::DW_AT_declaration).is_some(), |
141 | | - _ => true, |
142 | | - }; |
143 | | - Ok(result) |
144 | | -} |
145 | | - |
146 | 17 | fn has_valid_code_range( |
147 | | - die: &read::DebuggingInformationEntry<Reader<'_>>, |
148 | | - unit: read::UnitRef<Reader<'_>>, |
| 18 | + die: &write::FilterUnitEntry<'_, Reader<'_>>, |
149 | 19 | at: &AddressTransform, |
150 | 20 | ) -> read::Result<bool> { |
151 | | - match die.tag() { |
| 21 | + let unit = die.read_unit; |
| 22 | + match die.tag { |
152 | 23 | constants::DW_TAG_subprogram => { |
153 | 24 | if let Some(ranges_attr) = die.attr_value(constants::DW_AT_ranges) { |
154 | 25 | let offset = match ranges_attr { |
@@ -215,50 +86,14 @@ fn has_valid_code_range( |
215 | 86 | } |
216 | 87 |
|
217 | 88 | fn build_die_dependencies( |
218 | | - die: read::EntriesTreeNode<Reader<'_>>, |
219 | | - unit: read::UnitRef<Reader<'_>>, |
| 89 | + unit: &mut write::FilterUnit<'_, Reader<'_>>, |
220 | 90 | at: &AddressTransform, |
221 | | - deps: &mut Dependencies, |
222 | | -) -> read::Result<()> { |
223 | | - let entry = die.entry(); |
224 | | - let offset = entry.offset().to_unit_section_offset(&unit); |
225 | | - for attr in entry.attrs() { |
226 | | - build_attr_dependencies(attr, offset, unit, at, deps)?; |
227 | | - } |
228 | | - |
229 | | - let mut children = die.children(); |
230 | | - while let Some(child) = children.next()? { |
231 | | - let child_entry = child.entry(); |
232 | | - let child_offset = child_entry.offset().to_unit_section_offset(&unit); |
233 | | - deps.add_edge(child_offset, offset); |
234 | | - if has_die_back_edge(child_entry)? { |
235 | | - deps.add_edge(offset, child_offset); |
236 | | - } |
237 | | - if has_valid_code_range(child_entry, unit, at)? { |
238 | | - deps.add_root(child_offset); |
| 91 | +) -> write::ConvertResult<()> { |
| 92 | + let mut die = write::FilterUnitEntry::null(unit.read_unit); |
| 93 | + while unit.read_entry(&mut die)? { |
| 94 | + if has_valid_code_range(&die, at)? { |
| 95 | + unit.require_entry(die.offset); |
239 | 96 | } |
240 | | - build_die_dependencies(child, unit, at, deps)?; |
241 | | - } |
242 | | - Ok(()) |
243 | | -} |
244 | | - |
245 | | -fn build_attr_dependencies( |
246 | | - attr: &read::Attribute<Reader<'_>>, |
247 | | - offset: UnitSectionOffset, |
248 | | - unit: read::UnitRef<Reader<'_>>, |
249 | | - _at: &AddressTransform, |
250 | | - deps: &mut Dependencies, |
251 | | -) -> read::Result<()> { |
252 | | - match attr.value() { |
253 | | - read::AttributeValue::UnitRef(val) => { |
254 | | - let ref_offset = val.to_unit_section_offset(&unit); |
255 | | - deps.add_edge(offset, ref_offset); |
256 | | - } |
257 | | - read::AttributeValue::DebugInfoRef(val) => { |
258 | | - let ref_offset = UnitSectionOffset(val.0); |
259 | | - deps.add_edge(offset, ref_offset); |
260 | | - } |
261 | | - _ => (), |
262 | 97 | } |
263 | 98 | Ok(()) |
264 | 99 | } |
0 commit comments