190ac295eSAlex Crichton use super::address_transform::AddressTransform; 2bd7b59daSPhilip Craig use crate::debug::Reader; 3*c4a38d67SPhilip Craig use gimli::{AttributeValue, RangeListsOffset, UnitRef, write}; 4dd8c48b3SAlex Crichton use wasmtime_environ::DefinedFuncIndex; 5c7cab275SNick Fitzgerald use wasmtime_environ::error::Error; 687c33c29SAlex Crichton 787c33c29SAlex Crichton pub(crate) enum RangeInfoBuilder { 887c33c29SAlex Crichton Undefined, 987c33c29SAlex Crichton Position(u64), 1087c33c29SAlex Crichton Ranges(Vec<(u64, u64)>), 1187c33c29SAlex Crichton Function(DefinedFuncIndex), 1287c33c29SAlex Crichton } 1387c33c29SAlex Crichton 1487c33c29SAlex Crichton impl RangeInfoBuilder { from(entry: &write::ConvertUnitEntry<Reader<'_>>) -> Result<Self, Error>15*c4a38d67SPhilip Craig pub(crate) fn from(entry: &write::ConvertUnitEntry<Reader<'_>>) -> Result<Self, Error> { 167ee620a5SPhilip Craig if let Some(AttributeValue::RangeListsRef(r)) = entry.attr_value(gimli::DW_AT_ranges) { 17*c4a38d67SPhilip Craig let r = entry.read_unit.ranges_offset_from_raw(r); 18*c4a38d67SPhilip Craig return RangeInfoBuilder::from_ranges_ref(entry.read_unit, r); 1987c33c29SAlex Crichton }; 2087c33c29SAlex Crichton 217ee620a5SPhilip Craig let low_pc = if let Some(AttributeValue::Addr(addr)) = entry.attr_value(gimli::DW_AT_low_pc) 227ee620a5SPhilip Craig { 2387c33c29SAlex Crichton addr 2487c33c29SAlex Crichton } else if let Some(AttributeValue::DebugAddrIndex(i)) = 257ee620a5SPhilip Craig entry.attr_value(gimli::DW_AT_low_pc) 2687c33c29SAlex Crichton { 27*c4a38d67SPhilip Craig entry.read_unit.address(i)? 2887c33c29SAlex Crichton } else { 2987c33c29SAlex Crichton return Ok(RangeInfoBuilder::Undefined); 3087c33c29SAlex Crichton }; 3187c33c29SAlex Crichton 3287c33c29SAlex Crichton Ok( 337ee620a5SPhilip Craig if let Some(AttributeValue::Udata(u)) = entry.attr_value(gimli::DW_AT_high_pc) { 3487c33c29SAlex Crichton RangeInfoBuilder::Ranges(vec![(low_pc, low_pc + u)]) 3587c33c29SAlex Crichton } else { 3687c33c29SAlex Crichton RangeInfoBuilder::Position(low_pc) 3787c33c29SAlex Crichton }, 3887c33c29SAlex Crichton ) 3987c33c29SAlex Crichton } 4087c33c29SAlex Crichton from_ranges_ref( unit: UnitRef<'_, Reader<'_>>, ranges: RangeListsOffset, ) -> Result<Self, Error>41bd7b59daSPhilip Craig pub(crate) fn from_ranges_ref( 42*c4a38d67SPhilip Craig unit: UnitRef<'_, Reader<'_>>, 4387c33c29SAlex Crichton ranges: RangeListsOffset, 44bd7b59daSPhilip Craig ) -> Result<Self, Error> { 45bd7b59daSPhilip Craig let mut ranges = unit.ranges(ranges)?; 4687c33c29SAlex Crichton let mut result = Vec::new(); 4787c33c29SAlex Crichton while let Some(range) = ranges.next()? { 4887c33c29SAlex Crichton if range.begin >= range.end { 4987c33c29SAlex Crichton // ignore empty ranges 5087c33c29SAlex Crichton } 5187c33c29SAlex Crichton result.push((range.begin, range.end)); 5287c33c29SAlex Crichton } 5387c33c29SAlex Crichton 5487c33c29SAlex Crichton Ok(if result.is_empty() { 5587c33c29SAlex Crichton RangeInfoBuilder::Undefined 5687c33c29SAlex Crichton } else { 5787c33c29SAlex Crichton RangeInfoBuilder::Ranges(result) 5887c33c29SAlex Crichton }) 5987c33c29SAlex Crichton } 6087c33c29SAlex Crichton from_subprogram_die( entry: &write::ConvertUnitEntry<Reader<'_>>, addr_tr: &AddressTransform, ) -> Result<Self, Error>61bd7b59daSPhilip Craig pub(crate) fn from_subprogram_die( 62*c4a38d67SPhilip Craig entry: &write::ConvertUnitEntry<Reader<'_>>, 6387c33c29SAlex Crichton addr_tr: &AddressTransform, 64bd7b59daSPhilip Craig ) -> Result<Self, Error> { 65*c4a38d67SPhilip Craig let unit = entry.read_unit; 667ee620a5SPhilip Craig let addr = if let Some(AttributeValue::Addr(addr)) = entry.attr_value(gimli::DW_AT_low_pc) { 6787c33c29SAlex Crichton addr 6887c33c29SAlex Crichton } else if let Some(AttributeValue::DebugAddrIndex(i)) = 697ee620a5SPhilip Craig entry.attr_value(gimli::DW_AT_low_pc) 7087c33c29SAlex Crichton { 71bd7b59daSPhilip Craig unit.address(i)? 727ee620a5SPhilip Craig } else if let Some(AttributeValue::RangeListsRef(r)) = entry.attr_value(gimli::DW_AT_ranges) 7387c33c29SAlex Crichton { 74bd7b59daSPhilip Craig let r = unit.ranges_offset_from_raw(r); 75bd7b59daSPhilip Craig let mut ranges = unit.ranges(r)?; 7687c33c29SAlex Crichton if let Some(range) = ranges.next()? { 7787c33c29SAlex Crichton range.begin 7887c33c29SAlex Crichton } else { 7987c33c29SAlex Crichton return Ok(RangeInfoBuilder::Undefined); 8087c33c29SAlex Crichton } 8187c33c29SAlex Crichton } else { 8287c33c29SAlex Crichton return Ok(RangeInfoBuilder::Undefined); 8387c33c29SAlex Crichton }; 8487c33c29SAlex Crichton 8587c33c29SAlex Crichton let index = addr_tr.find_func_index(addr); 8687c33c29SAlex Crichton if index.is_none() { 8787c33c29SAlex Crichton return Ok(RangeInfoBuilder::Undefined); 8887c33c29SAlex Crichton } 8987c33c29SAlex Crichton Ok(RangeInfoBuilder::Function(index.unwrap())) 9087c33c29SAlex Crichton } 9187c33c29SAlex Crichton build( &self, addr_tr: &AddressTransform, out_unit: &mut write::Unit, current_scope_id: write::UnitEntryId, )9287c33c29SAlex Crichton pub(crate) fn build( 9387c33c29SAlex Crichton &self, 9487c33c29SAlex Crichton addr_tr: &AddressTransform, 9587c33c29SAlex Crichton out_unit: &mut write::Unit, 9687c33c29SAlex Crichton current_scope_id: write::UnitEntryId, 9787c33c29SAlex Crichton ) { 9887c33c29SAlex Crichton match self { 9987c33c29SAlex Crichton RangeInfoBuilder::Undefined => (), 10087c33c29SAlex Crichton RangeInfoBuilder::Position(pc) => { 10187c33c29SAlex Crichton let addr = addr_tr 10287c33c29SAlex Crichton .translate(*pc) 10387c33c29SAlex Crichton .unwrap_or(write::Address::Constant(0)); 10487c33c29SAlex Crichton let current_scope = out_unit.get_mut(current_scope_id); 10587c33c29SAlex Crichton current_scope.set(gimli::DW_AT_low_pc, write::AttributeValue::Address(addr)); 10687c33c29SAlex Crichton } 10787c33c29SAlex Crichton RangeInfoBuilder::Ranges(ranges) => { 10887c33c29SAlex Crichton let mut result = Vec::new(); 10987c33c29SAlex Crichton for (begin, end) in ranges { 11087c33c29SAlex Crichton result.extend(addr_tr.translate_ranges(*begin, *end)); 11187c33c29SAlex Crichton } 11233cc4959SAlex Crichton 11333cc4959SAlex Crichton // If we're seeing the ranges for a `DW_TAG_compile_unit` DIE 11433cc4959SAlex Crichton // then don't use `DW_AT_low_pc` and `DW_AT_high_pc`. These 11533cc4959SAlex Crichton // attributes, if set, will configure the base address of all 11633cc4959SAlex Crichton // location lists that this unit refers to. Currently this 11733cc4959SAlex Crichton // debug transform does not take this base address into account 11833cc4959SAlex Crichton // when generate the `.debug_loc` section. Consequently when a 11933cc4959SAlex Crichton // compile unit is configured here the `DW_AT_ranges` attribute 12033cc4959SAlex Crichton // is unconditionally used instead of 12133cc4959SAlex Crichton // `DW_AT_low_pc`/`DW_AT_high_pc`. 12233cc4959SAlex Crichton let is_attr_for_compile_unit = 12333cc4959SAlex Crichton out_unit.get(current_scope_id).tag() == gimli::DW_TAG_compile_unit; 12433cc4959SAlex Crichton 12533cc4959SAlex Crichton if result.len() != 1 || is_attr_for_compile_unit { 12687c33c29SAlex Crichton let range_list = result 12787c33c29SAlex Crichton .iter() 12887c33c29SAlex Crichton .map(|tr| write::Range::StartLength { 12987c33c29SAlex Crichton begin: tr.0, 13087c33c29SAlex Crichton length: tr.1, 13187c33c29SAlex Crichton }) 13287c33c29SAlex Crichton .collect::<Vec<_>>(); 13387c33c29SAlex Crichton let range_list_id = out_unit.ranges.add(write::RangeList(range_list)); 13487c33c29SAlex Crichton let current_scope = out_unit.get_mut(current_scope_id); 13587c33c29SAlex Crichton current_scope.set( 13687c33c29SAlex Crichton gimli::DW_AT_ranges, 13787c33c29SAlex Crichton write::AttributeValue::RangeListRef(range_list_id), 13887c33c29SAlex Crichton ); 13987c33c29SAlex Crichton } else { 14087c33c29SAlex Crichton let current_scope = out_unit.get_mut(current_scope_id); 14187c33c29SAlex Crichton current_scope.set( 14287c33c29SAlex Crichton gimli::DW_AT_low_pc, 14387c33c29SAlex Crichton write::AttributeValue::Address(result[0].0), 14487c33c29SAlex Crichton ); 14587c33c29SAlex Crichton current_scope.set( 14687c33c29SAlex Crichton gimli::DW_AT_high_pc, 14787c33c29SAlex Crichton write::AttributeValue::Udata(result[0].1), 14887c33c29SAlex Crichton ); 14987c33c29SAlex Crichton } 15087c33c29SAlex Crichton } 15187c33c29SAlex Crichton RangeInfoBuilder::Function(index) => { 152dd8c48b3SAlex Crichton let symbol = addr_tr.map()[*index].symbol; 15387c33c29SAlex Crichton let range = addr_tr.func_range(*index); 15487c33c29SAlex Crichton let addr = write::Address::Symbol { 15587c33c29SAlex Crichton symbol, 15687c33c29SAlex Crichton addend: range.0 as i64, 15787c33c29SAlex Crichton }; 15887c33c29SAlex Crichton let len = (range.1 - range.0) as u64; 15987c33c29SAlex Crichton let current_scope = out_unit.get_mut(current_scope_id); 16087c33c29SAlex Crichton current_scope.set(gimli::DW_AT_low_pc, write::AttributeValue::Address(addr)); 16187c33c29SAlex Crichton current_scope.set(gimli::DW_AT_high_pc, write::AttributeValue::Udata(len)); 16287c33c29SAlex Crichton } 16387c33c29SAlex Crichton } 16487c33c29SAlex Crichton } 16587c33c29SAlex Crichton get_ranges(&self, addr_tr: &AddressTransform) -> Vec<(u64, u64)>16687c33c29SAlex Crichton pub(crate) fn get_ranges(&self, addr_tr: &AddressTransform) -> Vec<(u64, u64)> { 16787c33c29SAlex Crichton match self { 16887c33c29SAlex Crichton RangeInfoBuilder::Undefined | RangeInfoBuilder::Position(_) => vec![], 16987c33c29SAlex Crichton RangeInfoBuilder::Ranges(ranges) => ranges.clone(), 17087c33c29SAlex Crichton RangeInfoBuilder::Function(index) => { 17187c33c29SAlex Crichton let range = addr_tr.func_source_range(*index); 17287c33c29SAlex Crichton vec![(range.0, range.1)] 17387c33c29SAlex Crichton } 17487c33c29SAlex Crichton } 17587c33c29SAlex Crichton } 17687c33c29SAlex Crichton build_ranges( &self, addr_tr: &AddressTransform, out_range_lists: &mut write::RangeListTable, ) -> write::RangeListId17787c33c29SAlex Crichton pub(crate) fn build_ranges( 17887c33c29SAlex Crichton &self, 17987c33c29SAlex Crichton addr_tr: &AddressTransform, 18087c33c29SAlex Crichton out_range_lists: &mut write::RangeListTable, 18187c33c29SAlex Crichton ) -> write::RangeListId { 18287c33c29SAlex Crichton if let RangeInfoBuilder::Ranges(ranges) = self { 18387c33c29SAlex Crichton let mut range_list = Vec::new(); 18487c33c29SAlex Crichton for (begin, end) in ranges { 1851321c234SAlex Crichton assert!(begin < end); 18687c33c29SAlex Crichton range_list.extend(addr_tr.translate_ranges(*begin, *end).map(|tr| { 18787c33c29SAlex Crichton write::Range::StartLength { 18887c33c29SAlex Crichton begin: tr.0, 18987c33c29SAlex Crichton length: tr.1, 19087c33c29SAlex Crichton } 19187c33c29SAlex Crichton })); 19287c33c29SAlex Crichton } 19387c33c29SAlex Crichton out_range_lists.add(write::RangeList(range_list)) 19487c33c29SAlex Crichton } else { 19587c33c29SAlex Crichton unreachable!(); 19687c33c29SAlex Crichton } 19787c33c29SAlex Crichton } 19887c33c29SAlex Crichton } 199