1 use crate::debug::Reader; 2 use crate::debug::transform::AddressTransform; 3 use gimli::constants; 4 use gimli::read; 5 use gimli::write; 6 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 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 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