Skip to content
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1843,6 +1843,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
self.fptoint_sat(true, val, dest_ty)
}

fn ptrauth_resign(
&mut self,
_value: Self::Value,
_old_key: u32,
_old_discriminator: u64,
_new_key: u32,
_new_discriminator: u64,
) -> Self::Value {
bug!("Resigning of pointers not implemented");
}
}

impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_gcc/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_abi::Primitive::Pointer;
use rustc_abi::{self as abi, HasDataLayout};
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, PacMetadata,
StaticCodegenMethods,
BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
};
use rustc_middle::mir::Mutability;
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar};
use rustc_middle::ty::layout::LayoutOf;
use rustc_session::PointerAuthSchema;

use crate::consts::const_alloc_to_gcc;
use crate::context::{CodegenCx, new_array_type};
Expand Down Expand Up @@ -247,7 +247,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
cv: Scalar,
layout: abi::Scalar,
ty: Type<'gcc>,
_pac: Option<PacMetadata>,
_schema: Option<PointerAuthSchema>,
) -> RValue<'gcc> {
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
match cv {
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_codegen_gcc/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RV
use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::traits::{
BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods, PacMetadata,
};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods};
use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::mir::interpret::Allocation;
Expand All @@ -18,9 +16,9 @@ use rustc_middle::ty::layout::{
LayoutOfHelpers,
};
use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
use rustc_session::Session;
#[cfg(feature = "master")]
use rustc_session::config::DebugInfo;
use rustc_session::{PointerAuthSchema, Session};
use rustc_span::{DUMMY_SP, Span, Symbol, respan};
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi};

Expand Down Expand Up @@ -400,7 +398,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
get_fn(self, instance)
}

fn get_fn_addr(&self, instance: Instance<'tcx>, _pac: Option<PacMetadata>) -> RValue<'gcc> {
fn get_fn_addr(
&self,
instance: Instance<'tcx>,
_pointer_auth_schema: Option<PointerAuthSchema>,
) -> RValue<'gcc> {
let func_name = self.tcx.symbol_name(instance).name;

let func = if let Some(variable) = self.get_declared_value(func_name) {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_gcc/src/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
fixed_count: 3,
conv: CanonAbi::C,
can_unwind: false,
ptrauth_type_discriminator: 0,
};
fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false });

Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,9 @@ use rustc_session::config::{
};
use rustc_span::sym;
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::spec::{
Arch, FramePointer, LlvmAbi, SanitizerSet, StackProbeType, StackProtector,
};
use rustc_target::spec::{Arch, FramePointer, SanitizerSet, StackProbeType, StackProtector};
use smallvec::SmallVec;

use crate::common::pauth_fn_attrs;
use crate::context::SimpleCx;
use crate::errors::{PackedStackBackchainNeedsSoftfloat, SanitizerMemtagRequiresMte};
use crate::llvm::AttributePlace::Function;
Expand Down Expand Up @@ -668,8 +665,9 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
}
}

