Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion library/std/src/sys/personality/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,34 @@ const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
#[cfg(any(target_arch = "loongarch32", target_arch = "loongarch64"))]
const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1

unsafe fn sign_lpad(context: *mut uw::_Unwind_Context, lpad: *const u8) -> *const u8 {
cfg_select! {
all(target_abi = "pauthtest", target_arch = "aarch64") => {
// DWARF register number for SP on AArch64.
const SP_REG: i32 = 31;

unsafe {
let sp = uw::_Unwind_GetGR(context, SP_REG) as u64;
let mut addr = lpad as usize;

// `pacib` corresponds to `ptrauth_key_process_dependent_code` in <ptrauth.h>.
core::arch::asm!(
"pacib {addr}, {sp}",
addr = inout(reg) addr,
sp = in(reg) sp,
options(nostack, preserves_flags)
);

lpad.with_addr(addr)
}
}
_ => {
let _ = context;
lpad
}
}
}

// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
Expand Down Expand Up @@ -239,7 +267,8 @@ cfg_select! {
exception_object.cast(),
);
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null());
uw::_Unwind_SetIP(context, lpad);
let maybe_signed_lpad = sign_lpad(context, lpad);
uw::_Unwind_SetIP(context, maybe_signed_lpad);
uw::_URC_INSTALL_CONTEXT
}
EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
Expand Down
5 changes: 5 additions & 0 deletions library/std/tests/pipe_subprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ fn main() {

fn parent() {
let me = env::current_exe().unwrap();
// If `runner` is set up for current target, we'll be executing `./runner ./test`, not
// just `./test`. For such a case, use the same arguments for child to avoid executing
// `runner` without actual executable.
let args = env::args();

let (rx, tx) = pipe().unwrap();
assert!(
process::Command::new(me)
.args(args)
.env("I_AM_THE_CHILD", "1")
.stdout(tx)
.status()
Expand Down
12 changes: 10 additions & 2 deletions library/std/tests/process_spawning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ fn issue_15149() {
env::join_paths(paths).unwrap()
};

let child_output =
process::Command::new("mytest").env("PATH", &path).arg("child").output().unwrap();
// If `runner` is set up for current target, we'll be executing `./runner ./test`, not
// just `./test`. For such a case, use the same arguments for child to avoid executing
// `runner` without actual executable.
let args = env::args();
let child_output = process::Command::new("mytest")
.args(args)
.env("PATH", &path)
.arg("child")
.output()
.unwrap();

assert!(
child_output.status.success(),
Expand Down
7 changes: 6 additions & 1 deletion library/unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ cfg_select! {
}
}

#[cfg(target_env = "musl")]
// For pauthtest the only supported unwinding mechanism is provided by libunwind.
#[cfg(target_abi = "pauthtest")]
#[link(name = "unwind")]
unsafe extern "C" {}

#[cfg(all(target_env = "musl", not(target_abi = "pauthtest")))]
cfg_select! {
all(feature = "llvm-libunwind", feature = "system-llvm-libunwind") => {
compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time");
Expand Down