1 use crate::debug::Reader;
2 use crate::debug::transform::AddressTransform;
3 use gimli::constants;
4 use gimli::read;
5 use gimli::write;
6
build_dependencies( filter: &mut write::FilterUnitSection<'_, Reader<'_>>, at: &AddressTransform, ) -> write::ConvertResult<()>7 pub fn build_dependencies(
8 filter: &mut write::FilterUnitSection<'_, Reader<'_>>,
9 at: &AddressTransform,
10 ) -> write::ConvertResult<()> {
11 while let Some(mut unit) = filter.read_unit()? {
12 build_die_dependencies(&mut unit, at)?;
13 }
14 Ok(())
15 }
16
has_valid_code_range( die: &write::FilterUnitEntry<'_, Reader<'_>>, at: &AddressTransform, ) -> read::Result<bool>17 fn has_valid_code_range(
18 die: &write::FilterUnitEntry<'_, Reader<'_>>,
19 at: &AddressTransform,
20 ) -> read::Result<bool> {
21 let unit = die.read_unit;
22 match die.tag {
23 constants::DW_TAG_subprogram => {
24 if let Some(ranges_attr) = die.attr_value(constants::DW_AT_ranges) {
25 let offset = match ranges_attr {
26 read::AttributeValue::RangeListsRef(val) => unit.ranges_offset_from_raw(val),
27 read::AttributeValue::DebugRngListsIndex(index) => unit.ranges_offset(index)?,
28 _ => return Ok(false),
29 };
30 let mut has_valid_base = if let Some(read::AttributeValue::Addr(low_pc)) =
31 die.attr_value(constants::DW_AT_low_pc)
32 {
33 Some(at.can_translate_address(low_pc))
34 } else {
35 None
36 };
37 let mut it = unit.raw_ranges(offset)?;
38 while let Some(range) = it.next()? {
39 // If at least one of the range addresses can be converted,
40 // declaring code range as valid.
41 match range {
42 read::RawRngListEntry::AddressOrOffsetPair { .. }
43 if has_valid_base.is_some() =>
44 {
45 if has_valid_base.unwrap() {
46 return Ok(true);
47 }
48 }
49 read::RawRngListEntry::StartEnd { begin, .. }
50 | read::RawRngListEntry::StartLength { begin, .. }
51 | read::RawRngListEntry::AddressOrOffsetPair { begin, .. } => {
52 if at.can_translate_address(begin) {
53 return Ok(true);
54 }
55 }
56 read::RawRngListEntry::StartxEndx { begin, .. }
57 | read::RawRngListEntry::StartxLength { begin, .. } => {
58 let addr = unit.address(begin)?;
59 if at.can_translate_address(addr) {
60 return Ok(true);
61 }
62 }
63 read::RawRngListEntry::BaseAddress { addr } => {
64 has_valid_base = Some(at.can_translate_address(addr));
65 }
66 read::RawRngListEntry::BaseAddressx { addr } => {
67 let addr = unit.address(addr)?;
68 has_valid_base = Some(at.can_translate_address(addr));
69 }
70 read::RawRngListEntry::OffsetPair { .. } => (),
71 }
72 }
73 return Ok(false);
74 } else if let Some(low_pc) = die.attr_value(constants::DW_AT_low_pc) {
75 if let read::AttributeValue::Addr(a) = low_pc {
76 return Ok(at.can_translate_address(a));
77 } else if let read::AttributeValue::DebugAddrIndex(i) = low_pc {
78 let a = unit.address(i)?;
79 return Ok(at.can_translate_address(a));
80 }
81 }
82 }
83 _ => (),
84 }
85 Ok(false)
86 }
87
build_die_dependencies( unit: &mut write::FilterUnit<'_, Reader<'_>>, at: &AddressTransform, ) -> write::ConvertResult<()>88 fn build_die_dependencies(
89 unit: &mut write::FilterUnit<'_, Reader<'_>>,
90 at: &AddressTransform,
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);
96 }
97 }
98 Ok(())
99 }
100