if sess.target.llvm_abiname == LlvmAbi::Pauthtest {
for &ptrauth_attr in pauth_fn_attrs() {
if sess.pointer_authentication() {
let cfg = sess.pointer_auth_config.as_ref().unwrap();
for ptrauth_attr in cfg.fn_attrs() {
to_add.push(llvm::CreateAttrString(cx.llcx, ptrauth_attr));
}
}
Expand Down
42 changes: 18 additions & 24 deletions compiler/rustc_codegen_llvm/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ use rustc_middle::mono::Visibility;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{DebugInfo, Offload};
use rustc_span::Symbol;
use rustc_target::spec::{LlvmAbi, SanitizerSet};
use rustc_target::spec::SanitizerSet;

use super::ModuleLlvm;
use crate::attributes;
use crate::builder::Builder;
use crate::builder::gpu_offload::OffloadGlobals;
use crate::common::pauth_fn_attrs;
use crate::context::CodegenCx;
use crate::llvm::{self, Value};

Expand Down Expand Up @@ -131,8 +130,9 @@ pub(crate) fn compile_codegen_unit(
// FIXME(jchlanda) If it ever becomes necessary to ensure that all compiler
// generated functions receive the ptrauth-* attributes, `declare_fn` or
// `declare_raw_fn` could be used to provide those.
if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest {
for &ptrauth_attr in pauth_fn_attrs() {
if cx.sess().pointer_authentication() {
let cfg = cx.sess().pointer_auth_config.as_ref().unwrap();
for ptrauth_attr in cfg.fn_attrs() {
attrs.push(llvm::CreateAttrString(cx.llcx, ptrauth_attr));
}
}
Expand All @@ -152,28 +152,22 @@ pub(crate) fn compile_codegen_unit(
cx.add_objc_module_flags();
}

if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest {
// FIXME(jchlanda): In LLVM/Clang, there are also `aarch64-elf-pauthabi-platform`
// and `aarch64-elf-pauthabi-version` module flags. These are emitted into the
// PAuth core info section of the resulting ELF, which the linker uses to enforce
// binary compatibility.
//
// We intentionally do not emit these flags now, since only a subset of features
// included in clang's pauthtest is currently supported. By default, the absence of
// this info is treated as compatible with any binary.
//
// Please note, that this would cause compatibility issues, specifically runtime
// crashes due to authentication failures (while compiling and linking
// successfully) when linking against binaries that support larger set of features
// (for example, signing of C++ member function pointers, virtual function
// pointers, virtual table pointers).
//
// Link to PAuth core info documentation:
// <https://github.com/ARM-software/abi-aa/blob/2025Q4/pauthabielf64/pauthabielf64.rst#core-information>
if cx.sess().opts.unstable_opts.ptrauth_elf_got {
if cx.sess().pointer_authentication() {
let cfg = cx.sess().pointer_auth_config.as_ref().unwrap();

let aarch64_elf_pauthabi_version =
cfg.calculate_pauth_abi_version(&cx.sess().target);
if aarch64_elf_pauthabi_version != 0 {
cx.add_ptrauth_pauthabi_version_and_platform_flags(
aarch64_elf_pauthabi_version,
);
}
if cfg.elf_got {
cx.add_ptrauth_elf_got_flag();
}
cx.add_ptrauth_sign_personality_flag();
if cx.sess().pointer_authentication_functions().is_some() {
cx.add_ptrauth_sign_personality_flag();
}
}

// Finalize code coverage by injecting the coverage map. Note, the coverage map will
Expand Down
38 changes: 34 additions & 4 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use rustc_sanitizers::{cfi, kcfi};
use rustc_session::config::OptLevel;
use rustc_span::Span;
use rustc_target::callconv::{FnAbi, PassMode};
use rustc_target::spec::{Arch, HasTargetSpec, LlvmAbi, SanitizerSet, Target};
use rustc_target::spec::{Arch, HasTargetSpec, SanitizerSet, Target};
use smallvec::SmallVec;
use tracing::{debug, instrument};

Expand Down Expand Up @@ -1543,6 +1543,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx);
attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]);
}

fn ptrauth_resign(
&mut self,
value: &'ll Value,
old_key: u32,
old_discriminator: u64,
new_key: u32,
new_discriminator: u64,
) -> &'ll Value {
let ptr_as_int = self.ptrtoint(value, self.type_i64());
let resigned_int = self.call_intrinsic(
"llvm.ptrauth.resign",
&[],
&[
ptr_as_int,
self.const_i32(old_key as i32),
self.const_i64(old_discriminator as i64),
self.const_i32(new_key as i32),
self.const_i64(new_discriminator as i64),
],
);

self.inttoptr(resigned_int, self.val_ty(value))
}
}

impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
Expand Down Expand Up @@ -2040,7 +2064,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
llfn: &'ll Value,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
) -> Option<llvm::OperandBundleBox<'ll>> {
if self.sess().target.llvm_abiname != LlvmAbi::Pauthtest {
if self.sess().pointer_authentication_functions().is_none() {
return None;
}
// Pointer authentication support is currently limited to extern "C" calls; filter out other
Expand All @@ -2060,8 +2084,14 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
// bundles.
// Once this is resolved, we should analyze each call and skip direct calls. See the
// discussion in the rust-lang issue: <https://github.com/rust-lang/rust/issues/152532>
let key: u32 = 0;
let discriminator: u64 = 0;

let key: u32 = self.sess().pointer_authentication_fn_ptr_key().unwrap() as u32;
let discriminator = if self.sess().pointer_authentication_fn_ptr_type_discrimination() {
fn_abi?.ptrauth_type_discriminator
} else {
0
};

Some(llvm::OperandBundleBox::new(
"ptrauth",
&[self.const_u32(key), self.const_u64(discriminator)],
Expand Down
38 changes: 12 additions & 26 deletions compiler/rustc_codegen_llvm/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_middle::bug;
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar};
use rustc_middle::ty::{Instance, TyCtxt};
use rustc_session::cstore::DllImport;
use rustc_target::spec::LlvmAbi;
use rustc_session::{PointerAuthAddressDiscriminator, PointerAuthSchema};
use tracing::debug;

use crate::consts::{IsInitOrFini, IsStatic, const_alloc_to_llvm};
Expand All @@ -26,29 +26,13 @@ use crate::llvm::{
self, BasicBlock, ConstantInt, FALSE, TRUE, ToLlvmBool, Type, Value, const_ptr_auth,
};

#[inline]
pub(crate) fn pauth_fn_attrs() -> &'static [&'static str] {
// FIXME(jchlanda) This is not an exhaustive list of all `ptrauth`-related attributes, but only
// those currently supported. The list is expected to grow as additional functionality is
// implemented, particularly for C++ interoperability.
&[
"aarch64-jump-table-hardening",
"ptrauth-indirect-gotos",
"ptrauth-calls",
"ptrauth-returns",
"ptrauth-auth-traps",
]
}

pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>(
cx: &CodegenCx<'ll, '_>,
instance: Instance<'tcx>,
llfn: &'ll llvm::Value,
pac: PacMetadata,
schema: PointerAuthSchema,
) -> &'ll llvm::Value {
if cx.sess().target.llvm_abiname != LlvmAbi::Pauthtest {
return llfn;
}
assert!(cx.tcx.sess.pointer_authentication_functions().is_some());

// Only free functions or methods
let def_id = instance.def_id();
Expand All @@ -68,16 +52,16 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>(
return llfn;
}

let addr_diversity = match pac.addr_diversity {
AddressDiversity::None => None,
AddressDiversity::Real => Some(llfn),
AddressDiversity::Synthetic(val) => {
let addr_diversity = match schema.is_address_discriminated {
PointerAuthAddressDiscriminator::HardwareAddress(true) => Some(llfn),
PointerAuthAddressDiscriminator::HardwareAddress(false) => None,
PointerAuthAddressDiscriminator::Synthetic(val) => {
let llval = cx.const_u64(val);
let llty = cx.val_ty(llfn);
Some(unsafe { llvm::LLVMConstIntToPtr(llval, llty) })
}
};
const_ptr_auth(llfn, pac.key, pac.disc, addr_diversity)
const_ptr_auth(llfn, schema.key as u32, schema.constant_discriminator as u64, addr_diversity)
}

/*
Expand Down Expand Up @@ -331,7 +315,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
cv: Scalar,
layout: abi::Scalar,
llty: &'ll Type,
pac: Option<PacMetadata>,
schema: Option<PointerAuthSchema>,
) -> &'ll Value {
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
match cv {
Expand Down Expand Up @@ -366,6 +350,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
alloc.inner(),
IsStatic::No,
IsInitOrFini::No,
None,
);
let alloc = alloc.inner();
let value = match alloc.mutability {
Expand All @@ -387,7 +372,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
value
}
}
GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance, pac),
GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance, schema),
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
Expand All @@ -403,6 +388,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
alloc.inner(),
IsStatic::No,
IsInitOrFini::No,
None,
);
self.static_addr_of_impl(init, alloc.inner().align, None)
}
Expand Down
Loading
Loading