Skip to content

Commit 343448e

Browse files
committed
Port backtrace dylib-dep test to a ui test
1 parent 6a92312 commit 343448e

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ compile-flags: -g -Cstrip=none
2+
3+
#[inline(never)]
4+
pub fn callback<F>(f: F)
5+
where
6+
F: FnOnce((&'static str, u32)),
7+
{
8+
f((file!(), line!()))
9+
}
10+
11+
#[inline(always)]
12+
pub fn callback_inlined<F>(f: F)
13+
where
14+
F: FnOnce((&'static str, u32)),
15+
{
16+
f((file!(), line!()))
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ compile-flags: -g -Cstrip=none
2+
3+
#![crate_type = "cdylib"]
4+
#![crate_type = "rlib"]
5+
6+
#![allow(improper_ctypes_definitions)]
7+
8+
type Pos = (&'static str, u32);
9+
10+
macro_rules! pos {
11+
() => {
12+
(file!(), line!())
13+
};
14+
}
15+
16+
#[no_mangle]
17+
pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) {
18+
inner(outer, pos!());
19+
}
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Check that backtrace info is correctly generated for dynamic libraries and is usable by a
2+
// rust binary.
3+
// Part of porting some backtrace tests to rustc: <https://github.com/rust-lang/rust/issues/122899>.
4+
// Original test:
5+
// <https://github.com/rust-lang/backtrace-rs/tree/6fa4b85b9962c3e1be8c2e5cc605cd078134152b/crates/dylib-dep>
6+
// ignore-tidy-linelength
7+
//@ ignore-android FIXME #17520
8+
//@ ignore-fuchsia Backtraces not symbolized
9+
//@ needs-unwind
10+
//@ compile-flags: -g -Copt-level=0 -Cstrip=none
11+
//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs
12+
//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs
13+
//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written).
14+
//@ run-pass
15+
16+
#![allow(improper_ctypes)]
17+
#![allow(improper_ctypes_definitions)]
18+
19+
extern crate dylib_dep_helper;
20+
extern crate auxiliary;
21+
22+
use std::backtrace::Backtrace;
23+
24+
macro_rules! pos {
25+
() => {
26+
(file!(), line!())
27+
};
28+
}
29+
30+
macro_rules! check {
31+
($($pos:expr),*) => ({
32+
verify(&[$($pos,)* pos!()]);
33+
})
34+
}
35+
36+
fn verify(filelines: &[Pos]) {
37+
let trace = Backtrace::capture();
38+
eprintln!("-----------------------------------");
39+
eprintln!("looking for:");
40+
for (file, line) in filelines.iter().rev() {
41+
eprintln!("\t{file}:{line}");
42+
}
43+
eprintln!("found:\n{trace:#?}");
44+
let mut iter = filelines.iter().rev();
45+
// FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now,
46+
// this depends on the debug format of `Backtrace` which is of course fragile.
47+
let backtrace = format!("{:#?}", trace);
48+
while let Some((file, line)) = iter.next() {
49+
// FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has
50+
// them.
51+
assert!(backtrace.contains(file), "expected backtrace to contain {}", file);
52+
assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line);
53+
}
54+
}
55+
56+
type Pos = (&'static str, u32);
57+
58+
extern "C" {
59+
#[link_name = "foo"]
60+
fn foo(p: Pos, cb: fn(Pos, Pos));
61+
}
62+
63+
fn main() {
64+
std::env::set_var("RUST_BACKTRACE", "1");
65+
std::env::set_var("WASMTIME_BACKTRACE_DETAILS", "1");
66+
67+
unsafe {
68+
foo(pos!(), |a, b| {
69+
check!(a, b)
70+
})
71+
}
72+
73+
outer(pos!());
74+
}
75+
76+
#[inline(never)]
77+
fn outer(main_pos: Pos) {
78+
inner(main_pos, pos!());
79+
inner_inlined(main_pos, pos!());
80+
}
81+
82+
#[inline(never)]
83+
fn inner(main_pos: Pos, outer_pos: Pos) {
84+
check!(main_pos, outer_pos);
85+
check!(main_pos, outer_pos);
86+
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
87+
check!(main_pos, outer_pos, inner_pos, aux_pos);
88+
});
89+
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
90+
check!(main_pos, outer_pos, inner_pos, aux_pos);
91+
});
92+
}
93+
94+
#[inline(always)]
95+
fn inner_inlined(main_pos: Pos, outer_pos: Pos) {
96+
check!(main_pos, outer_pos);
97+
check!(main_pos, outer_pos);
98+
99+
#[inline(always)]
100+
fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
101+
check!(main_pos, outer_pos, inner_pos);
102+
}
103+
inner_further_inlined(main_pos, outer_pos, pos!());
104+
105+
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
106+
check!(main_pos, outer_pos, inner_pos, aux_pos);
107+
});
108+
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
109+
check!(main_pos, outer_pos, inner_pos, aux_pos);
110+
});
111+
112+
// this tests a distinction between two independent calls to the inlined function.
113+
// (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
114+
inner_further_inlined(main_pos, outer_pos, pos!());
115+
}

0 commit comments

Comments
 (0)