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