Skip to content

Commit 08d5e28

Browse files
committed
Ignore functions before main and thread entry points in backtraces
1 parent 0119b44 commit 08d5e28

File tree

10 files changed

+73
-52
lines changed

10 files changed

+73
-52
lines changed

src/libstd/rt.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
// Re-export some of our utilities which are expected by other crates.
2727
pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
2828

29+
#[cfg(feature = "backtrace")]
30+
pub use sys_common::backtrace::begin_short_backtrace;
31+
32+
#[cfg(not(feature = "backtrace"))]
33+
#[unstable(feature = "rt", reason = "this is only exported for use in libtest", issue = "0")]
34+
pub fn begin_short_backtrace<F: FnOnce() -> R, R>(f: F) -> R {
35+
f()
36+
}
37+
2938
// To reduce the generated code of the new `lang_start`, this function is doing
3039
// the real work.
3140
#[cfg(not(test))]
@@ -56,7 +65,7 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
5665
// Let's run some code!
5766
#[cfg(feature = "backtrace")]
5867
let exit_code = panic::catch_unwind(|| {
59-
::sys_common::backtrace::__rust_begin_short_backtrace(move || main())
68+
::sys_common::backtrace::begin_short_backtrace(move || main())
6069
});
6170
#[cfg(not(feature = "backtrace"))]
6271
let exit_code = panic::catch_unwind(move || main());

src/libstd/sys/cloudabi/backtrace.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,17 @@ where
9595

9696
pub fn resolve_symname<F>(frame: Frame, callback: F, _: &BacktraceContext) -> io::Result<()>
9797
where
98-
F: FnOnce(Option<&str>) -> io::Result<()>,
98+
F: FnOnce(Option<(&str, usize)>) -> io::Result<()>,
9999
{
100100
unsafe {
101101
let mut info: Dl_info = intrinsics::init();
102-
let symname =
102+
let syminfo =
103103
if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() {
104104
None
105105
} else {
106-
CStr::from_ptr(info.dli_sname).to_str().ok()
106+
CStr::from_ptr(info.dli_sname).to_str().ok().map(|s| (s, info.dli_saddr as usize))
107107
};
108-
callback(symname)
108+
callback(syminfo)
109109
}
110110
}
111111

src/libstd/sys/unix/backtrace/printing/dladdr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ use sys_common::backtrace::Frame;
1818
pub fn resolve_symname<F>(frame: Frame,
1919
callback: F,
2020
_: &BacktraceContext) -> io::Result<()>
21-
where F: FnOnce(Option<&str>) -> io::Result<()>
21+
where F: FnOnce(Option<(&str, usize)>) -> io::Result<()>
2222
{
2323
unsafe {
2424
let mut info: Dl_info = intrinsics::init();
25-
let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 ||
25+
let syminfo = if dladdr(frame.exact_position as *mut _, &mut info) == 0 ||
2626
info.dli_sname.is_null() {
2727
None
2828
} else {
29-
CStr::from_ptr(info.dli_sname).to_str().ok()
29+
CStr::from_ptr(info.dli_sname).to_str().ok().map(|s| (s, info.dli_saddr as usize))
3030
};
31-
callback(symname)
31+
callback(syminfo)
3232
}
3333
}
3434

