Skip to content

Commit 8a79ed2

Browse files
committed
[PtrAuth] Add support for arm64e intrinsics
This patch provides barebones support for ARM64e instructions to be emitted like braaz and paciza.
1 parent 76c5ed2 commit 8a79ed2

File tree

6 files changed

+78
-2
lines changed

6 files changed

+78
-2
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
431431
bundles.push(kcfi_bundle);
432432
}
433433

434+
let pauth = self.ptrauth_operand_bundle(llfn);
435+
if let Some(p) = pauth.as_ref().map(|b| b.as_ref()) {
436+
bundles.push(p);
437+
}
438+
434439
let invoke = unsafe {
435440
llvm::LLVMBuildInvokeWithOperandBundles(
436441
self.llbuilder,
@@ -1417,6 +1422,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14171422
bundles.push(kcfi_bundle);
14181423
}
14191424

1425+
let pauth = self.ptrauth_operand_bundle(llfn);
1426+
if let Some(p) = pauth.as_ref().map(|b| b.as_ref()) {
1427+
bundles.push(p);
1428+
}
1429+
14201430
let call = unsafe {
14211431
llvm::LLVMBuildCallWithOperandBundles(
14221432
self.llbuilder,
@@ -1785,6 +1795,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17851795
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) {
17861796
bundles.push(kcfi_bundle);
17871797
}
1798+
1799+
let pauth = self.ptrauth_operand_bundle(llfn);
1800+
if let Some(p) = pauth.as_ref().map(|b| b.as_ref()) {
1801+
bundles.push(p);
1802+
}
17881803

17891804
let callbr = unsafe {
17901805
llvm::LLVMBuildCallBr(
@@ -1905,6 +1920,18 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19051920
kcfi_bundle
19061921
}
19071922

1923+
fn ptrauth_operand_bundle(&mut self, llfn: &'ll Value)
1924+
-> Option<llvm::OperandBundleBox<'ll>>
1925+
{
1926+
let on_arm64e = self.cx.sess().target.llvm_target.starts_with("arm64e-apple-");
1927+
if !on_arm64e { return None; }
1928+
1929+
let is_non_gv_fn_ptr = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
1930+
if !is_non_gv_fn_ptr { return None; }
1931+
1932+
Some(llvm::OperandBundleBox::new("ptrauth", &[self.const_i32(0), self.const_u64(0)]))
1933+
}
1934+
19081935
/// Emits a call to `llvm.instrprof.increment`. Used by coverage instrumentation.
19091936
#[instrument(level = "debug", skip(self))]
19101937
pub(crate) fn instrprof_increment(

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ use crate::llvm::{self, BasicBlock, ConstantInt, FALSE, Metadata, TRUE, ToLlvmBo
2424
use crate::type_::Type;
2525
use crate::value::Value;
2626

27+
pub(crate) fn sign_fn_ptr_if_arm64e<'ll>(
28+
cx: &CodegenCx<'ll, '_>,
29+
llfn: &'ll llvm::Value,
30+
) -> &'ll llvm::Value {
31+
if !cx.sess().target.llvm_target.starts_with("arm64e-apple-") {
32+
return llfn;
33+
}
34+
35+
unsafe {
36+
let authed = llvm::LLVMRustConstPtrAuth(llfn as *const _ as *mut _, /*IA*/ 0, /*disc*/ 0);
37+
&*authed
38+
}
39+
}
40+
2741
/*
2842
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
2943
*

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,14 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
767767
}
768768

769769
fn get_fn_addr(&self, instance: Instance<'tcx>) -> &'ll Value {
770-
get_fn(self, instance)
770+
let llfn = get_fn(self, instance);
771+
772+
let name_bytes = llvm::get_value_name(llfn);
773+
if name_bytes.starts_with(b"llvm.") {
774+
return llfn;
775+
}
776+
777+
common::sign_fn_ptr_if_arm64e(self, llfn)
771778
}
772779

773780
fn eh_personality(&self) -> &'ll Value {

compiler/rustc_codegen_llvm/src/llvm/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,11 @@ pub(crate) fn append_module_inline_asm<'ll>(llmod: &'ll Module, asm: &[u8]) {
437437
LLVMAppendModuleInlineAsm(llmod, asm.as_ptr(), asm.len());
438438
}
439439
}
440+
441+
unsafe extern "C" {
442+
pub(crate) fn LLVMRustConstPtrAuth(
443+
Fn: *mut Value,
444+
Key: c_uint,
445+
Disc: u64,
446+
) -> *mut Value;
447+
}

compiler/rustc_codegen_ssa/src/back/metadata.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
216216
file.set_sub_architecture(sub_architecture);
217217
if sess.target.is_like_darwin {
218218
if macho_is_arm64e(&sess.target) {
219-
file.set_macho_cpu_subtype(object::macho::CPU_SUBTYPE_ARM64E);
219+
const ARM64E_SUBTYPE: u32 = object::macho::CPU_SUBTYPE_ARM64E |
220+
object::macho::CPU_SUBTYPE_PTRAUTH_ABI;
221+
file.set_macho_cpu_subtype(ARM64E_SUBTYPE);
220222
}
221223

222224
file.set_macho_build_version(macho_object_build_version_for_target(sess))

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,3 +1945,21 @@ extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) {
19451945
MD.NoHWAddress = true;
19461946
GV.setSanitizerMetadata(MD);
19471947
}
1948+
1949+
extern "C" LLVMValueRef LLVMRustConstPtrAuth(LLVMValueRef Ptr,
1950+
unsigned Key,
1951+
uint64_t Disc) {
1952+
auto *V = unwrap<Value>(Ptr);
1953+
auto *C = dyn_cast<Constant>(V);
1954+
if (!C) return Ptr;
1955+
auto *PTy = dyn_cast<PointerType>(C->getType());
1956+
if (!PTy) return Ptr;
1957+
if (isa<UndefValue>(C) || isa<ConstantPointerNull>(C)) return Ptr;
1958+
1959+
LLVMContext &Ctx = C->getContext();
1960+
auto *KeyC = ConstantInt::get(Type::getInt32Ty(Ctx), Key);
1961+
auto *DiscC = ConstantInt::get(Type::getInt64Ty(Ctx), Disc);
1962+
auto *NullAD = ConstantPointerNull::get(PTy); // <— important
1963+
1964+
return wrap(ConstantPtrAuth::get(C, KeyC, DiscC, NullAD));
1965+
}

0 commit comments

Comments
 (0)