diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index d8397ab51de3c..6a48366e974ca 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1395,16 +1395,19 @@ impl Build { // its caching system since we're executing quite a lot of tests and // ideally shouldn't pollute the cache too much. if let Some(path) = finder.maybe_have("wasmtime") { - if let Ok(mut path) = path.into_os_string().into_string() { - path.push_str(" run -C cache=n --dir ."); + if let Ok(mut cmd) = path.into_os_string().into_string() { + cmd.push_str(" run -C cache=n --dir ."); // Make sure that tests have access to RUSTC_BOOTSTRAP. This (for example) is // required for libtest to work on beta/stable channels. // // NB: with Wasmtime 20 this can change to `-S inherit-env` to // inherit the entire environment rather than just this single // environment variable. - path.push_str(" --env RUSTC_BOOTSTRAP"); - return Some(path); + cmd.push_str(" --env RUSTC_BOOTSTRAP"); + // Make sure debug-info is enabled so we can have backtraces with file names and + // line numbers. + cmd.push_str(" -D debug-info=y"); + return Some(cmd); } } diff --git a/tests/auxiliary/rust_test_helpers.c b/tests/auxiliary/rust_test_helpers.c index 977ea487a9804..18bf328945bb5 100644 --- a/tests/auxiliary/rust_test_helpers.c +++ b/tests/auxiliary/rust_test_helpers.c @@ -427,3 +427,18 @@ uint16_t issue_97463_leak_uninit_data(uint32_t a, uint32_t b, uint32_t c) { return data->b; /* leak data */ } + +// Used for testing backtrace line_tables_only +typedef void (*line_tables_only_callback) (void *data); + +void line_tables_only_baz(line_tables_only_callback cb, void *data) { + cb(data); +} + +void line_tables_only_bar(line_tables_only_callback cb, void *data) { + line_tables_only_baz(cb, data); +} + +void line_tables_only_foo(line_tables_only_callback cb, void *data) { + line_tables_only_bar(cb, data); +} diff --git a/tests/ui/debuginfo/backtrace-line-tables-only.rs b/tests/ui/debuginfo/backtrace-line-tables-only.rs new file mode 100644 index 0000000000000..143d39081bb87 --- /dev/null +++ b/tests/ui/debuginfo/backtrace-line-tables-only.rs @@ -0,0 +1,61 @@ +// Test that when debug info only includes line tables that backtrace is still generated +// successfully. This previously failed when compiling with `clang -g1`. +// Part of porting some backtrace tests to rustc. +// ignore-tidy-linelength +//@ ignore-windows original test is ignore-windows +//@ ignore-android FIXME #17520 +//@ ignore-openbsd no support for libbacktrace without filename +//@ ignore-fuchsia Backtraces not symbolized +//@ needs-unwind +//@ run-pass +//@ compile-flags: -Cdebuginfo=line-tables-only -Cstrip=none +#![feature(backtrace_frames)] + +use std::backtrace::{self, Backtrace}; +use std::ffi::c_void; +use std::ptr::addr_of_mut; + +pub type Callback = extern "C" fn(data: *mut c_void); + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn line_tables_only_foo(cb: Callback, data: *mut c_void); +} + +extern "C" fn store_backtrace(data: *mut c_void) { + let bt = backtrace::Backtrace::capture(); + unsafe { *data.cast::>() = Some(bt) }; +} + +fn assert_contains( + backtrace: &Backtrace, + expected_name: &str, + expected_file: &str, + expected_line: u32, +) { + // FIXME(jieyouxu): fix this ugly fragile test when `BacktraceFrame` has accessors like... + // `symbols()`. + let backtrace = format!("{:#?}", backtrace); + eprintln!("{}", backtrace); + assert!(backtrace.contains(expected_name), "backtrace does not contain expected name {}", expected_name); + assert!(backtrace.contains(expected_file), "backtrace does not contain expected file {}", expected_file); + assert!(backtrace.contains(&expected_line.to_string()), "backtrace does not contain expected line {}", expected_line); +} + +/// Verifies that when debug info includes only lines tables the generated +/// backtrace is still generated successfully. The test exercises behaviour +/// that failed previously when compiling with clang -g1. +/// +/// The test case uses C rather than rust, since at that time when it was +/// written the debug info generated at level 1 in rustc was essentially +/// the same as at level 2. +fn main() { + std::env::set_var("RUST_BACKTRACE", "1"); + std::env::set_var("WASMTIME_BACKTRACE_DETAILS", "1"); + let mut backtrace: Option = None; + unsafe { line_tables_only_foo(store_backtrace, addr_of_mut!(backtrace).cast::()) }; + let backtrace = backtrace.expect("backtrace"); + assert_contains(&backtrace, "line_tables_only_foo", "rust_test_helpers.c", 435); + assert_contains(&backtrace, "line_tables_only_bar", "rust_test_helpers.c", 439); + assert_contains(&backtrace, "line_tables_only_baz", "rust_test_helpers.c", 443); +}