115 lines
3.5 KiB
Rust
115 lines
3.5 KiB
Rust
// Check that backtrace info is correctly generated for dynamic libraries and is usable by a
|
|
// rust binary.
|
|
// Part of porting some backtrace tests to rustc: <https://github.com/rust-lang/rust/issues/122899>.
|
|
// Original test:
|
|
// <https://github.com/rust-lang/backtrace-rs/tree/6fa4b85b9962c3e1be8c2e5cc605cd078134152b/crates/dylib-dep>
|
|
// ignore-tidy-linelength
|
|
//@ ignore-android FIXME #17520
|
|
//@ ignore-fuchsia Backtraces not symbolized
|
|
//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written).
|
|
//@ needs-unwind
|
|
//@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes
|
|
//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs
|
|
//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs
|
|
//@ run-pass
|
|
|
|
#![allow(improper_ctypes)]
|
|
#![allow(improper_ctypes_definitions)]
|
|
|
|
extern crate dylib_dep_helper;
|
|
extern crate auxiliary;
|
|
|
|
use std::backtrace::Backtrace;
|
|
|
|
macro_rules! pos {
|
|
() => {
|
|
(file!(), line!())
|
|
};
|
|
}
|
|
|
|
macro_rules! check {
|
|
($($pos:expr),*) => ({
|
|
verify(&[$($pos,)* pos!()]);
|
|
})
|
|
}
|
|
|
|
fn verify(filelines: &[Pos]) {
|
|
let trace = Backtrace::capture();
|
|
eprintln!("-----------------------------------");
|
|
eprintln!("looking for:");
|
|
for (file, line) in filelines.iter().rev() {
|
|
eprintln!("\t{file}:{line}");
|
|
}
|
|
eprintln!("found:\n{trace:#?}");
|
|
let mut iter = filelines.iter().rev();
|
|
// FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now,
|
|
// this depends on the debug format of `Backtrace` which is of course fragile.
|
|
let backtrace = format!("{:#?}", trace);
|
|
while let Some((file, line)) = iter.next() {
|
|
// FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has
|
|
// them.
|
|
assert!(backtrace.contains(file), "expected backtrace to contain {}", file);
|
|
assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line);
|
|
}
|
|
}
|
|
|
|
type Pos = (&'static str, u32);
|
|
|
|
extern "C" {
|
|
#[link_name = "foo"]
|
|
fn foo(p: Pos, cb: fn(Pos, Pos));
|
|
}
|
|
|
|
fn main() {
|
|
std::env::set_var("RUST_BACKTRACE", "1");
|
|
|
|
unsafe {
|
|
foo(pos!(), |a, b| {
|
|
check!(a, b)
|
|
})
|
|
}
|
|
|
|
outer(pos!());
|
|
}
|
|
|
|
#[inline(never)]
|
|
fn outer(main_pos: Pos) {
|
|
inner(main_pos, pos!());
|
|
inner_inlined(main_pos, pos!());
|
|
}
|
|
|
|
#[inline(never)]
|
|
fn inner(main_pos: Pos, outer_pos: Pos) {
|
|
check!(main_pos, outer_pos);
|
|
check!(main_pos, outer_pos);
|
|
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
|
|
check!(main_pos, outer_pos, inner_pos, aux_pos);
|
|
});
|
|
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
|
|
check!(main_pos, outer_pos, inner_pos, aux_pos);
|
|
});
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn inner_inlined(main_pos: Pos, outer_pos: Pos) {
|
|
check!(main_pos, outer_pos);
|
|
check!(main_pos, outer_pos);
|
|
|
|
#[inline(always)]
|
|
fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
|
|
check!(main_pos, outer_pos, inner_pos);
|
|
}
|
|
inner_further_inlined(main_pos, outer_pos, pos!());
|
|
|
|
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
|
|
check!(main_pos, outer_pos, inner_pos, aux_pos);
|
|
});
|
|
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
|
|
check!(main_pos, outer_pos, inner_pos, aux_pos);
|
|
});
|
|
|
|
// this tests a distinction between two independent calls to the inlined function.
|
|
// (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
|
|
inner_further_inlined(main_pos, outer_pos, pos!());
|
|
}
|