Skip to content
Merged
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
32 changes: 31 additions & 1 deletion library/std/src/sys/personality/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,35 @@ cfg_select! {
}
}
_ => {
#[rustc_force_inline]
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).addr() as u64;
let mut addr = lpad.addr();

// `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
}
}
}

/// Default personality routine, which is used directly on most targets
/// and indirectly on Windows x86_64 and AArch64 via SEH.
unsafe extern "C" fn rust_eh_personality_impl(
Expand Down Expand Up @@ -239,7 +268,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
6 changes: 6 additions & 0 deletions library/std/tests/pipe_subprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ fn main() {

fn parent() {
let me = env::current_exe().unwrap();
// If a custom `runner` is set up for the 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 an 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 a custom `runner` is set up for the 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 an 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
9 changes: 8 additions & 1 deletion library/unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,14 @@ cfg_select! {
}
}

#[cfg(target_env = "musl")]
// `target_abi = "pauthtest"` is currently only used by the Linux/musl
// `aarch64-unknown-linux-pauthtest` target. That target only supports unwinding
// via 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
Loading