From 8dc10da81fd005b2120099b711e8af26100ab317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sat, 23 Mar 2024 18:10:14 +0000 Subject: [PATCH] Port backtrace dylib-dep test to a ui test --- src/bootstrap/src/core/build_steps/test.rs | 1 + .../auxiliary/dylib-dep-helper-aux.rs | 17 +++ .../debuginfo/auxiliary/dylib-dep-helper.rs | 19 +++ tests/ui/debuginfo/backtrace-dylib-dep.rs | 115 ++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs create mode 100644 tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs create mode 100644 tests/ui/debuginfo/backtrace-dylib-dep.rs diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 6d3163b90b10c..90eba8bc17295 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3159,6 +3159,7 @@ impl Step for TestHelpers { .opt_level(0) .warnings(false) .debug(false) + .flag("-g1") // needed to have line number tables .file(builder.src.join("tests/auxiliary/rust_test_helpers.c")) .compile("rust_test_helpers"); } diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs new file mode 100644 index 0000000000000..88bbb2532159f --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -g -Cstrip=none + +#[inline(never)] +pub fn callback(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} + +#[inline(always)] +pub fn callback_inlined(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs new file mode 100644 index 0000000000000..20d554993ac2e --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -g -Cstrip=none + +#![crate_type = "cdylib"] +#![crate_type = "rlib"] + +#![allow(improper_ctypes_definitions)] + +type Pos = (&'static str, u32); + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +#[no_mangle] +pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) { + inner(outer, pos!()); +} diff --git a/tests/ui/debuginfo/backtrace-dylib-dep.rs b/tests/ui/debuginfo/backtrace-dylib-dep.rs new file mode 100644 index 0000000000000..b2bf118e38a10 --- /dev/null +++ b/tests/ui/debuginfo/backtrace-dylib-dep.rs @@ -0,0 +1,115 @@ +// Check that backtrace info is correctly generated for dynamic libraries and is usable by a +// rust binary. +// Part of porting some backtrace tests to rustc: . +// Original test: +// +// ignore-tidy-linelength +//@ ignore-android FIXME #17520 +//@ ignore-fuchsia Backtraces not symbolized +//@ needs-unwind +//@ compile-flags: -g -Copt-level=0 -Cstrip=none +//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs +//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs +//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written). +//@ run-pass + +#![allow(improper_ctypes)] +#![allow(improper_ctypes_definitions)] + +extern crate dylib_dep_helper; +extern crate auxiliary; + +use std::backtrace::Backtrace; + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +macro_rules! check { + ($($pos:expr),*) => ({ + verify(&[$($pos,)* pos!()]); + }) +} + +fn verify(filelines: &[Pos]) { + let trace = Backtrace::capture(); + eprintln!("-----------------------------------"); + eprintln!("looking for:"); + for (file, line) in filelines.iter().rev() { + eprintln!("\t{file}:{line}"); + } + eprintln!("found:\n{trace:#?}"); + let mut iter = filelines.iter().rev(); + // FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now, + // this depends on the debug format of `Backtrace` which is of course fragile. + let backtrace = format!("{:#?}", trace); + while let Some((file, line)) = iter.next() { + // FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has + // them. + assert!(backtrace.contains(file), "expected backtrace to contain {}", file); + assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line); + } +} + +type Pos = (&'static str, u32); + +extern "C" { + #[link_name = "foo"] + fn foo(p: Pos, cb: fn(Pos, Pos)); +} + +fn main() { + std::env::set_var("RUST_BACKTRACE", "1"); + std::env::set_var("WASMTIME_BACKTRACE_DETAILS", "1"); + + unsafe { + foo(pos!(), |a, b| { + check!(a, b) + }) + } + + outer(pos!()); +} + +#[inline(never)] +fn outer(main_pos: Pos) { + inner(main_pos, pos!()); + inner_inlined(main_pos, pos!()); +} + +#[inline(never)] +fn inner(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); +} + +#[inline(always)] +fn inner_inlined(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + + #[inline(always)] + fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { + check!(main_pos, outer_pos, inner_pos); + } + inner_further_inlined(main_pos, outer_pos, pos!()); + + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + + // this tests a distinction between two independent calls to the inlined function. + // (un)fortunately, LLVM somehow merges two consecutive such calls into one node. + inner_further_inlined(main_pos, outer_pos, pos!()); +}