diff options
Diffstat (limited to 'vendor/addr2line/src/function.rs')
-rw-r--r-- | vendor/addr2line/src/function.rs | 133 |
1 files changed, 77 insertions, 56 deletions
diff --git a/vendor/addr2line/src/function.rs b/vendor/addr2line/src/function.rs index 44dc73f24..09c19e01e 100644 --- a/vendor/addr2line/src/function.rs +++ b/vendor/addr2line/src/function.rs @@ -5,7 +5,7 @@ use core::iter; use crate::lazy::LazyCell; use crate::maybe_small; -use crate::{Error, RangeAttributes, ResDwarf}; +use crate::{Context, DebugFile, Error, RangeAttributes}; pub(crate) struct Functions<R: gimli::Reader> { /// List of all `DW_TAG_subprogram` details in the unit. @@ -49,13 +49,16 @@ pub(crate) struct InlinedFunctionAddress { pub(crate) struct InlinedFunction<R: gimli::Reader> { pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>, pub(crate) name: Option<R>, - pub(crate) call_file: u64, + pub(crate) call_file: Option<u64>, pub(crate) call_line: u32, pub(crate) call_column: u32, } impl<R: gimli::Reader> Functions<R> { - pub(crate) fn parse(unit: &gimli::Unit<R>, dwarf: &ResDwarf<R>) -> Result<Functions<R>, Error> { + pub(crate) fn parse( + unit: &gimli::Unit<R>, + sections: &gimli::Dwarf<R>, + ) -> Result<Functions<R>, Error> { let mut functions = Vec::new(); let mut addresses = Vec::new(); let mut entries = unit.entries_raw(None)?; @@ -73,8 +76,7 @@ impl<R: gimli::Reader> Functions<R> { ranges.low_pc = Some(val) } gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.low_pc = - Some(dwarf.sections.address(unit, index)?); + ranges.low_pc = Some(sections.address(unit, index)?); } _ => {} }, @@ -83,8 +85,7 @@ impl<R: gimli::Reader> Functions<R> { ranges.high_pc = Some(val) } gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.high_pc = - Some(dwarf.sections.address(unit, index)?); + ranges.high_pc = Some(sections.address(unit, index)?); } gimli::AttributeValue::Udata(val) => { ranges.size = Some(val) @@ -92,9 +93,8 @@ impl<R: gimli::Reader> Functions<R> { _ => {} }, gimli::DW_AT_ranges => { - ranges.ranges_offset = dwarf - .sections - .attr_ranges_offset(unit, attr.value())?; + ranges.ranges_offset = + sections.attr_ranges_offset(unit, attr.value())?; } _ => {} }; @@ -104,7 +104,7 @@ impl<R: gimli::Reader> Functions<R> { } let function_index = functions.len(); - if ranges.for_each_range(&dwarf.sections, unit, |range| { + if ranges.for_each_range(sections, unit, |range| { addresses.push(FunctionAddress { range, function: function_index, @@ -150,13 +150,15 @@ impl<R: gimli::Reader> Functions<R> { pub(crate) fn parse_inlined_functions( &self, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, ) -> Result<(), Error> { for function in &*self.functions { function .1 - .borrow_with(|| Function::parse(function.0, unit, dwarf)) + .borrow_with(|| Function::parse(function.0, file, unit, ctx, sections)) .as_ref() .map_err(Error::clone)?; } @@ -167,8 +169,10 @@ impl<R: gimli::Reader> Functions<R> { impl<R: gimli::Reader> Function<R> { pub(crate) fn parse( dw_die_offset: gimli::UnitOffset<R::Offset>, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, ) -> Result<Self, Error> { let mut entries = unit.entries_raw(Some(dw_die_offset))?; let depth = entries.next_depth(); @@ -181,18 +185,18 @@ impl<R: gimli::Reader> Function<R> { Ok(ref attr) => { match attr.name() { gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { name = Some(val); } } gimli::DW_AT_name => { if name.is_none() { - name = dwarf.sections.attr_string(unit, attr.value()).ok(); + name = sections.attr_string(unit, attr.value()).ok(); } } gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { if name.is_none() { - name = name_attr(attr.value(), unit, dwarf, 16)?; + name = name_attr(attr.value(), file, unit, ctx, sections, 16)?; } } _ => {} @@ -207,8 +211,10 @@ impl<R: gimli::Reader> Function<R> { Function::parse_children( &mut entries, depth, + file, unit, - dwarf, + ctx, + sections, &mut inlined_functions, &mut inlined_addresses, 0, @@ -247,10 +253,12 @@ impl<R: gimli::Reader> Function<R> { } fn parse_children( - entries: &mut gimli::EntriesRaw<R>, + entries: &mut gimli::EntriesRaw<'_, '_, R>, depth: isize, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, inlined_functions: &mut Vec<InlinedFunction<R>>, inlined_addresses: &mut Vec<InlinedFunctionAddress>, inlined_depth: usize, @@ -272,8 +280,10 @@ impl<R: gimli::Reader> Function<R> { entries, abbrev, next_depth, + file, unit, - dwarf, + ctx, + sections, inlined_functions, inlined_addresses, inlined_depth, @@ -288,7 +298,7 @@ impl<R: gimli::Reader> Function<R> { } fn skip( - entries: &mut gimli::EntriesRaw<R>, + entries: &mut gimli::EntriesRaw<'_, '_, R>, abbrev: &gimli::Abbreviation, depth: isize, ) -> Result<(), Error> { @@ -344,18 +354,20 @@ impl<R: gimli::Reader> Function<R> { impl<R: gimli::Reader> InlinedFunction<R> { fn parse( dw_die_offset: gimli::UnitOffset<R::Offset>, - entries: &mut gimli::EntriesRaw<R>, + entries: &mut gimli::EntriesRaw<'_, '_, R>, abbrev: &gimli::Abbreviation, depth: isize, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, inlined_functions: &mut Vec<InlinedFunction<R>>, inlined_addresses: &mut Vec<InlinedFunctionAddress>, inlined_depth: usize, ) -> Result<(), Error> { let mut ranges = RangeAttributes::default(); let mut name = None; - let mut call_file = 0; + let mut call_file = None; let mut call_line = 0; let mut call_column = 0; for spec in abbrev.attributes() { @@ -364,40 +376,50 @@ impl<R: gimli::Reader> InlinedFunction<R> { gimli::DW_AT_low_pc => match attr.value() { gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val), gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.low_pc = Some(dwarf.sections.address(unit, index)?); + ranges.low_pc = Some(sections.address(unit, index)?); } _ => {} }, gimli::DW_AT_high_pc => match attr.value() { gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val), gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.high_pc = Some(dwarf.sections.address(unit, index)?); + ranges.high_pc = Some(sections.address(unit, index)?); } gimli::AttributeValue::Udata(val) => ranges.size = Some(val), _ => {} }, gimli::DW_AT_ranges => { - ranges.ranges_offset = - dwarf.sections.attr_ranges_offset(unit, attr.value())?; + ranges.ranges_offset = sections.attr_ranges_offset(unit, attr.value())?; } gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { name = Some(val); } } gimli::DW_AT_name => { if name.is_none() { - name = dwarf.sections.attr_string(unit, attr.value()).ok(); + name = sections.attr_string(unit, attr.value()).ok(); } } gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { if name.is_none() { - name = name_attr(attr.value(), unit, dwarf, 16)?; + name = name_attr(attr.value(), file, unit, ctx, sections, 16)?; } } gimli::DW_AT_call_file => { + // There is a spec issue [1] with how DW_AT_call_file is specified in DWARF 5. + // Before, a file index of 0 would indicate no source file, however in + // DWARF 5 this could be a valid index into the file table. + // + // Implementations such as LLVM generates a file index of 0 when DWARF 5 is + // used. + // + // Thus, if we see a version of 5 or later, treat a file index of 0 as such. + // [1]: http://wiki.dwarfstd.org/index.php?title=DWARF5_Line_Table_File_Numbers if let gimli::AttributeValue::FileIndex(fi) = attr.value() { - call_file = fi; + if fi > 0 || unit.header.version() >= 5 { + call_file = Some(fi); + } } } gimli::DW_AT_call_line => { @@ -421,7 +443,7 @@ impl<R: gimli::Reader> InlinedFunction<R> { call_column, }); - ranges.for_each_range(&dwarf.sections, unit, |range| { + ranges.for_each_range(sections, unit, |range| { inlined_addresses.push(InlinedFunctionAddress { range, call_depth: inlined_depth, @@ -432,8 +454,10 @@ impl<R: gimli::Reader> InlinedFunction<R> { Function::parse_children( entries, depth, + file, unit, - dwarf, + ctx, + sections, inlined_functions, inlined_addresses, inlined_depth + 1, @@ -443,8 +467,10 @@ impl<R: gimli::Reader> InlinedFunction<R> { fn name_attr<R>( attr: gimli::AttributeValue<R>, + mut file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, recursion_limit: usize, ) -> Result<Option<R>, Error> where @@ -455,25 +481,18 @@ where } match attr { - gimli::AttributeValue::UnitRef(offset) => name_entry(unit, offset, dwarf, recursion_limit), + gimli::AttributeValue::UnitRef(offset) => { + name_entry(file, unit, offset, ctx, sections, recursion_limit) + } gimli::AttributeValue::DebugInfoRef(dr) => { - let res_unit = dwarf.find_unit(dr)?; - name_entry( - &res_unit.dw_unit, - gimli::UnitOffset(dr.0 - res_unit.offset.0), - dwarf, - recursion_limit, - ) + let (unit, offset) = ctx.find_unit(dr, file)?; + name_entry(file, unit, offset, ctx, sections, recursion_limit) } gimli::AttributeValue::DebugInfoRefSup(dr) => { - if let Some(sup_dwarf) = dwarf.sup.as_ref() { - let res_unit = sup_dwarf.find_unit(dr)?; - name_entry( - &res_unit.dw_unit, - gimli::UnitOffset(dr.0 - res_unit.offset.0), - sup_dwarf, - recursion_limit, - ) + if let Some(sup_sections) = sections.sup.as_ref() { + file = DebugFile::Supplementary; + let (unit, offset) = ctx.find_unit(dr, file)?; + name_entry(file, unit, offset, ctx, sup_sections, recursion_limit) } else { Ok(None) } @@ -483,9 +502,11 @@ where } fn name_entry<R>( + file: DebugFile, unit: &gimli::Unit<R>, offset: gimli::UnitOffset<R::Offset>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, recursion_limit: usize, ) -> Result<Option<R>, Error> where @@ -504,12 +525,12 @@ where match entries.read_attribute(*spec) { Ok(ref attr) => match attr.name() { gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { return Ok(Some(val)); } } gimli::DW_AT_name => { - if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { name = Some(val); } } @@ -527,7 +548,7 @@ where } if let Some(next) = next { - return name_attr(next, unit, dwarf, recursion_limit - 1); + return name_attr(next, file, unit, ctx, sections, recursion_limit - 1); } Ok(None) |