diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:41 +0000 |
commit | 4f9fe856a25ab29345b90e7725509e9ee38a37be (patch) | |
tree | e4ffd8a9374cae7b21f7cbfb352927e0e074aff6 /vendor/addr2line/src | |
parent | Adding upstream version 1.68.2+dfsg1. (diff) | |
download | rustc-upstream/1.69.0+dfsg1.tar.xz rustc-upstream/1.69.0+dfsg1.zip |
Adding upstream version 1.69.0+dfsg1.upstream/1.69.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/addr2line/src')
-rw-r--r-- | vendor/addr2line/src/function.rs | 30 | ||||
-rw-r--r-- | vendor/addr2line/src/lazy.rs | 24 | ||||
-rw-r--r-- | vendor/addr2line/src/lib.rs | 246 |
3 files changed, 177 insertions, 123 deletions
diff --git a/vendor/addr2line/src/function.rs b/vendor/addr2line/src/function.rs index 1589acdbe..44dc73f24 100644 --- a/vendor/addr2line/src/function.rs +++ b/vendor/addr2line/src/function.rs @@ -68,15 +68,24 @@ impl<R: gimli::Reader> Functions<R> { match entries.read_attribute(*spec) { Ok(ref attr) => { match attr.name() { - gimli::DW_AT_low_pc => { - if let gimli::AttributeValue::Addr(val) = attr.value() { - ranges.low_pc = Some(val); + 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)?); + } + _ => {} + }, 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)?); + } gimli::AttributeValue::Udata(val) => { ranges.size = Some(val) } @@ -352,13 +361,18 @@ impl<R: gimli::Reader> InlinedFunction<R> { for spec in abbrev.attributes() { match entries.read_attribute(*spec) { Ok(ref attr) => match attr.name() { - gimli::DW_AT_low_pc => { - if let gimli::AttributeValue::Addr(val) = attr.value() { - ranges.low_pc = Some(val); + 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)?); } - } + _ => {} + }, 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)?); + } gimli::AttributeValue::Udata(val) => ranges.size = Some(val), _ => {} }, diff --git a/vendor/addr2line/src/lazy.rs b/vendor/addr2line/src/lazy.rs index 280c76b46..a34ed176a 100644 --- a/vendor/addr2line/src/lazy.rs +++ b/vendor/addr2line/src/lazy.rs @@ -11,19 +11,17 @@ impl<T> LazyCell<T> { } pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T { - unsafe { - // First check if we're already initialized... - let ptr = self.contents.get(); - if let Some(val) = &*ptr { - return val; - } - // Note that while we're executing `closure` our `borrow_with` may - // be called recursively. This means we need to check again after - // the closure has executed. For that we use the `get_or_insert` - // method which will only perform mutation if we aren't already - // `Some`. - let val = closure(); - (*ptr).get_or_insert(val) + // First check if we're already initialized... + let ptr = self.contents.get(); + if let Some(val) = unsafe { &*ptr } { + return val; } + // Note that while we're executing `closure` our `borrow_with` may + // be called recursively. This means we need to check again after + // the closure has executed. For that we use the `get_or_insert` + // method which will only perform mutation if we aren't already + // `Some`. + let val = closure(); + unsafe { (*ptr).get_or_insert(val) } } } diff --git a/vendor/addr2line/src/lib.rs b/vendor/addr2line/src/lib.rs index b46a98393..3afa37f8f 100644 --- a/vendor/addr2line/src/lib.rs +++ b/vendor/addr2line/src/lib.rs @@ -181,6 +181,7 @@ impl<R: gimli::Reader> Context<R> { ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists), file_type: gimli::DwarfFileType::Main, sup: None, + abbreviations_cache: gimli::AbbreviationsCache::new(), }) } @@ -404,6 +405,7 @@ impl<R: gimli::Reader> ResDwarf<R> { }; let mut lang = None; + let mut have_unit_range = false; { let mut entries = dw_unit.entries_raw(None)?; @@ -416,13 +418,18 @@ impl<R: gimli::Reader> ResDwarf<R> { for spec in abbrev.attributes() { let attr = entries.read_attribute(*spec)?; match attr.name() { - gimli::DW_AT_low_pc => { - if let gimli::AttributeValue::Addr(val) = attr.value() { - ranges.low_pc = Some(val); + 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(sections.address(&dw_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(sections.address(&dw_unit, index)?); + } gimli::AttributeValue::Udata(val) => ranges.size = Some(val), _ => {} }, @@ -472,11 +479,12 @@ impl<R: gimli::Reader> ResDwarf<R> { unit_id, max_end: 0, }); + have_unit_range = true; } } } } else { - ranges.for_each_range(§ions, &dw_unit, |range| { + have_unit_range |= ranges.for_each_range(§ions, &dw_unit, |range| { unit_ranges.push(UnitRange { range, unit_id, @@ -486,11 +494,34 @@ impl<R: gimli::Reader> ResDwarf<R> { } } + let lines = LazyCell::new(); + if !have_unit_range { + // The unit did not declare any ranges. + // Try to get some ranges from the line program sequences. + if let Some(ref ilnp) = dw_unit.line_program { + if let Ok(lines) = lines + .borrow_with(|| Lines::parse(&dw_unit, ilnp.clone(), &*sections)) + .as_ref() + { + for sequence in lines.sequences.iter() { + unit_ranges.push(UnitRange { + range: gimli::Range { + begin: sequence.start, + end: sequence.end, + }, + unit_id, + max_end: 0, + }) + } + } + } + } + res_units.push(ResUnit { offset, dw_unit, lang, - lines: LazyCell::new(), + lines, funcs: LazyCell::new(), }); } @@ -531,6 +562,111 @@ struct Lines { sequences: Box<[LineSequence]>, } +impl Lines { + fn parse<R: gimli::Reader>( + dw_unit: &gimli::Unit<R>, + ilnp: gimli::IncompleteLineProgram<R, R::Offset>, + sections: &gimli::Dwarf<R>, + ) -> Result<Self, Error> { + let mut sequences = Vec::new(); + let mut sequence_rows = Vec::<LineRow>::new(); + let mut rows = ilnp.rows(); + while let Some((_, row)) = rows.next_row()? { + if row.end_sequence() { + if let Some(start) = sequence_rows.first().map(|x| x.address) { + let end = row.address(); + let mut rows = Vec::new(); + mem::swap(&mut rows, &mut sequence_rows); + sequences.push(LineSequence { + start, + end, + rows: rows.into_boxed_slice(), + }); + } + continue; + } + + let address = row.address(); + let file_index = row.file_index(); + let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32; + let column = match row.column() { + gimli::ColumnType::LeftEdge => 0, + gimli::ColumnType::Column(x) => x.get() as u32, + }; + + if let Some(last_row) = sequence_rows.last_mut() { + if last_row.address == address { + last_row.file_index = file_index; + last_row.line = line; + last_row.column = column; + continue; + } + } + + sequence_rows.push(LineRow { + address, + file_index, + line, + column, + }); + } + sequences.sort_by_key(|x| x.start); + + let mut files = Vec::new(); + let header = rows.header(); + match header.file(0) { + Some(file) => files.push(render_file(dw_unit, file, header, sections)?), + None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index + } + let mut index = 1; + while let Some(file) = header.file(index) { + files.push(render_file(dw_unit, file, header, sections)?); + index += 1; + } + + Ok(Self { + files: files.into_boxed_slice(), + sequences: sequences.into_boxed_slice(), + }) + } +} + +fn render_file<R: gimli::Reader>( + dw_unit: &gimli::Unit<R>, + file: &gimli::FileEntry<R, R::Offset>, + header: &gimli::LineProgramHeader<R, R::Offset>, + sections: &gimli::Dwarf<R>, +) -> Result<String, gimli::Error> { + let mut path = if let Some(ref comp_dir) = dw_unit.comp_dir { + comp_dir.to_string_lossy()?.into_owned() + } else { + String::new() + }; + + // The directory index 0 is defined to correspond to the compilation unit directory. + if file.directory_index() != 0 { + if let Some(directory) = file.directory(header) { + path_push( + &mut path, + sections + .attr_string(dw_unit, directory)? + .to_string_lossy()? + .as_ref(), + ); + } + } + + path_push( + &mut path, + sections + .attr_string(dw_unit, file.path_name())? + .to_string_lossy()? + .as_ref(), + ); + + Ok(path) +} + struct LineSequence { start: u64, end: u64, @@ -559,68 +695,7 @@ impl<R: gimli::Reader> ResUnit<R> { None => return Ok(None), }; self.lines - .borrow_with(|| { - let mut sequences = Vec::new(); - let mut sequence_rows = Vec::<LineRow>::new(); - let mut rows = ilnp.clone().rows(); - while let Some((_, row)) = rows.next_row()? { - if row.end_sequence() { - if let Some(start) = sequence_rows.first().map(|x| x.address) { - let end = row.address(); - let mut rows = Vec::new(); - mem::swap(&mut rows, &mut sequence_rows); - sequences.push(LineSequence { - start, - end, - rows: rows.into_boxed_slice(), - }); - } - continue; - } - - let address = row.address(); - let file_index = row.file_index(); - let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32; - let column = match row.column() { - gimli::ColumnType::LeftEdge => 0, - gimli::ColumnType::Column(x) => x.get() as u32, - }; - - if let Some(last_row) = sequence_rows.last_mut() { - if last_row.address == address { - last_row.file_index = file_index; - last_row.line = line; - last_row.column = column; - continue; - } - } - - sequence_rows.push(LineRow { - address, - file_index, - line, - column, - }); - } - sequences.sort_by_key(|x| x.start); - - let mut files = Vec::new(); - let header = ilnp.header(); - match header.file(0) { - Some(file) => files.push(self.render_file(file, header, sections)?), - None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index - } - let mut index = 1; - while let Some(file) = header.file(index) { - files.push(self.render_file(file, header, sections)?); - index += 1; - } - - Ok(Lines { - files: files.into_boxed_slice(), - sequences: sequences.into_boxed_slice(), - }) - }) + .borrow_with(|| Lines::parse(&self.dw_unit, ilnp.clone(), sections)) .as_ref() .map(Some) .map_err(Error::clone) @@ -688,39 +763,6 @@ impl<R: gimli::Reader> ResUnit<R> { let location = self.find_location(probe, &dwarf.sections)?; Ok((function, location)) } - - fn render_file( - &self, - file: &gimli::FileEntry<R, R::Offset>, - header: &gimli::LineProgramHeader<R, R::Offset>, - sections: &gimli::Dwarf<R>, - ) -> Result<String, gimli::Error> { - let mut path = if let Some(ref comp_dir) = self.dw_unit.comp_dir { - comp_dir.to_string_lossy()?.into_owned() - } else { - String::new() - }; - - if let Some(directory) = file.directory(header) { - path_push( - &mut path, - sections - .attr_string(&self.dw_unit, directory)? - .to_string_lossy()? - .as_ref(), - ); - } - - path_push( - &mut path, - sections - .attr_string(&self.dw_unit, file.path_name())? - .to_string_lossy()? - .as_ref(), - ); - - Ok(path) - } } /// Iterator over `Location`s in a range of addresses, returned by `Context::find_location_range`. @@ -928,7 +970,7 @@ fn path_push(path: &mut String, p: &str) { '/' }; - if !path.ends_with(dir_separator) { + if !path.is_empty() && !path.ends_with(dir_separator) { path.push(dir_separator); } *path += p; |