diff --git a/src/backtrace/libunwind.rs b/src/backtrace/libunwind.rs index 0564f2ea..a8a0d1a7 100644 --- a/src/backtrace/libunwind.rs +++ b/src/backtrace/libunwind.rs @@ -79,6 +79,18 @@ impl Frame { // clause, and if this is fixed that test in theory can be run on macOS! if cfg!(target_vendor = "apple") { self.ip() + } else if cfg!(target_env = "pauthtest") { + // NOTE: As ip here is not signed (raw, non-PAC-enabled pointer) we + // must not use uw::_Unwind_FindEnclosingFunction. This is because, + // for pauthtest toolchain, libunwind will try to authenticate and + // resign it. Signing here (apart from risking creating a signing + // oracle) is not possible. According to the schema the value must + // be signed using SP as the discriminator - which is the problem. + // SP obtained here would not match the SP at the auth-resign time, + // as uw::_Unwind_FindEnclosingFunction creates a new context so + // the SP used for signing here would belong to a different frame + // that the one used for auth-resign. Hence return a raw value. + self.ip() } else { unsafe { uw::_Unwind_FindEnclosingFunction(self.ip()) } } diff --git a/tests/skip_inner_frames.rs b/tests/skip_inner_frames.rs index e62a1603..f39cdf71 100644 --- a/tests/skip_inner_frames.rs +++ b/tests/skip_inner_frames.rs @@ -10,6 +10,12 @@ const ENABLED: bool = cfg!(all( target_os = "linux", // On ARM finding the enclosing function is simply returning the ip itself. not(target_arch = "arm"), + // On `aarch64-unknown-linux-pauthtest` `_Unwind_FindEnclosingFunction` + // cannot be used safely, because instruction pointers are not in a form + // suitable for authentication/resigning, so `symbol_address()` returns the + // raw IP instead. In this case the returned address may be inside the + // function body rather than at its entry. + not(target_env = "pauthtest"), )); #[test] diff --git a/tests/smoke.rs b/tests/smoke.rs index fd5684f9..fa789f1a 100644 --- a/tests/smoke.rs +++ b/tests/smoke.rs @@ -25,6 +25,13 @@ fn get_actual_fn_pointer(fp: *mut c_void) -> *mut c_void { } #[test] +// This test relies on recovering precise symbol addresses from instruction +// pointers. On `aarch64-unknown-linux-pauthtest`, we cannot safely use +// `_Unwind_FindEnclosingFunction`, and instead fall back to using raw +// instruction pointers. As a result, symbol resolution cannot reliably +// recover a canonical function entry address, and `sym.addr()` will often be +// `None`. Therefore this test is disabled. +#[cfg_attr(target_env = "pauthtest", ignore)] // FIXME: shouldn't ignore this test on i686-msvc, unsure why it's failing #[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)] #[inline(never)] @@ -310,7 +317,10 @@ fn sp_smoke_test() { let r = refs.pop().unwrap(); eprintln!("ref = {:p}", r); if sp as usize != 0 { - assert!(r > sp); + // Stack grows down, however stack slots can be reused and + // frame pointers ommited, `r == sp` should be a valid edge + // case. + assert!(r >= sp); if let Some(child_ref) = child_ref { assert!(sp >= child_ref); }