Open
Description
currently, backtraces for rust cdylibs called from a C main function look like this:
thread '<unnamed>' panicked at lib.rs:5:34:
oops
stack backtrace:
0: std::panicking::begin_panic
1: lib::foo::{{closure}}
2: std::panicking::try::do_call
3: __rust_try
4: std::panic::catch_unwind
5: foo
6: main
7: __libc_start_call_main
at ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
8: __libc_start_main_impl
at ./csu/../csu/libc-start.c:392:3
9: _start
(the catch_unwind
-> do_call
stack should be included, i had a manual catch_unwind in my program.)
this does ok for frames after main, but it shows three irrelevant frames before main. that happens because rustc doesn't control the final link, so it can't generate a __rust_start_short_backtrace
frame. it would be nice if we could omit those.
to avoid making this dependent on the libc in use, i think we should:
- determine whether
main
was generated by rustc. we have a reliable signal for this at runtime, which is "isstd::rt::lang_start
present anywhere in the backtrace". - if not, treat
main
the same as__rust_start_short_backtrace
, except we also print themain
frame in addition to toggling the state machine.
code that replicates this backtrace
; cat lib.rs main.c Makefile
File: lib.rs
use std::ffi::c_int;
use std::panic::catch_unwind;
#[no_mangle]
pub extern "C" fn foo() -> c_int {
let _panic = catch_unwind(|| panic!("oops")).unwrap_err();
1
}
────────────────────────────────────────────────────────
File: main.c
#include <stdio.h>
int foo();
int main() {
printf("%d\n", foo());
}
────────────────────────────────────────────────────────
File: Makefile
.PHONY: run
run: main
LD_LIBRARY_PATH=. RUST_BACKTRACE=1 ./main
main: main.o librust.so
gcc main.o -L. -lrust -o main
librust.so: lib.rs
rustc --crate-type cdylib lib.rs -o librust.so