summaryrefslogtreecommitdiffstats
path: root/vendor/addr2line/src/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/addr2line/src/function.rs')
-rw-r--r--vendor/addr2line/src/function.rs133
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)