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