summaryrefslogtreecommitdiffstats
path: root/library/backtrace/src/symbolize/gimli.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /library/backtrace/src/symbolize/gimli.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/backtrace/src/symbolize/gimli.rs')
-rw-r--r--library/backtrace/src/symbolize/gimli.rs73
1 files changed, 60 insertions, 13 deletions
diff --git a/library/backtrace/src/symbolize/gimli.rs b/library/backtrace/src/symbolize/gimli.rs
index cd4cec58c..7f1c6a528 100644
--- a/library/backtrace/src/symbolize/gimli.rs
+++ b/library/backtrace/src/symbolize/gimli.rs
@@ -58,7 +58,7 @@ struct Mapping {
// 'static lifetime is a lie to hack around lack of support for self-referential structs.
cx: Context<'static>,
_map: Mmap,
- _stash: Stash,
+ stash: Stash,
}
enum Either<A, B> {
@@ -97,7 +97,7 @@ impl Mapping {
// only borrow `map` and `stash` and we're preserving them below.
cx: unsafe { core::mem::transmute::<Context<'_>, Context<'static>>(cx) },
_map: data,
- _stash: stash,
+ stash: stash,
})
}
}
@@ -105,6 +105,7 @@ impl Mapping {
struct Context<'a> {
dwarf: addr2line::Context<EndianSlice<'a, Endian>>,
object: Object<'a>,
+ package: Option<gimli::DwarfPackage<EndianSlice<'a, Endian>>>,
}
impl<'data> Context<'data> {
@@ -112,6 +113,7 @@ impl<'data> Context<'data> {
stash: &'data Stash,
object: Object<'data>,
sup: Option<Object<'data>>,
+ dwp: Option<Object<'data>>,
) -> Option<Context<'data>> {
let mut sections = gimli::Dwarf::load(|id| -> Result<_, ()> {
let data = object.section(stash, id.name()).unwrap_or(&[]);
@@ -129,7 +131,46 @@ impl<'data> Context<'data> {
}
let dwarf = addr2line::Context::from_dwarf(sections).ok()?;
- Some(Context { dwarf, object })
+ let mut package = None;
+ if let Some(dwp) = dwp {
+ package = Some(
+ gimli::DwarfPackage::load(
+ |id| -> Result<_, gimli::Error> {
+ let data = id
+ .dwo_name()
+ .and_then(|name| dwp.section(stash, name))
+ .unwrap_or(&[]);
+ Ok(EndianSlice::new(data, Endian))
+ },
+ EndianSlice::new(&[], Endian),
+ )
+ .ok()?,
+ );
+ }
+
+ Some(Context {
+ dwarf,
+ object,
+ package,
+ })
+ }
+
+ fn find_frames(
+ &'_ self,
+ stash: &'data Stash,
+ probe: u64,
+ ) -> gimli::Result<addr2line::FrameIter<'_, EndianSlice<'data, Endian>>> {
+ use addr2line::{LookupContinuation, LookupResult};
+
+ let mut l = self.dwarf.find_frames(probe);
+ loop {
+ let (load, continuation) = match l {
+ LookupResult::Output(output) => break output,
+ LookupResult::Load { load, continuation } => (load, continuation),
+ };
+
+ l = continuation.resume(handle_split_dwarf(self.package.as_ref(), stash, load));
+ }
}
}
@@ -142,7 +183,7 @@ fn mmap(path: &Path) -> Option<Mmap> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
mod coff;
- use self::coff::Object;
+ use self::coff::{handle_split_dwarf, Object};
} else if #[cfg(any(
target_os = "macos",
target_os = "ios",
@@ -150,10 +191,10 @@ cfg_if::cfg_if! {
target_os = "watchos",
))] {
mod macho;
- use self::macho::Object;
+ use self::macho::{handle_split_dwarf, Object};
} else {
mod elf;
- use self::elf::Object;
+ use self::elf::{handle_split_dwarf, Object};
}
}
@@ -178,6 +219,7 @@ cfg_if::cfg_if! {
target_os = "fuchsia",
target_os = "freebsd",
target_os = "openbsd",
+ target_os = "netbsd",
all(target_os = "android", feature = "dl_iterate_phdr"),
),
not(target_env = "uclibc"),
@@ -302,7 +344,7 @@ impl Cache {
.next()
}
- fn mapping_for_lib<'a>(&'a mut self, lib: usize) -> Option<&'a mut Context<'a>> {
+ fn mapping_for_lib<'a>(&'a mut self, lib: usize) -> Option<(&'a mut Context<'a>, &'a Stash)> {
let idx = self.mappings.iter().position(|(idx, _)| *idx == lib);
// Invariant: after this conditional completes without early returning
@@ -328,10 +370,15 @@ impl Cache {
self.mappings.insert(0, (lib, mapping));
}
- let cx: &'a mut Context<'static> = &mut self.mappings[0].1.cx;
+ let mapping = &mut self.mappings[0].1;
+ let cx: &'a mut Context<'static> = &mut mapping.cx;
+ let stash: &'a Stash = &mapping.stash;
// don't leak the `'static` lifetime, make sure it's scoped to just
// ourselves
- Some(unsafe { mem::transmute::<&'a mut Context<'static>, &'a mut Context<'a>>(cx) })
+ Some((
+ unsafe { mem::transmute::<&'a mut Context<'static>, &'a mut Context<'a>>(cx) },
+ stash,
+ ))
}
}
@@ -353,12 +400,12 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
// Finally, get a cached mapping or create a new mapping for this file, and
// evaluate the DWARF info to find the file/line/name for this address.
- let cx = match cache.mapping_for_lib(lib) {
- Some(cx) => cx,
+ let (cx, stash) = match cache.mapping_for_lib(lib) {
+ Some((cx, stash)) => (cx, stash),
None => return,
};
let mut any_frames = false;
- if let Ok(mut frames) = cx.dwarf.find_frames(addr as u64) {
+ if let Ok(mut frames) = cx.find_frames(stash, addr as u64) {
while let Ok(Some(frame)) = frames.next() {
any_frames = true;
let name = match frame.function {
@@ -374,7 +421,7 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
}
if !any_frames {
if let Some((object_cx, object_addr)) = cx.object.search_object_map(addr as u64) {
- if let Ok(mut frames) = object_cx.dwarf.find_frames(object_addr) {
+ if let Ok(mut frames) = object_cx.find_frames(stash, object_addr) {
while let Ok(Some(frame)) = frames.next() {
any_frames = true;
call(Symbol::Frame {