summaryrefslogtreecommitdiffstats
path: root/library/backtrace
diff options
context:
space:
mode:
Diffstat (limited to 'library/backtrace')
-rw-r--r--library/backtrace/.github/workflows/main.yml2
-rw-r--r--library/backtrace/Cargo.toml10
-rwxr-xr-xlibrary/backtrace/ci/android-ndk.sh27
-rw-r--r--library/backtrace/ci/docker/aarch64-linux-android/Dockerfile6
-rw-r--r--library/backtrace/ci/docker/arm-linux-androideabi/Dockerfile6
-rw-r--r--library/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile6
-rw-r--r--library/backtrace/ci/docker/i686-linux-android/Dockerfile6
-rw-r--r--library/backtrace/ci/docker/x86_64-linux-android/Dockerfile6
-rw-r--r--library/backtrace/crates/as-if-std/Cargo.toml10
-rw-r--r--library/backtrace/crates/as-if-std/src/lib.rs3
-rw-r--r--library/backtrace/src/backtrace/libunwind.rs2
-rw-r--r--library/backtrace/src/backtrace/mod.rs1
-rw-r--r--library/backtrace/src/dbghelp.rs24
-rw-r--r--library/backtrace/src/lib.rs1
-rw-r--r--library/backtrace/src/print.rs17
-rw-r--r--library/backtrace/src/symbolize/gimli.rs73
-rw-r--r--library/backtrace/src/symbolize/gimli/coff.rs14
-rw-r--r--library/backtrace/src/symbolize/gimli/elf.rs92
-rw-r--r--library/backtrace/src/symbolize/gimli/macho.rs17
-rw-r--r--library/backtrace/src/symbolize/gimli/mmap_unix.rs7
-rw-r--r--library/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs26
-rw-r--r--library/backtrace/src/symbolize/gimli/stash.rs22
-rw-r--r--library/backtrace/tests/current-exe-mismatch.rs7
23 files changed, 268 insertions, 117 deletions
diff --git a/library/backtrace/.github/workflows/main.yml b/library/backtrace/.github/workflows/main.yml
index 24d814363..29fff2795 100644
--- a/library/backtrace/.github/workflows/main.yml
+++ b/library/backtrace/.github/workflows/main.yml
@@ -229,7 +229,7 @@ jobs:
with:
submodules: true
- name: Install Rust
- run: rustup update 1.42.0 && rustup default 1.42.0
+ run: rustup update 1.55.0 && rustup default 1.55.0
- run: cargo build
miri:
diff --git a/library/backtrace/Cargo.toml b/library/backtrace/Cargo.toml
index 477909111..cff2c9e66 100644
--- a/library/backtrace/Cargo.toml
+++ b/library/backtrace/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "backtrace"
-version = "0.3.67"
+version = "0.3.68"
authors = ["The Rust Project Developers"]
build = "build.rs"
license = "MIT OR Apache-2.0"
@@ -27,7 +27,7 @@ exclude = [
[dependencies]
cfg-if = "1.0"
rustc-demangle = "0.1.4"
-libc = { version = "0.2.94", default-features = false }
+libc = { version = "0.2.146", default-features = false }
# Optionally enable the ability to serialize a `Backtrace`, controlled through
# the `serialize-*` features below.
@@ -37,11 +37,11 @@ rustc-serialize = { version = "0.3", optional = true }
# Optionally demangle C++ frames' symbols in backtraces.
cpp_demangle = { default-features = false, version = "0.4.0", optional = true, features = ["alloc"] }
-addr2line = { version = "0.19.0", default-features = false }
-miniz_oxide = { version = "0.6.0", default-features = false }
+addr2line = { version = "0.20.0", default-features = false }
+miniz_oxide = { version = "0.7.0", default-features = false }
[dependencies.object]
-version = "0.30.0"
+version = "0.31.1"
default-features = false
features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
diff --git a/library/backtrace/ci/android-ndk.sh b/library/backtrace/ci/android-ndk.sh
index b5df62b6f..38521daf1 100755
--- a/library/backtrace/ci/android-ndk.sh
+++ b/library/backtrace/ci/android-ndk.sh
@@ -1,23 +1,14 @@
set -ex
-ANDROID_ARCH=$1
-ANDROID_SDK_VERSION=4333796
-
-mkdir /tmp/android
-cd /tmp/android
-
-curl -o android-sdk.zip \
- "https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_VERSION}.zip"
-unzip -q android-sdk.zip
-
-yes | ./tools/bin/sdkmanager --licenses > /dev/null
-./tools/bin/sdkmanager ndk-bundle > /dev/null
-
-./ndk-bundle/build/tools/make_standalone_toolchain.py \
- --arch $ANDROID_ARCH \
- --stl=libc++ \
- --api 21 \
- --install-dir /android-toolchain
+ANDROID_NDK_URL=https://dl.google.com/android/repository
+ANDROID_NDK_ARCHIVE=android-ndk-r25b-linux.zip
+
+mkdir /android-toolchain
+cd /android-toolchain
+curl -fO $ANDROID_NDK_URL/$ANDROID_NDK_ARCHIVE
+unzip -q $ANDROID_NDK_ARCHIVE
+rm $ANDROID_NDK_ARCHIVE
+mv android-ndk-* ndk
cd /tmp
rm -rf android
diff --git a/library/backtrace/ci/docker/aarch64-linux-android/Dockerfile b/library/backtrace/ci/docker/aarch64-linux-android/Dockerfile
index c5655ed5e..906c68789 100644
--- a/library/backtrace/ci/docker/aarch64-linux-android/Dockerfile
+++ b/library/backtrace/ci/docker/aarch64-linux-android/Dockerfile
@@ -10,9 +10,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libc6-dev
COPY android-ndk.sh /
-RUN /android-ndk.sh arm64
-ENV PATH=$PATH:/android-toolchain/bin
+RUN /android-ndk.sh
+ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
# TODO: run tests in an emulator eventually
-ENV CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android-gcc \
+ENV CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android21-clang \
CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER=echo
diff --git a/library/backtrace/ci/docker/arm-linux-androideabi/Dockerfile b/library/backtrace/ci/docker/arm-linux-androideabi/Dockerfile
index 446a64cc0..7471dcb73 100644
--- a/library/backtrace/ci/docker/arm-linux-androideabi/Dockerfile
+++ b/library/backtrace/ci/docker/arm-linux-androideabi/Dockerfile
@@ -10,9 +10,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libc6-dev
COPY android-ndk.sh /
-RUN /android-ndk.sh arm
-ENV PATH=$PATH:/android-toolchain/bin
+RUN /android-ndk.sh
+ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
# TODO: run tests in an emulator eventually
-ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
+ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=armv7a-linux-androideabi19-clang \
CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=echo
diff --git a/library/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile b/library/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile
index 539bbc494..543fcd243 100644
--- a/library/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile
+++ b/library/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile
@@ -10,9 +10,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libc6-dev
COPY android-ndk.sh /
-RUN /android-ndk.sh arm
-ENV PATH=$PATH:/android-toolchain/bin
+RUN /android-ndk.sh
+ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
# TODO: run tests in an emulator eventually
-ENV CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
+ENV CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=armv7a-linux-androideabi19-clang \
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_RUNNER=echo
diff --git a/library/backtrace/ci/docker/i686-linux-android/Dockerfile b/library/backtrace/ci/docker/i686-linux-android/Dockerfile
index 83ccb2948..61cb9d075 100644
--- a/library/backtrace/ci/docker/i686-linux-android/Dockerfile
+++ b/library/backtrace/ci/docker/i686-linux-android/Dockerfile
@@ -10,9 +10,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libc6-dev
COPY android-ndk.sh /
-RUN /android-ndk.sh x86
-ENV PATH=$PATH:/android-toolchain/bin
+RUN /android-ndk.sh
+ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
# TODO: run tests in an emulator eventually
-ENV CARGO_TARGET_I686_LINUX_ANDROID_LINKER=i686-linux-android-gcc \
+ENV CARGO_TARGET_I686_LINUX_ANDROID_LINKER=i686-linux-android19-clang \
CARGO_TARGET_I686_LINUX_ANDROID_RUNNER=echo
diff --git a/library/backtrace/ci/docker/x86_64-linux-android/Dockerfile b/library/backtrace/ci/docker/x86_64-linux-android/Dockerfile
index 88a22ce6c..4c8922936 100644
--- a/library/backtrace/ci/docker/x86_64-linux-android/Dockerfile
+++ b/library/backtrace/ci/docker/x86_64-linux-android/Dockerfile
@@ -10,9 +10,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libc6-dev
COPY android-ndk.sh /
-RUN /android-ndk.sh x86_64
-ENV PATH=$PATH:/android-toolchain/bin
+RUN /android-ndk.sh
+ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
# TODO: run tests in an emulator eventually
-ENV CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android-gcc \
+ENV CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android21-clang \
CARGO_TARGET_X86_64_LINUX_ANDROID_RUNNER=echo
diff --git a/library/backtrace/crates/as-if-std/Cargo.toml b/library/backtrace/crates/as-if-std/Cargo.toml
index c763227f2..012e60f8f 100644
--- a/library/backtrace/crates/as-if-std/Cargo.toml
+++ b/library/backtrace/crates/as-if-std/Cargo.toml
@@ -13,13 +13,13 @@ bench = false
[dependencies]
cfg-if = "1.0"
-rustc-demangle = "0.1.4"
-libc = { version = "0.2.45", default-features = false }
-addr2line = { version = "0.16.0", default-features = false, optional = true }
-miniz_oxide = { version = "0.4.0", default-features = false }
+rustc-demangle = "0.1.21"
+libc = { version = "0.2.146", default-features = false }
+addr2line = { version = "0.20.0", default-features = false, optional = true }
+miniz_oxide = { version = "0.7", default-features = false }
[dependencies.object]
-version = "0.28"
+version = "0.31.1"
default-features = false
optional = true
features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
diff --git a/library/backtrace/crates/as-if-std/src/lib.rs b/library/backtrace/crates/as-if-std/src/lib.rs
index c0f49b77d..e1d8faaeb 100644
--- a/library/backtrace/crates/as-if-std/src/lib.rs
+++ b/library/backtrace/crates/as-if-std/src/lib.rs
@@ -14,7 +14,8 @@ mod __internal {
pub use std::*;
}
-pub use __internal::*;
+#[allow(unused_imports)]
+use __internal::*;
// This is the magical part which we hope works.
#[path = "../../../src/lib.rs"]
diff --git a/library/backtrace/src/backtrace/libunwind.rs b/library/backtrace/src/backtrace/libunwind.rs
index c319fe45a..aefa8b094 100644
--- a/library/backtrace/src/backtrace/libunwind.rs
+++ b/library/backtrace/src/backtrace/libunwind.rs
@@ -66,7 +66,7 @@ impl Frame {
//
// Note the `skip_inner_frames.rs` test is skipped on macOS due to this
// clause, and if this is fixed that test in theory can be run on macOS!
- if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
+ if cfg!(target_vendor = "apple") {
self.ip()
} else {
unsafe { uw::_Unwind_FindEnclosingFunction(self.ip()) }
diff --git a/library/backtrace/src/backtrace/mod.rs b/library/backtrace/src/backtrace/mod.rs
index 93355d744..6ca1080c4 100644
--- a/library/backtrace/src/backtrace/mod.rs
+++ b/library/backtrace/src/backtrace/mod.rs
@@ -138,6 +138,7 @@ cfg_if::cfg_if! {
unix,
not(target_os = "emscripten"),
not(all(target_os = "ios", target_arch = "arm")),
+ not(all(target_os = "nto", target_env = "nto70")),
),
all(
target_env = "sgx",
diff --git a/library/backtrace/src/dbghelp.rs b/library/backtrace/src/dbghelp.rs
index edeec653d..c81766bae 100644
--- a/library/backtrace/src/dbghelp.rs
+++ b/library/backtrace/src/dbghelp.rs
@@ -239,6 +239,23 @@ pub struct Init {
pub fn init() -> Result<Init, ()> {
use core::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+ // Helper function for generating a name that's unique to the process.
+ fn mutex_name() -> [u8; 33] {
+ let mut name: [u8; 33] = *b"Local\\RustBacktraceMutex00000000\0";
+ let mut id = unsafe { GetCurrentProcessId() };
+ // Quick and dirty no alloc u32 to hex.
+ let mut index = name.len() - 1;
+ while id > 0 {
+ name[index - 1] = match (id & 0xF) as u8 {
+ h @ 0..=9 => b'0' + h,
+ h => b'A' + (h - 10),
+ };
+ id >>= 4;
+ index -= 1;
+ }
+ name
+ }
+
unsafe {
// First thing we need to do is to synchronize this function. This can
// be called concurrently from other threads or recursively within one
@@ -277,11 +294,8 @@ pub fn init() -> Result<Init, ()> {
static LOCK: AtomicUsize = AtomicUsize::new(0);
let mut lock = LOCK.load(SeqCst);
if lock == 0 {
- lock = CreateMutexA(
- ptr::null_mut(),
- 0,
- "Local\\RustBacktraceMutex\0".as_ptr() as _,
- ) as usize;
+ let name = mutex_name();
+ lock = CreateMutexA(ptr::null_mut(), 0, name.as_ptr().cast::<i8>()) as usize;
if lock == 0 {
return Err(());
}
diff --git a/library/backtrace/src/lib.rs b/library/backtrace/src/lib.rs
index e5dea3387..4615e1f96 100644
--- a/library/backtrace/src/lib.rs
+++ b/library/backtrace/src/lib.rs
@@ -86,7 +86,6 @@
//! time, but otherwise it's important to be aware of the limitations of
//! unwinding-based backtraces!
-#![doc(html_root_url = "https://docs.rs/backtrace")]
#![deny(missing_docs)]
#![no_std]
#![cfg_attr(
diff --git a/library/backtrace/src/print.rs b/library/backtrace/src/print.rs
index 174d8ae5c..8d9cbe3d4 100644
--- a/library/backtrace/src/print.rs
+++ b/library/backtrace/src/print.rs
@@ -86,6 +86,23 @@ impl<'a, 'b> BacktraceFmt<'a, 'b> {
// Currently a no-op-- including this hook to allow for future additions.
Ok(())
}
+
+ /// Inserts a message in the backtrace output.
+ ///
+ /// This allows information to be inserted between frames,
+ /// and won't increment the `frame_index` unlike the `frame`
+ /// method.
+ pub fn message(&mut self, msg: &str) -> fmt::Result {
+ self.fmt.write_str(msg)
+ }
+
+ /// Return the inner formatter.
+ ///
+ /// This is used for writing custom information between frames with `write!` and `writeln!`,
+ /// and won't increment the `frame_index` unlike the `frame` method.
+ pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
+ self.fmt
+ }
}
/// A formatter for just one frame of a backtrace.
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 {
diff --git a/library/backtrace/src/symbolize/gimli/coff.rs b/library/backtrace/src/symbolize/gimli/coff.rs
index 84d334207..759c827e0 100644
--- a/library/backtrace/src/symbolize/gimli/coff.rs
+++ b/library/backtrace/src/symbolize/gimli/coff.rs
@@ -1,6 +1,8 @@
-use super::{Context, Mapping, Path, Stash, Vec};
+use super::{gimli, Context, Endian, EndianSlice, Mapping, Path, Stash, Vec};
+use alloc::sync::Arc;
use core::convert::TryFrom;
use object::pe::{ImageDosHeader, ImageSymbol};
+use object::read::coff::ImageSymbol as _;
use object::read::pe::{ImageNtHeaders, ImageOptionalHeader, SectionTable};
use object::read::StringTable;
use object::LittleEndian as LE;
@@ -14,7 +16,7 @@ impl Mapping {
pub fn new(path: &Path) -> Option<Mapping> {
let map = super::mmap(path)?;
Mapping::mk(map, |data, stash| {
- Context::new(stash, Object::parse(data)?, None)
+ Context::new(stash, Object::parse(data)?, None, None)
})
}
}
@@ -106,3 +108,11 @@ impl<'a> Object<'a> {
None
}
}
+
+pub(super) fn handle_split_dwarf<'data>(
+ _package: Option<&gimli::DwarfPackage<EndianSlice<'data, Endian>>>,
+ _stash: &'data Stash,
+ _load: addr2line::SplitDwarfLoad<EndianSlice<'data, Endian>>,
+) -> Option<Arc<gimli::Dwarf<EndianSlice<'data, Endian>>>> {
+ None
+}
diff --git a/library/backtrace/src/symbolize/gimli/elf.rs b/library/backtrace/src/symbolize/gimli/elf.rs
index bc71ee2c9..b0eec0762 100644
--- a/library/backtrace/src/symbolize/gimli/elf.rs
+++ b/library/backtrace/src/symbolize/gimli/elf.rs
@@ -3,7 +3,8 @@ use super::mystd::fs;
use super::mystd::os::unix::ffi::{OsStrExt, OsStringExt};
use super::mystd::path::{Path, PathBuf};
use super::Either;
-use super::{Context, Mapping, Stash, Vec};
+use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash, Vec};
+use alloc::sync::Arc;
use core::convert::{TryFrom, TryInto};
use core::str;
use object::elf::{ELFCOMPRESS_ZLIB, ELF_NOTE_GNU, NT_GNU_BUILD_ID, SHF_COMPRESSED};
@@ -24,24 +25,26 @@ impl Mapping {
// Try to locate an external debug file using the build ID.
if let Some(path_debug) = object.build_id().and_then(locate_build_id) {
- if let Some(mapping) = Mapping::new_debug(path_debug, None) {
+ if let Some(mapping) = Mapping::new_debug(path, path_debug, None) {
return Some(Either::A(mapping));
}
}
// Try to locate an external debug file using the GNU debug link section.
if let Some((path_debug, crc)) = object.gnu_debuglink_path(path) {
- if let Some(mapping) = Mapping::new_debug(path_debug, Some(crc)) {
+ if let Some(mapping) = Mapping::new_debug(path, path_debug, Some(crc)) {
return Some(Either::A(mapping));
}
}
- Context::new(stash, object, None).map(Either::B)
+ let dwp = Mapping::load_dwarf_package(path, stash);
+
+ Context::new(stash, object, None, dwp).map(Either::B)
})
}
/// Load debuginfo from an external debug file.
- fn new_debug(path: PathBuf, crc: Option<u32>) -> Option<Mapping> {
+ fn new_debug(original_path: &Path, path: PathBuf, crc: Option<u32>) -> Option<Mapping> {
let map = super::mmap(&path)?;
Mapping::mk(map, |map, stash| {
let object = Object::parse(&map)?;
@@ -51,20 +54,45 @@ impl Mapping {
}
// Try to locate a supplementary object file.
+ let mut sup = None;
if let Some((path_sup, build_id_sup)) = object.gnu_debugaltlink_path(&path) {
if let Some(map_sup) = super::mmap(&path_sup) {
- let map_sup = stash.set_mmap_aux(map_sup);
- if let Some(sup) = Object::parse(map_sup) {
- if sup.build_id() == Some(build_id_sup) {
- return Context::new(stash, object, Some(sup));
+ let map_sup = stash.cache_mmap(map_sup);
+ if let Some(sup_) = Object::parse(map_sup) {
+ if sup_.build_id() == Some(build_id_sup) {
+ sup = Some(sup_);
}
}
}
}
- Context::new(stash, object, None)
+ let dwp = Mapping::load_dwarf_package(original_path, stash);
+
+ Context::new(stash, object, sup, dwp)
})
}
+
+ /// Try to locate a DWARF package file.
+ fn load_dwarf_package<'data>(path: &Path, stash: &'data Stash) -> Option<Object<'data>> {
+ let mut path_dwp = path.to_path_buf();
+ let dwp_extension = path
+ .extension()
+ .map(|previous_extension| {
+ let mut previous_extension = previous_extension.to_os_string();
+ previous_extension.push(".dwp");
+ previous_extension
+ })
+ .unwrap_or_else(|| "dwp".into());
+ path_dwp.set_extension(dwp_extension);
+ if let Some(map_dwp) = super::mmap(&path_dwp) {
+ let map_dwp = stash.cache_mmap(map_dwp);
+ if let Some(dwp_) = Object::parse(map_dwp) {
+ return Some(dwp_);
+ }
+ }
+
+ None
+ }
}
struct ParsedSym {
@@ -421,3 +449,47 @@ fn locate_debugaltlink(path: &Path, filename: &[u8], build_id: &[u8]) -> Option<
locate_build_id(build_id)
}
+
+fn convert_path<R: gimli::Reader>(r: &R) -> Result<PathBuf, gimli::Error> {
+ let bytes = r.to_slice()?;
+ Ok(PathBuf::from(OsStr::from_bytes(&bytes)))
+}
+
+pub(super) fn handle_split_dwarf<'data>(
+ package: Option<&gimli::DwarfPackage<EndianSlice<'data, Endian>>>,
+ stash: &'data Stash,
+ load: addr2line::SplitDwarfLoad<EndianSlice<'data, Endian>>,
+) -> Option<Arc<gimli::Dwarf<EndianSlice<'data, Endian>>>> {
+ if let Some(dwp) = package.as_ref() {
+ if let Ok(Some(cu)) = dwp.find_cu(load.dwo_id, &load.parent) {
+ return Some(Arc::new(cu));
+ }
+ }
+
+ let mut path = PathBuf::new();
+ if let Some(p) = load.comp_dir.as_ref() {
+ path.push(convert_path(p).ok()?);
+ }
+
+ path.push(convert_path(load.path.as_ref()?).ok()?);
+
+ if let Some(map_dwo) = super::mmap(&path) {
+ let map_dwo = stash.cache_mmap(map_dwo);
+ if let Some(dwo) = Object::parse(map_dwo) {
+ return gimli::Dwarf::load(|id| -> Result<_, ()> {
+ let data = id
+ .dwo_name()
+ .and_then(|name| dwo.section(stash, name))
+ .unwrap_or(&[]);
+ Ok(EndianSlice::new(data, Endian))
+ })
+ .ok()
+ .map(|mut dwo_dwarf| {
+ dwo_dwarf.make_dwo(&load.parent);
+ Arc::new(dwo_dwarf)
+ });
+ }
+ }
+
+ None
+}
diff --git a/library/backtrace/src/symbolize/gimli/macho.rs b/library/backtrace/src/symbolize/gimli/macho.rs
index adea97a09..74ed8091a 100644
--- a/library/backtrace/src/symbolize/gimli/macho.rs
+++ b/library/backtrace/src/symbolize/gimli/macho.rs
@@ -1,4 +1,5 @@
-use super::{Box, Context, Mapping, Path, Stash, Vec};
+use super::{gimli, Box, Context, Endian, EndianSlice, Mapping, Path, Stash, Vec};
+use alloc::sync::Arc;
use core::convert::TryInto;
use object::macho;
use object::read::macho::{MachHeader, Nlist, Section, Segment as _};
@@ -45,7 +46,7 @@ impl Mapping {
let (macho, data) = find_header(data)?;
let endian = macho.endian().ok()?;
let obj = Object::parse(macho, endian, data)?;
- Context::new(stash, obj, None)
+ Context::new(stash, obj, None, None)
})
}
@@ -82,7 +83,7 @@ impl Mapping {
return None;
}
let obj = Object::parse(macho, endian, data)?;
- Context::new(stash, obj, None)
+ Context::new(stash, obj, None, None)
});
if let Some(candidate) = candidate {
return Some(candidate);
@@ -309,7 +310,7 @@ fn object_mapping(path: &[u8]) -> Option<Mapping> {
let (macho, data) = find_header(data)?;
let endian = macho.endian().ok()?;
let obj = Object::parse(macho, endian, data)?;
- Context::new(stash, obj, None)
+ Context::new(stash, obj, None, None)
})
}
@@ -322,3 +323,11 @@ fn split_archive_path(path: &[u8]) -> Option<(&[u8], &[u8])> {
let (archive, rest) = path.split_at(index);
Some((archive, &rest[1..]))
}
+
+pub(super) fn handle_split_dwarf<'data>(
+ _package: Option<&gimli::DwarfPackage<EndianSlice<'data, Endian>>>,
+ _stash: &'data Stash,
+ _load: addr2line::SplitDwarfLoad<EndianSlice<'data, Endian>>,
+) -> Option<Arc<gimli::Dwarf<EndianSlice<'data, Endian>>>> {
+ None
+}
diff --git a/library/backtrace/src/symbolize/gimli/mmap_unix.rs b/library/backtrace/src/symbolize/gimli/mmap_unix.rs
index 5806c9f7e..261ffc1d8 100644
--- a/library/backtrace/src/symbolize/gimli/mmap_unix.rs
+++ b/library/backtrace/src/symbolize/gimli/mmap_unix.rs
@@ -4,6 +4,11 @@ use core::ops::Deref;
use core::ptr;
use core::slice;
+#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
+use libc::mmap as mmap64;
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+use libc::mmap64;
+
pub struct Mmap {
ptr: *mut libc::c_void,
len: usize,
@@ -11,7 +16,7 @@ pub struct Mmap {
impl Mmap {
pub unsafe fn map(file: &File, len: usize) -> Option<Mmap> {
- let ptr = libc::mmap(
+ let ptr = mmap64(
ptr::null_mut(),
len,
libc::PROT_READ,
diff --git a/library/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs b/library/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
index a196ffcfb..deeeb2971 100644
--- a/library/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
+++ b/library/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
@@ -97,15 +97,10 @@ impl FromStr for MapsEntry {
let pathname_str = parts.next().unwrap_or(""); // pathname may be omitted.
let hex = |s| usize::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number");
- let address = {
- // This could use `range_str.split_once('-')` once the MSRV passes 1.52.
- if let Some(idx) = range_str.find('-') {
- let (start, rest) = range_str.split_at(idx);
- let (_div, limit) = rest.split_at(1);
- (hex(start)?, hex(limit)?)
- } else {
- return Err("Couldn't parse address range");
- }
+ let address = if let Some((start, limit)) = range_str.split_once('-') {
+ (hex(start)?, hex(limit)?)
+ } else {
+ return Err("Couldn't parse address range");
};
let perms: [char; 4] = {
let mut chars = perms_str.chars();
@@ -117,15 +112,10 @@ impl FromStr for MapsEntry {
perms
};
let offset = hex(offset_str)?;
- let dev = {
- // This could use `dev_str.split_once(':')` once the MSRV passes 1.52.
- if let Some(idx) = dev_str.find(':') {
- let (major, rest) = dev_str.split_at(idx);
- let (_div, minor) = rest.split_at(1);
- (hex(major)?, hex(minor)?)
- } else {
- return Err("Couldn't parse dev")?;
- }
+ let dev = if let Some((major, minor)) = dev_str.split_once(':') {
+ (hex(major)?, hex(minor)?)
+ } else {
+ return Err("Couldn't parse dev");
};
let inode = hex(inode_str)?;
let pathname = pathname_str.into();
diff --git a/library/backtrace/src/symbolize/gimli/stash.rs b/library/backtrace/src/symbolize/gimli/stash.rs
index 3adfc598a..792f9a6f8 100644
--- a/library/backtrace/src/symbolize/gimli/stash.rs
+++ b/library/backtrace/src/symbolize/gimli/stash.rs
@@ -9,14 +9,14 @@ use core::cell::UnsafeCell;
/// A simple arena allocator for byte buffers.
pub struct Stash {
buffers: UnsafeCell<Vec<Vec<u8>>>,
- mmap_aux: UnsafeCell<Option<Mmap>>,
+ mmaps: UnsafeCell<Vec<Mmap>>,
}
impl Stash {
pub fn new() -> Stash {
Stash {
buffers: UnsafeCell::new(Vec::new()),
- mmap_aux: UnsafeCell::new(None),
+ mmaps: UnsafeCell::new(Vec::new()),
}
}
@@ -35,18 +35,16 @@ impl Stash {
/// Stores a `Mmap` for the lifetime of this `Stash`, returning a pointer
/// which is scoped to just this lifetime.
- pub fn set_mmap_aux(&self, map: Mmap) -> &[u8] {
+ pub fn cache_mmap(&self, map: Mmap) -> &[u8] {
// SAFETY: this is the only location for a mutable pointer to
- // `mmap_aux`, and this structure isn't threadsafe to shared across
- // threads either. This also is careful to store at most one `mmap_aux`
- // since overwriting a previous one would invalidate the previous
- // pointer. Given that though we can safely return a pointer to our
- // interior-owned contents.
+ // `mmaps`, and this structure isn't threadsafe to shared across
+ // threads either. We also never remove elements from `self.mmaps`,
+ // so a reference to the data inside the map will live as long as
+ // `self` does.
unsafe {
- let mmap_aux = &mut *self.mmap_aux.get();
- assert!(mmap_aux.is_none());
- *mmap_aux = Some(map);
- mmap_aux.as_ref().unwrap()
+ let mmaps = &mut *self.mmaps.get();
+ mmaps.push(map);
+ mmaps.last().unwrap()
}
}
}
diff --git a/library/backtrace/tests/current-exe-mismatch.rs b/library/backtrace/tests/current-exe-mismatch.rs
index 21c67bcbf..b655827fb 100644
--- a/library/backtrace/tests/current-exe-mismatch.rs
+++ b/library/backtrace/tests/current-exe-mismatch.rs
@@ -118,11 +118,8 @@ fn find_interpreter(me: &Path) -> Result<PathBuf, EarlyExit> {
let line = line?;
let line = line.trim();
let prefix = "[Requesting program interpreter: ";
- // This could use `line.split_once` and `suffix.rsplit_once` once the MSRV passes 1.52
- if let Some(idx) = line.find(prefix) {
- let (_, suffix) = line.split_at(idx + prefix.len());
- if let Some(idx) = suffix.rfind("]") {
- let (found_path, _ignore_remainder) = suffix.split_at(idx);
+ if let Some((_, suffix)) = line.split_once(prefix) {
+ if let Some((found_path, _)) = suffix.rsplit_once("]") {
return Ok(found_path.into());
}
}