Skip to content

Commit

Permalink
[backtraces]: look for the begin symbol only after seeing end
Browse files Browse the repository at this point in the history
On `x86_64-pc-windows-msvc`, we often get backtraces which look like
this:

```
10:     0x7ff77e0e9be5 - std::panicking::rust_panic_with_hook
11:     0x7ff77e0e11b4 - std::sys_common::backtrace::__rust_begin_short_backtrace::h5769736bdb11136c
12:     0x7ff77e0e116f - std::sys_common::backtrace::__rust_end_short_backtrace::h61c7ecb1b55338ae
13:     0x7ff77e0f89dd - std::panicking::begin_panic::h8e60ef9f82a41805
14:     0x7ff77e0e108c - d
15:     0x7ff77e0e1069 - c
16:     0x7ff77e0e1059 - b
17:     0x7ff77e0e1049 - a
18:     0x7ff77e0e1039 - core::ptr::drop_in_place<std::rt::lang_start<()>::{{closure}}>::h1bfcd14d5e15ba81
19:     0x7ff77e0e1186 - std::sys_common::backtrace::__rust_begin_short_backtrace::h5769736bdb11136c
20:     0x7ff77e0e100c - std::rt::lang_start::{{closure}}::ha054184bbf9921e3
```

Notice that `__rust_begin_short_backtrace` appears on frame 11 before
`__rust_end_short_backtrace` on frame 12. This is because in typical
release binaries without debug symbols, dbghelp.dll, which we use to walk
and symbolize the stack, does not know where CGU internal functions
start or end and so the closure invoked by `__rust_end_short_backtrace`
is incorrectly described as `__rust_begin_short_backtrace` because it
happens to be near that symbol.

While that can obviously change, this has been happening quite
consistently since rust-lang#75048. Since this is a very small change to the std
and the change makes sense by itself, I think this is worth doing.

This doesn't completely resolve the situation for release binaries on
Windows, since without debug symbols, the stack printed can still show
incorrect symbol names (this is why the test uses `#[no_mangle]`) but it
does slightly improve the situation in that you see the same backtrace
you would see with `RUST_BACKTRACE=full` or in a debugger (without the
uninteresting bits at the top and bottom).
  • Loading branch information
wesleywiser committed Jul 29, 2021
1 parent 3fda708 commit 286cdc8
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 2 deletions.
2 changes: 1 addition & 1 deletion library/std/src/sys_common/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
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") {
if start && sym.contains("__rust_begin_short_backtrace") {
stop = true;
return;
}
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/panics/panic-short-backtrace-windows-x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
// check-run-results
// exec-env:RUST_BACKTRACE=1

// We need to normalize out frame 5 because without debug info, dbghelp.dll doesn't know where CGU
// internal functions like `main` start or end and so it will return whatever symbol happens
// to be located near the address.
// normalize-stderr-test: "5: .*" -> "5: some Rust fn"

// Backtraces are pretty broken in general on i686-pc-windows-msvc (#62897).
// only-x86_64-pc-windows-msvc

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
thread 'main' panicked at 'd was called', $DIR/panic-short-backtrace-windows-x86_64.rs:43:5
thread 'main' panicked at 'd was called', $DIR/panic-short-backtrace-windows-x86_64.rs:48:5
stack backtrace:
0: std::panicking::begin_panic
1: d
2: c
3: b
4: a
5: some Rust fn
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

0 comments on commit 286cdc8

Please sign in to comment.