src/libstd/sys/unix/backtrace/printing/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ pub use sys_common::gnu::libbacktrace::foreach_symbol_fileline;
3131
#[cfg(not(target_os = "emscripten"))]
3232
pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()>
3333
where
34-
F: FnOnce(Option<&str>) -> io::Result<()>
34+
F: FnOnce(Option<(&str, usize)>) -> io::Result<()>
3535
{
36-
::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| {
37-
if symname.is_some() {
38-
callback(symname)
36+
::sys_common::gnu::libbacktrace::resolve_symname(frame, |syminfo| {
37+
if syminfo.is_some() {
38+
callback(syminfo)
3939
} else {
4040
dladdr::resolve_symname(frame, callback, bc)
4141
}

src/libstd/sys/wasm/backtrace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn unwind_backtrace(_frames: &mut [Frame])
2323
pub fn resolve_symname<F>(_frame: Frame,
2424
_callback: F,
2525
_: &BacktraceContext) -> io::Result<()>
26-
where F: FnOnce(Option<&str>) -> io::Result<()>
26+
where F: FnOnce(Option<(&str, usize)>) -> io::Result<()>
2727
{
2828
unsupported()
2929
}

src/libstd/sys/windows/backtrace/printing/msvc.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type SymGetLineFromInlineContextFn =
2727
pub fn resolve_symname<F>(frame: Frame,
2828
callback: F,
2929
context: &BacktraceContext) -> io::Result<()>
30-
where F: FnOnce(Option<&str>) -> io::Result<()>
30+
where F: FnOnce(Option<(&str, usize)>) -> io::Result<()>
3131
{
3232
let SymFromInlineContext = sym!(&context.dbghelp,
3333
"SymFromInlineContext",
@@ -57,13 +57,15 @@ pub fn resolve_symname<F>(frame: Frame,
5757
} else {
5858
false
5959
};
60-
let symname = if valid_range {
60+
let syminfo = if valid_range {
6161
let ptr = info.Name.as_ptr() as *const c_char;
62-
CStr::from_ptr(ptr).to_str().ok()
62+
CStr::from_ptr(ptr).to_str().ok().map(|s| {
63+
(s, (frame.symbol_addr as usize).wrapping_sub(displacement as usize))
64+
})
6365
} else {
6466
None
6567
};
66-
callback(symname)
68+
callback(syminfo)
6769
}
6870
}
6971

src/libstd/sys_common/backtrace.rs

+27-13
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
7979

8080
let filtered_frames = &frames[..nb_frames - skipped_after];
8181
for (index, frame) in filtered_frames.iter().skip(skipped_before).enumerate() {
82-
resolve_symname(*frame, |symname| {
83-
output(w, index, *frame, symname, format)
82+
resolve_symname(*frame, |syminfo| {
83+
output(w, index, *frame, syminfo.map(|i| i.0), format)
8484
}, &context)?;
8585
let has_more_filenames = foreach_symbol_fileline(*frame, |file, line| {
8686
output_fileline(w, file, line, format)
@@ -105,14 +105,14 @@ fn filter_frames(frames: &[Frame],
105105

106106
let skipped_before = 0;
107107

108+
// Look for the first occurence of `mark_start`
109+
// There can be multiple in one backtrace
110+
// Skip all frames after that
108111
let skipped_after = frames.len() - frames.iter().position(|frame| {
109112
let mut is_marker = false;
110-
let _ = resolve_symname(*frame, |symname| {
111-
if let Some(mangled_symbol_name) = symname {
112-
// Use grep to find the concerned functions
113-
if mangled_symbol_name.contains("__rust_begin_short_backtrace") {
114-
is_marker = true;
115-
}
113+
let _ = resolve_symname(*frame, |syminfo| {
114+
if syminfo.map(|i| i.1) == Some(MARK_START as usize) {
115+
is_marker = true;
116116
}
117117
Ok(())
118118
}, context);
@@ -127,13 +127,27 @@ fn filter_frames(frames: &[Frame],
127127
(skipped_before, skipped_after)
128128
}
129129

130+
static MARK_START: fn(&mut FnMut()) = mark_start;
130131

131-
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
132+
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`
132133
#[inline(never)]
133-
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
134-
where F: FnOnce() -> T, F: Send, T: Send
135-
{
136-
f()
134+
fn mark_start(f: &mut FnMut()) {
135+
f();
136+
unsafe {
137+
asm!("" ::: "memory" : "volatile"); // A dummy statement to prevent tail call optimization
138+
}
139+
}
140+
141+
/// Convenience wrapper for `mark_start`
142+
#[unstable(feature = "rt", reason = "this is only exported for use in libtest", issue = "0")]
143+
pub fn begin_short_backtrace<F: FnOnce() -> R, R>(f: F) -> R {
144+
let mut f = Some(f);
145+
let mut r = None;
146+
mark_start(&mut || {
147+
let f = f.take().unwrap();
148+
r = Some(f());
149+
});
150+
r.unwrap()
137151
}
138152

139153
/// Controls how the backtrace should be formated.

src/libstd/sys_common/gnu/libbacktrace.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -63,34 +63,34 @@ where F: FnMut(&[u8], u32) -> io::Result<()>
6363
pub fn resolve_symname<F>(frame: Frame,
6464
callback: F,
6565
_: &BacktraceContext) -> io::Result<()>
66-
where F: FnOnce(Option<&str>) -> io::Result<()>
66+
where F: FnOnce(Option<(&str, usize)>) -> io::Result<()>
6767
{
68-
let symname = {
68+
let syminfo = {
6969
let state = unsafe { init_state() };
7070
if state.is_null() {
7171
return Err(io::Error::new(
7272
io::ErrorKind::Other,
7373
"failed to allocate libbacktrace state")
7474
)
7575
}
76-
let mut data: *const libc::c_char = ptr::null();
77-
let data_addr = &mut data as *mut *const libc::c_char;
76+
let mut data: (*const libc::c_char, _) = (ptr::null(), 0);
77+
let data_addr = &mut data as *mut _;
7878
let ret = unsafe {
7979
backtrace_syminfo(state,
8080
frame.symbol_addr as libc::uintptr_t,
8181
syminfo_cb,
8282
error_cb,
8383
data_addr as *mut libc::c_void)
8484
};
85-
if ret == 0 || data.is_null() {
85+
if ret == 0 || data.0.is_null() {
8686
None
8787
} else {
8888
unsafe {
89-
CStr::from_ptr(data).to_str().ok()
89+
CStr::from_ptr(data.0).to_str().ok().map(|s| (s, data.1))
9090
}
9191
}
9292
};
93-
callback(symname)
93+
callback(syminfo)
9494
}
9595

9696
////////////////////////////////////////////////////////////////////////
@@ -145,10 +145,10 @@ extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
145145
extern fn syminfo_cb(data: *mut libc::c_void,
146146
_pc: libc::uintptr_t,
147147
symname: *const libc::c_char,
148-
_symval: libc::uintptr_t,
148+
symval: libc::uintptr_t,
149149
_symsize: libc::uintptr_t) {
150-
let slot = data as *mut *const libc::c_char;
151-
unsafe { *slot = symname; }
150+
let slot = data as *mut (*const libc::c_char, usize);
151+
unsafe { *slot = (symname, symval); }
152152
}
153153
extern fn pcinfo_cb(data: *mut libc::c_void,
154154
_pc: libc::uintptr_t,

src/libstd/thread/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ impl Builder {
403403
thread_info::set(imp::guard::current(), their_thread);
404404
#[cfg(feature = "backtrace")]
405405
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
406-
::sys_common::backtrace::__rust_begin_short_backtrace(f)
406+
::sys_common::backtrace::begin_short_backtrace(f)
407407
}));
408408
#[cfg(not(feature = "backtrace"))]
409409
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));

src/libtest/lib.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#![feature(set_stdio)]
4141
#![feature(panic_unwind)]
4242
#![feature(staged_api)]
43+
#![feature(rt)]
4344

4445
extern crate getopts;
4546
extern crate term;
@@ -72,6 +73,7 @@ use std::sync::{Arc, Mutex};
7273
use std::thread;
7374
use std::time::{Instant, Duration};
7475
use std::borrow::Cow;
76+
use std::rt::begin_short_backtrace;
7577

7678
const TEST_WARN_TIMEOUT_S: u64 = 60;
7779
const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode
@@ -1344,14 +1346,14 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
13441346
DynBenchFn(bench) => {
13451347
DynTestFn(Box::new(move || {
13461348
bench::run_once(|b| {
1347-
__rust_begin_short_backtrace(|| bench.run(b))
1349+
begin_short_backtrace(|| bench.run(b))
13481350
})
13491351
}))
13501352
}
13511353
StaticBenchFn(benchfn) => {
13521354
DynTestFn(Box::new(move || {
13531355
bench::run_once(|b| {
1354-
__rust_begin_short_backtrace(|| benchfn(b))
1356+
begin_short_backtrace(|| benchfn(b))
13551357
})
13561358
}))
13571359
}
@@ -1444,23 +1446,17 @@ pub fn run_test(
14441446
}
14451447
DynTestFn(f) => {
14461448
let cb = move || {
1447-
__rust_begin_short_backtrace(f)
1449+
begin_short_backtrace(f)
14481450
};
14491451
run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb))
14501452
}
14511453
StaticTestFn(f) => {
14521454
run_test_inner(desc, monitor_ch, opts.nocapture,
1453-
Box::new(move || __rust_begin_short_backtrace(f)))
1455+
Box::new(move || begin_short_backtrace(f)))
14541456
}
14551457
}
14561458
}
14571459

1458-
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
1459-
#[inline(never)]
1460-
fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
1461-
f()
1462-
}
1463-
14641460
fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> TestResult {
14651461
match (&desc.should_panic, task_result) {
14661462
(&ShouldPanic::No, Ok(())) |

0 commit comments

Comments
 (0)