As titled.
I know that __rust_begin_short_backtrace
is used for stack backtracing, but how does it work actually? I find the implementation of it is really short just like below. And what it does is only calling the passed-in function indirectly, and return back the result. I also find the counterpart function __rust_end_short_backtrace
which has totally identical implementation. The code is at library/std/src/sys_common/backtrace.rs .
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
/// this is only inline(never) when backtraces in libstd are enabled, otherwise
/// it's fine to optimize away.
#[cfg_attr(feature = "backtrace", inline(never))]
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
where
F: FnOnce() -> T,
{
let result = f();
// prevent this frame from being tail-call optimised away
crate::hint::black_box(());
result
}
Another part of the related implementation is also at " library/std/src/sys_common/backtrace.rs ". Below is a snippet of code of this part which I think is highly related and important, but I don't understand the logic here that how Rust deals with the symbols that relate to the previous two functions:
backtrace_rs::trace_unsynchronized(|frame| {
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
return false;
}
let mut hit = false;
let mut stop = false;
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
hit = true;
if print_fmt == PrintFmt::Short {
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
if sym.contains("__rust_begin_short_backtrace") {
stop = true;
return;
}
if sym.contains("__rust_end_short_backtrace") {
start = true;
return;
}
}
}
if start {
res = bt_fmt.frame().symbol(frame, symbol);
}
});
if stop {
return false;
}
if !hit {
if start {
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
}
}
idx += 1;
res.is_ok()
});
Rust is inserting these "dummy symbols" to allow a short backtrace.
Consider this code
fn a() {
b()
}
fn b() {
c()
}
fn c() {
d()
}
fn d() {
panic!()
}
fn main() {
a()
}
This gives a nice backtrace
$ rustc demo.rs
$ RUST_BACKTRACE=1 ./demo
thread 'main' panicked at 'explicit panic', demo.rs:14:5
stack backtrace:
0: std::panicking::begin_panic
1: demo::d
2: demo::c
3: demo::b
4: demo::a
5: demo::main
6: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
If we instead use RUST_BACKTRACE=full
$ RUST_BACKTRACE=full ./demo
thread 'main' panicked at 'explicit panic', demo.rs:14:5
stack backtrace:
0: 0x107e34fe4 - std::backtrace_rs::backtrace::libunwind::trace::ha70d3c0580051b5e
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
1: 0x107e34fe4 - std::backtrace_rs::backtrace::trace_unsynchronized::h70c3b3ef22cddd13
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x107e34fe4 - std::sys_common::backtrace::_print_fmt::h698e42c1766250fa
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:67:5
3: 0x107e34fe4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h18cc31b07c2f1a67
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:46:22
4: 0x107e4808d - core::fmt::write::h24f8349e8e89c9af
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/fmt/mod.rs:1096:17
5: 0x107e33046 - std::io::Write::write_fmt::hc54d7d6e95b15753
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/io/mod.rs:1568:15
6: 0x107e36b79 - std::sys_common::backtrace::_print::h07ca439149358748
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:49:5
7: 0x107e36b79 - std::sys_common::backtrace::print::hb7331bf9c4b208ca
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:36:9
8: 0x107e36b79 - std::panicking::default_hook::{{closure}}::h11b550d560f5cc66
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:208:50
9: 0x107e36709 - std::panicking::default_hook::he168e99d1cf91c3c
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:225:9
10: 0x107e371fb - std::panicking::rust_panic_with_hook::hf87bfc4afef21ea6
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:591:17
11: 0x107e18d27 - std::panicking::begin_panic::{{closure}}::h631923d2be23e79e
12: 0x107e18998 - std::sys_common::backtrace::__rust_end_short_backtrace::h891b6a0b6f9c1b80
13: 0x107e4bcfb - std::panicking::begin_panic::hd2dfddb0fed650c0
14: 0x107e18aec - demo::d::h9d9ff8ddd5377da5
15: 0x107e18ac9 - demo::c::haceeec3fee4323ba
16: 0x107e18ab9 - demo::b::h4146166847508fc7
17: 0x107e18aa9 - demo::a::h60d47e17615f49c4
18: 0x107e18af9 - demo::main::h60dea0663d4b849d
19: 0x107e18bea - core::ops::function::FnOnce::call_once::hf435db03deecd456
20: 0x107e189cd - std::sys_common::backtrace::__rust_begin_short_backtrace::h936624db758e7870
21: 0x107e194d0 - std::rt::lang_start::{{closure}}::ha060b13a4d59d3f5
22: 0x107e37574 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h0e377e204feaadc3
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:259:13
23: 0x107e37574 - std::panicking::try::do_call::h9c5b8eda90bbe0b7
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:379:40
24: 0x107e37574 - std::panicking::try::he150bdff9d5b30f2
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:343:19
25: 0x107e37574 - std::panic::catch_unwind::h04e9c415c0907892
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:431:14
26: 0x107e37574 - std::rt::lang_start_internal::h86f505dc7de50d93
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/rt.rs:51:25
27: 0x107e194a5 - std::rt::lang_start::h9d080ccd85b4c518
28: 0x107e18b22 - _main
Which is the full stack trace. However is isn't very usefull as most of it is language internals. Therefor, in the normal mode, rust scans the stack for the __rust_end_short_backtrace
and __rust_begin_short_backtrace
functions.
These functions dont do anything (hence the trickery to stop them being optimized away), but are rust their for the backtracer to pick up.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.