summaryrefslogtreecommitdiffstats
path: root/library/backtrace/crates
diff options
context:
space:
mode:
Diffstat (limited to 'library/backtrace/crates')
-rw-r--r--library/backtrace/crates/as-if-std/Cargo.toml29
-rw-r--r--library/backtrace/crates/as-if-std/build.rs3
-rw-r--r--library/backtrace/crates/as-if-std/src/lib.rs21
-rw-r--r--library/backtrace/crates/cpp_smoke_test/Cargo.toml11
-rw-r--r--library/backtrace/crates/cpp_smoke_test/build.rs14
-rw-r--r--library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp14
-rw-r--r--library/backtrace/crates/cpp_smoke_test/src/lib.rs2
-rw-r--r--library/backtrace/crates/cpp_smoke_test/tests/smoke.rs73
-rw-r--r--library/backtrace/crates/debuglink/Cargo.toml7
-rw-r--r--library/backtrace/crates/debuglink/src/main.rs34
-rw-r--r--library/backtrace/crates/dylib-dep/Cargo.toml10
-rw-r--r--library/backtrace/crates/dylib-dep/src/lib.rs14
-rw-r--r--library/backtrace/crates/line-tables-only/Cargo.toml21
-rw-r--r--library/backtrace/crates/line-tables-only/build.rs10
-rw-r--r--library/backtrace/crates/line-tables-only/src/callback.c14
-rw-r--r--library/backtrace/crates/line-tables-only/src/lib.rs57
-rw-r--r--library/backtrace/crates/macos_frames_test/Cargo.toml8
-rw-r--r--library/backtrace/crates/macos_frames_test/src/lib.rs1
-rw-r--r--library/backtrace/crates/macos_frames_test/tests/main.rs30
-rw-r--r--library/backtrace/crates/without_debuginfo/Cargo.toml20
-rw-r--r--library/backtrace/crates/without_debuginfo/src/lib.rs1
-rw-r--r--library/backtrace/crates/without_debuginfo/tests/smoke.rs44
22 files changed, 438 insertions, 0 deletions
diff --git a/library/backtrace/crates/as-if-std/Cargo.toml b/library/backtrace/crates/as-if-std/Cargo.toml
new file mode 100644
index 000000000..c763227f2
--- /dev/null
+++ b/library/backtrace/crates/as-if-std/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "as-if-std"
+version = "0.1.0"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+edition = "2018"
+publish = false
+
+[lib]
+test = false
+doc = false
+doctest = false
+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 }
+
+[dependencies.object]
+version = "0.28"
+default-features = false
+optional = true
+features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
+
+[features]
+default = ['backtrace']
+backtrace = ['addr2line', 'object']
diff --git a/library/backtrace/crates/as-if-std/build.rs b/library/backtrace/crates/as-if-std/build.rs
new file mode 100644
index 000000000..7018b1017
--- /dev/null
+++ b/library/backtrace/crates/as-if-std/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("cargo:rustc-cfg=backtrace_in_libstd");
+}
diff --git a/library/backtrace/crates/as-if-std/src/lib.rs b/library/backtrace/crates/as-if-std/src/lib.rs
new file mode 100644
index 000000000..c0f49b77d
--- /dev/null
+++ b/library/backtrace/crates/as-if-std/src/lib.rs
@@ -0,0 +1,21 @@
+// A crate which builds the `backtrace` crate as-if it's included as a
+// submodule into the standard library. We try to set this crate up similarly
+// to the standard library itself to minimize the likelihood of issues when
+// updating the `backtrace` crate.
+
+#![no_std]
+
+extern crate alloc;
+
+// We want to `pub use std::*` in the root but we don't want `std` available in
+// the root namespace, so do this in a funky inner module.
+mod __internal {
+ extern crate std;
+ pub use std::*;
+}
+
+pub use __internal::*;
+
+// This is the magical part which we hope works.
+#[path = "../../../src/lib.rs"]
+mod the_backtrace_crate;
diff --git a/library/backtrace/crates/cpp_smoke_test/Cargo.toml b/library/backtrace/crates/cpp_smoke_test/Cargo.toml
new file mode 100644
index 000000000..1325d7c04
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "cpp_smoke_test"
+version = "0.1.0"
+authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
+build = "build.rs"
+
+[build-dependencies]
+cc = "1.0"
+
+[dependencies]
+backtrace = { path = "../..", features = ["cpp_demangle"] }
diff --git a/library/backtrace/crates/cpp_smoke_test/build.rs b/library/backtrace/crates/cpp_smoke_test/build.rs
new file mode 100644
index 000000000..5ddc63d82
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/build.rs
@@ -0,0 +1,14 @@
+fn main() {
+ compile_cpp();
+}
+
+fn compile_cpp() {
+ println!("cargo:rerun-if-changed=cpp/trampoline.cpp");
+
+ cc::Build::new()
+ .cpp(true)
+ .debug(true)
+ .opt_level(0)
+ .file("cpp/trampoline.cpp")
+ .compile("libcpptrampoline.a");
+}
diff --git a/library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp b/library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp
new file mode 100644
index 000000000..61e09604c
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+namespace space {
+ template <typename FuncT>
+ void templated_trampoline(FuncT func) {
+ func();
+ }
+}
+
+typedef void (*FuncPtr)();
+
+extern "C" void cpp_trampoline(FuncPtr func) {
+ space::templated_trampoline(func);
+}
diff --git a/library/backtrace/crates/cpp_smoke_test/src/lib.rs b/library/backtrace/crates/cpp_smoke_test/src/lib.rs
new file mode 100644
index 000000000..2002ef17d
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/src/lib.rs
@@ -0,0 +1,2 @@
+#[test]
+fn it_works() {}
diff --git a/library/backtrace/crates/cpp_smoke_test/tests/smoke.rs b/library/backtrace/crates/cpp_smoke_test/tests/smoke.rs
new file mode 100644
index 000000000..b9aef47f5
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/tests/smoke.rs
@@ -0,0 +1,73 @@
+extern crate backtrace;
+extern crate cpp_smoke_test;
+
+use std::sync::atomic::{AtomicBool, Ordering};
+
+extern "C" {
+ fn cpp_trampoline(func: extern "C" fn()) -> ();
+}
+
+#[test]
+#[ignore] // fixme(fitzgen/cpp_demangle#73)
+fn smoke_test_cpp() {
+ static RAN_ASSERTS: AtomicBool = AtomicBool::new(false);
+
+ extern "C" fn assert_cpp_frames() {
+ let mut physical_frames = Vec::new();
+ backtrace::trace(|cx| {
+ physical_frames.push(cx.ip());
+
+ // We only want to capture this closure's frame, assert_cpp_frames,
+ // space::templated_trampoline, and cpp_trampoline. Those are
+ // logical frames, which might be inlined into fewer physical
+ // frames, so we may end up with extra logical frames after
+ // resolving these.
+ physical_frames.len() < 4
+ });
+
+ let names: Vec<_> = physical_frames
+ .into_iter()
+ .flat_map(|ip| {
+ let mut logical_frame_names = vec![];
+
+ backtrace::resolve(ip, |sym| {
+ let sym_name = sym.name().expect("Should have a symbol name");
+ let demangled = sym_name.to_string();
+ logical_frame_names.push(demangled);
+ });
+
+ assert!(
+ !logical_frame_names.is_empty(),
+ "Should have resolved at least one symbol for the physical frame"
+ );
+
+ logical_frame_names
+ })
+ // Skip the backtrace::trace closure and assert_cpp_frames, and then
+ // take the two C++ frame names.
+ .skip_while(|name| !name.contains("trampoline"))
+ .take(2)
+ .collect();
+
+ println!("actual names = {:#?}", names);
+
+ let expected = [
+ "void space::templated_trampoline<void (*)()>(void (*)())",
+ "cpp_trampoline",
+ ];
+ println!("expected names = {:#?}", expected);
+
+ assert_eq!(names.len(), expected.len());
+ for (actual, expected) in names.iter().zip(expected.iter()) {
+ assert_eq!(actual, expected);
+ }
+
+ RAN_ASSERTS.store(true, Ordering::SeqCst);
+ }
+
+ assert!(!RAN_ASSERTS.load(Ordering::SeqCst));
+ unsafe {
+ cpp_trampoline(assert_cpp_frames);
+ }
+ assert!(RAN_ASSERTS.load(Ordering::SeqCst));
+}
diff --git a/library/backtrace/crates/debuglink/Cargo.toml b/library/backtrace/crates/debuglink/Cargo.toml
new file mode 100644
index 000000000..6b55b1394
--- /dev/null
+++ b/library/backtrace/crates/debuglink/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "debuglink"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+backtrace = { path = "../.." }
diff --git a/library/backtrace/crates/debuglink/src/main.rs b/library/backtrace/crates/debuglink/src/main.rs
new file mode 100644
index 000000000..99265ae9a
--- /dev/null
+++ b/library/backtrace/crates/debuglink/src/main.rs
@@ -0,0 +1,34 @@
+// Test that the debuginfo is being found by checking that the
+// backtrace contains `main` and that the source filename uses
+// the path given in the command line arguments.
+//
+// For dwz tests, this assumes that the path string will be moved into
+// the dwz file.
+fn main() {
+ let crate_dir = std::env::args().skip(1).next().unwrap();
+ let expect = std::path::Path::new(&crate_dir).join("src/main.rs");
+
+ let bt = backtrace::Backtrace::new();
+ println!("{:?}", bt);
+
+ let mut found_main = false;
+
+ for frame in bt.frames() {
+ let symbols = frame.symbols();
+ if symbols.is_empty() {
+ continue;
+ }
+
+ if let Some(name) = symbols[0].name() {
+ let name = format!("{:#}", name);
+ if name == "debuglink::main" {
+ found_main = true;
+ let filename = symbols[0].filename().unwrap();
+ assert_eq!(filename, expect);
+ break;
+ }
+ }
+ }
+
+ assert!(found_main);
+}
diff --git a/library/backtrace/crates/dylib-dep/Cargo.toml b/library/backtrace/crates/dylib-dep/Cargo.toml
new file mode 100644
index 000000000..c3d4a8c2f
--- /dev/null
+++ b/library/backtrace/crates/dylib-dep/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "dylib-dep"
+version = "0.1.0"
+edition = "2018"
+authors = []
+publish = false
+
+[lib]
+name = "dylib_dep"
+crate-type = ["cdylib", "rlib"]
diff --git a/library/backtrace/crates/dylib-dep/src/lib.rs b/library/backtrace/crates/dylib-dep/src/lib.rs
new file mode 100644
index 000000000..201807797
--- /dev/null
+++ b/library/backtrace/crates/dylib-dep/src/lib.rs
@@ -0,0 +1,14 @@
+#![allow(improper_ctypes_definitions)]
+
+type Pos = (&'static str, u32);
+
+macro_rules! pos {
+ () => {
+ (file!(), line!())
+ };
+}
+
+#[no_mangle]
+pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) {
+ inner(outer, pos!());
+}
diff --git a/library/backtrace/crates/line-tables-only/Cargo.toml b/library/backtrace/crates/line-tables-only/Cargo.toml
new file mode 100644
index 000000000..e2967d3d3
--- /dev/null
+++ b/library/backtrace/crates/line-tables-only/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "line-tables-only"
+version = "0.1.0"
+edition = "2018"
+
+[build-dependencies]
+cc = "1.0"
+
+[dependencies]
+libc = { version = "0.2", default-features = false }
+
+[dependencies.backtrace]
+path = "../.."
+features = [
+ 'libunwind',
+ 'std',
+]
+
+[features]
+libbacktrace = ['backtrace/libbacktrace']
+gimli-symbolize = ['backtrace/gimli-symbolize']
diff --git a/library/backtrace/crates/line-tables-only/build.rs b/library/backtrace/crates/line-tables-only/build.rs
new file mode 100644
index 000000000..125fb7645
--- /dev/null
+++ b/library/backtrace/crates/line-tables-only/build.rs
@@ -0,0 +1,10 @@
+fn main() {
+ println!("cargo:rerun-if-changed=src/callback.c");
+
+ cc::Build::new()
+ .opt_level(0)
+ .debug(false)
+ .flag("-g1")
+ .file("src/callback.c")
+ .compile("libcallback.a");
+}
diff --git a/library/backtrace/crates/line-tables-only/src/callback.c b/library/backtrace/crates/line-tables-only/src/callback.c
new file mode 100644
index 000000000..c9d5d072a
--- /dev/null
+++ b/library/backtrace/crates/line-tables-only/src/callback.c
@@ -0,0 +1,14 @@
+
+typedef void (*callback) (void *data);
+
+void baz(callback cb, void *data) {
+ cb(data);
+}
+
+void bar(callback cb, void *data) {
+ baz(cb, data);
+}
+
+void foo(callback cb, void *data) {
+ bar(cb, data);
+}
diff --git a/library/backtrace/crates/line-tables-only/src/lib.rs b/library/backtrace/crates/line-tables-only/src/lib.rs
new file mode 100644
index 000000000..bd5afcb3a
--- /dev/null
+++ b/library/backtrace/crates/line-tables-only/src/lib.rs
@@ -0,0 +1,57 @@
+#[cfg(test)]
+mod tests {
+ use std::path::Path;
+ use backtrace::Backtrace;
+ use libc::c_void;
+
+ pub type Callback = extern "C" fn(data: *mut c_void);
+
+ extern "C" {
+ fn foo(cb: Callback, data: *mut c_void);
+ }
+
+ extern "C" fn store_backtrace(data: *mut c_void) {
+ let bt = backtrace::Backtrace::new();
+ unsafe { *(data as *mut Option<Backtrace>) = Some(bt) };
+ }
+
+ fn assert_contains(backtrace: &Backtrace,
+ expected_name: &str,
+ expected_file: &str,
+ expected_line: u32) {
+
+ let expected_file = Path::new(expected_file);
+
+ for frame in backtrace.frames() {
+ for symbol in frame.symbols() {
+ if let Some(name) = symbol.name() {
+ if name.as_bytes() == expected_name.as_bytes() {
+ assert!(symbol.filename().unwrap().ends_with(expected_file));
+ assert_eq!(symbol.lineno(), Some(expected_line));
+ return;
+ }
+ }
+ }
+ }
+
+ panic!("symbol {:?} not found in backtrace: {:?}", expected_name, backtrace);
+ }
+
+ /// Verifies that when debug info includes only lines tables the generated
+ /// backtrace is still generated successfully. The test exercises behaviour
+ /// that failed previously when compiling with clang -g1.
+ ///
+ /// The test case uses C rather than rust, since at that time when it was
+ /// written the debug info generated at level 1 in rustc was essentially
+ /// the same as at level 2.
+ #[test]
+ #[cfg_attr(windows, ignore)]
+ fn backtrace_works_with_line_tables_only() {
+ let mut backtrace: Option<Backtrace> = None;
+ unsafe { foo(store_backtrace, &mut backtrace as *mut _ as *mut c_void) };
+ let backtrace = backtrace.expect("backtrace");
+ assert_contains(&backtrace, "foo", "src/callback.c", 13);
+ assert_contains(&backtrace, "bar", "src/callback.c", 9);
+ assert_contains(&backtrace, "baz", "src/callback.c", 5);
+ }
+}
diff --git a/library/backtrace/crates/macos_frames_test/Cargo.toml b/library/backtrace/crates/macos_frames_test/Cargo.toml
new file mode 100644
index 000000000..278d51e79
--- /dev/null
+++ b/library/backtrace/crates/macos_frames_test/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "macos_frames_test"
+version = "0.1.0"
+authors = ["Aaron Hill <aa1ronham@gmail.com>"]
+edition = "2018"
+
+[dependencies.backtrace]
+path = "../.."
diff --git a/library/backtrace/crates/macos_frames_test/src/lib.rs b/library/backtrace/crates/macos_frames_test/src/lib.rs
new file mode 100644
index 000000000..65e2cc340
--- /dev/null
+++ b/library/backtrace/crates/macos_frames_test/src/lib.rs
@@ -0,0 +1 @@
+// intentionally blank
diff --git a/library/backtrace/crates/macos_frames_test/tests/main.rs b/library/backtrace/crates/macos_frames_test/tests/main.rs
new file mode 100644
index 000000000..f0e905b24
--- /dev/null
+++ b/library/backtrace/crates/macos_frames_test/tests/main.rs
@@ -0,0 +1,30 @@
+// Based on from https://github.com/rust-lang/rust/blob/2cb0b8582ebbf9784db9cec06fff517badbf4553/src/test/ui/issues/issue-45731.rs
+// This needs to go in a crate by itself, since it modifies the dSYM for the entire test
+// output directory.
+//
+// Note that this crate is *not* part of the overall `backtrace-rs` workspace,
+// so that it gets its own 'target' directory. We manually invoke this test
+// in .github/workflows/main.yml by passing `--manifest-path` to Cargo
+#[test]
+#[cfg(target_os = "macos")]
+fn backtrace_no_dsym() {
+ use std::{env, fs};
+
+ // Find our dSYM and replace the DWARF binary with an empty file
+ let mut dsym_path = env::current_exe().unwrap();
+ let executable_name = dsym_path.file_name().unwrap().to_str().unwrap().to_string();
+ assert!(dsym_path.pop()); // Pop executable
+ dsym_path.push(format!(
+ "{}.dSYM/Contents/Resources/DWARF/{0}",
+ executable_name
+ ));
+ let _ = fs::OpenOptions::new()
+ .read(false)
+ .write(true)
+ .truncate(true)
+ .create(false)
+ .open(&dsym_path)
+ .unwrap();
+
+ backtrace::Backtrace::new();
+}
diff --git a/library/backtrace/crates/without_debuginfo/Cargo.toml b/library/backtrace/crates/without_debuginfo/Cargo.toml
new file mode 100644
index 000000000..19d76cbec
--- /dev/null
+++ b/library/backtrace/crates/without_debuginfo/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "without_debuginfo"
+version = "0.1.0"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+edition = "2018"
+
+[dependencies.backtrace]
+path = "../.."
+default-features = false
+features = ['std']
+
+[profile.dev]
+debug = false
+
+[profile.test]
+debug = false
+
+[features]
+libbacktrace = ['backtrace/libbacktrace']
+gimli-symbolize = ['backtrace/gimli-symbolize']
diff --git a/library/backtrace/crates/without_debuginfo/src/lib.rs b/library/backtrace/crates/without_debuginfo/src/lib.rs
new file mode 100644
index 000000000..65e2cc340
--- /dev/null
+++ b/library/backtrace/crates/without_debuginfo/src/lib.rs
@@ -0,0 +1 @@
+// intentionally blank
diff --git a/library/backtrace/crates/without_debuginfo/tests/smoke.rs b/library/backtrace/crates/without_debuginfo/tests/smoke.rs
new file mode 100644
index 000000000..5a0dfea15
--- /dev/null
+++ b/library/backtrace/crates/without_debuginfo/tests/smoke.rs
@@ -0,0 +1,44 @@
+#[test]
+fn all_frames_have_symbols() {
+ println!("{:?}", backtrace::Backtrace::new());
+
+ let mut missing_symbols = 0;
+ let mut has_symbols = 0;
+ backtrace::trace(|frame| {
+ let mut any = false;
+ backtrace::resolve_frame(frame, |sym| {
+ if sym.name().is_some() {
+ any = true;
+ }
+ });
+ if any {
+ has_symbols += 1;
+ } else if !frame.ip().is_null() {
+ missing_symbols += 1;
+ }
+ true
+ });
+
+ // FIXME(#346) currently on MinGW we can't symbolize kernel32.dll and other
+ // system libraries, which means we miss the last few symbols.
+ if cfg!(windows) && cfg!(target_env = "gnu") {
+ assert!(missing_symbols < has_symbols && has_symbols > 4);
+ } else {
+ assert_eq!(missing_symbols, 0);
+ }
+}
+
+#[test]
+fn all_frames_have_module_base_address() {
+ let mut missing_base_addresses = 0;
+ backtrace::trace(|frame| {
+ if frame.module_base_address().is_none() {
+ missing_base_addresses += 1;
+ }
+ true
+ });
+
+ if cfg!(windows) {
+ assert_eq!(missing_base_addresses, 0);
+ }
+}