Skip to content

Fix short backtraces from stripped executables#151740

Open
eggyal wants to merge 3 commits intorust-lang:mainfrom
eggyal:short-backtrace-markers-by-addr
Open

Fix short backtraces from stripped executables#151740
eggyal wants to merge 3 commits intorust-lang:mainfrom
eggyal:short-backtrace-markers-by-addr

Conversation

@eggyal
Copy link
Contributor

@eggyal eggyal commented Jan 27, 2026

Locate the beginning and ending frames for short backtraces by address in addition to symbol name, so that they work even when symbols have been stripped from the executable.

We need to retain matching by symbol name for the time being, because rustc (and some associated ui tests) rely upon it to have ICE backtraces abbreviated. They can be updated once this commit lands in beta/stage0. (It is for this reason that the begin/end methods are being publicly exported from std::backtrace, albeit hidden from documentation and marked unstable).

Fixes #147846
r? libs

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jan 27, 2026
@rust-log-analyzer

This comment has been minimized.

@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from 53c0426 to f857f07 Compare January 27, 2026 15:28
@rust-log-analyzer

This comment has been minimized.

@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from f857f07 to 6605497 Compare January 27, 2026 15:51
@rust-log-analyzer

This comment has been minimized.

@rustbot
Copy link
Collaborator

rustbot commented Jan 27, 2026

The Miri subtree was changed

cc @rust-lang/miri

@rust-log-analyzer

This comment has been minimized.

@jhpratt
Copy link
Member

jhpratt commented Jan 29, 2026

@rustbot reroll

@rustbot rustbot assigned joboet and unassigned jhpratt Jan 29, 2026
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 30, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 30, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from c650ea2 to 6c5d59a Compare January 30, 2026 14:26
@eggyal

This comment was marked as outdated.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 30, 2026
@rust-log-analyzer

This comment has been minimized.

@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from 6c5d59a to 827da1d Compare January 30, 2026 18:08
@rust-log-analyzer

This comment has been minimized.

@eggyal

This comment was marked as outdated.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 30, 2026
@rust-log-analyzer

This comment has been minimized.

@eggyal

This comment was marked as resolved.

@saethlin
Copy link
Member

You added a generic parameter to the backtrace markers which removes their address stability:

fn get_global_alloc_salt(
ecx: &InterpCx<'tcx, Self>,
instance: Option<ty::Instance<'tcx>>,
) -> usize {
let unique = if let Some(instance) = instance {
// Functions cannot be identified by pointers, as asm-equal functions can get
// deduplicated by the linker (we set the "unnamed_addr" attribute for LLVM) and
// functions can be duplicated across crates. We thus generate a new `AllocId` for every
// mention of a function. This means that `main as fn() == main as fn()` is false, while
// `let x = main as fn(); x == x` is true. However, as a quality-of-life feature it can
// be useful to identify certain functions uniquely, e.g. for backtraces. So we identify
// whether codegen will actually emit duplicate functions. It does that when they have
// non-lifetime generics, or when they can be inlined. All other functions are given a
// unique address. This is not a stable guarantee! The `inline` attribute is a hint and
// cannot be relied upon for anything. But if we don't do this, the
// `__rust_begin_short_backtrace`/`__rust_end_short_backtrace` logic breaks and panic
// backtraces look terrible.
let is_generic = instance
.args
.into_iter()
.any(|arg| !matches!(arg.kind(), ty::GenericArgKind::Lifetime(_)));
let can_be_inlined = matches!(
ecx.tcx.sess.opts.unstable_opts.cross_crate_inline_threshold,
InliningThreshold::Always
) || !matches!(
ecx.tcx.codegen_instance_attrs(instance.def).inline,
InlineAttr::Never
);
!is_generic && !can_be_inlined
} else {
// Non-functions are never unique.
false
};
// Always use the same salt if the allocation is unique.
if unique {
CTFE_ALLOC_SALT
} else {
ecx.machine.rng.borrow_mut().random_range(0..ADDRS_PER_ANON_GLOBAL)
}
}

Miri explicitly tries to destabilize function pointer addresses in all cases where it would be plausible for an optimizer to do so.

@eggyal

This comment was marked as resolved.

@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from fdc2a6e to b981453 Compare February 15, 2026 01:23
@rust-log-analyzer

This comment has been minimized.

@eggyal

This comment was marked as resolved.

@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from b981453 to dda0845 Compare February 15, 2026 10:56
@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch 2 times, most recently from 5cdf6b0 to faea1f7 Compare February 15, 2026 22:15
Locate the beginning and ending frames for short backtraces by address
in addition to symbol name, so that they work even when symbols have
been stripped from the executable.

We need to retain matching by symbol name for the time being, because
rustc (and some associated ui tests) rely upon it to have ICE backtraces
abbreviated.  They can be updated once this commit lands in beta/stage0.
The new short backtrace markers place three frames in backtraces: the
marker initially invoked by downstream code (should be inlined into such
downstream code); the type-erased marker at a known-address (detected by
the backtrace printing code); and the type-restoring callback shim (into
which the actual callback should also be inlined).  This differs from
the status-quo ante, where the backtrace markers placed only a single
frame into backtraces.

Whilst these additional frames should have negligible impact on runtime
performance (not only are they called, by the language runtime, at most
twice: once during start before invoking main and once upon panic, if
any; but furthermore, due to the aforementioned inlining, optimized
assembly should be very similar - the additional frames will mostly only
arise from additional debug info), the expected outputs from some miri
tests require updating to reflect these backtrace changes.
This status-quo ante of this naked function test defined a label with
the symbolic name `.L7`.  However, changes to the stack could cause a
collision with that same symbolic name being defined by compiler-
generated code; therefore we use a local label instead to guarantee
collision avoidance.
@eggyal eggyal force-pushed the short-backtrace-markers-by-addr branch from faea1f7 to c8164c0 Compare February 15, 2026 22:16
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stripped executables don't print backtrace with RUST_BACKTRACE=1

7 participants