Skip to content

Commit c0ae25f

Browse files
committed
Add support for aarch64-unknown-linux-pauthtest
This PR adds support for `aarch64-unknown-linux-pauthtest`, a target that enables Pointer Authentication Code (PAC) support in Rust on AArch64 ELF based Linux systems using a pauthtest ABI (provided by LLVM) and pauthtest-enabled sysroot with custom musl, serving as a reference libc implementation.
1 parent 06b2cc5 commit c0ae25f

3 files changed

Lines changed: 26 additions & 1 deletion

File tree

src/backtrace/libunwind.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ impl Frame {
7979
// clause, and if this is fixed that test in theory can be run on macOS!
8080
if cfg!(target_vendor = "apple") {
8181
self.ip()
82+
} else if cfg!(target_abi = "pauthtest") {
83+
// NOTE: `_Unwind_FindEnclosingFunction` creates a fresh unwind
84+
// cursor and, on the pointer-authentication-enabled AArch64
85+
// reference ABI, authenticates/re-signs the supplied IP using that
86+
// cursor's SP. The original frame's SP is not available through
87+
// this API, so the current libunwind implementation cannot be used
88+
// here: it would attempt to authenticate the IP using the wrong SP.
89+
// Return the raw instruction pointer instead.
90+
self.ip()
8291
} else {
8392
unsafe { uw::_Unwind_FindEnclosingFunction(self.ip()) }
8493
}

tests/skip_inner_frames.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ const ENABLED: bool = cfg!(all(
1010
target_os = "linux",
1111
// On ARM finding the enclosing function is simply returning the ip itself.
1212
not(target_arch = "arm"),
13+
// On `aarch64-unknown-linux-pauthtest` `_Unwind_FindEnclosingFunction`
14+
// cannot be used safely, because instruction pointers are not in a form
15+
// suitable for authentication/resigning, so `symbol_address()` returns the
16+
// raw IP instead. In this case the returned address may be inside the
17+
// function body rather than at its entry.
18+
not(target_env = "pauthtest"),
1319
));
1420

1521
#[test]

tests/smoke.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ fn get_actual_fn_pointer(fp: *mut c_void) -> *mut c_void {
2525
}
2626

2727
#[test]
28+
// This test relies on recovering precise symbol addresses from instruction
29+
// pointers. On `aarch64-unknown-linux-pauthtest`, we cannot safely use
30+
// `_Unwind_FindEnclosingFunction`, and instead fall back to using raw
31+
// instruction pointers. As a result, symbol resolution cannot reliably
32+
// recover a canonical function entry address, and `sym.addr()` will often be
33+
// `None`. Therefore this test is disabled.
34+
#[cfg_attr(target_env = "pauthtest", ignore)]
2835
// FIXME: shouldn't ignore this test on i686-msvc, unsure why it's failing
2936
#[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
3037
#[inline(never)]
@@ -310,7 +317,10 @@ fn sp_smoke_test() {
310317
let r = refs.pop().unwrap();
311318
eprintln!("ref = {:p}", r);
312319
if sp as usize != 0 {
313-
assert!(r > sp);
320+
// Stack grows down, however stack slots can be reused and
321+
// frame pointers ommited, `r == sp` should be a valid edge
322+
// case.
323+
assert!(r >= sp);
314324
if let Some(child_ref) = child_ref {
315325
assert!(sp >= child_ref);
316326
}

0 commit comments

Comments
 (0)