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
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
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 @@ -646,8 +643,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() {
cx.add_ptrauth_sign_personality_flag();
}
}

// Finalize code coverage by injecting the coverage map. Note, the coverage map will
Expand Down
4 changes: 2 additions & 2 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 @@ -2042,7 +2042,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() {
return None;
}
// Pointer authentication support is currently limited to extern "C" calls; filter out other
Expand Down
34 changes: 10 additions & 24 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,27 +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 {
if !cx.tcx.sess.pointer_authentication_functions() {

@kovdan01 kovdan01 May 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this check needed? My understanding was that we define schema argument somewhere earlier in the call stack based on the cx.tcx.sess.pointer_authentication_functions(), and if it's not set, the schema would just have kind == None.

So, can we delete the check and instead add an assertion against schema kind not being none?

I might be missing smth, and if so - I would appreciate your explanation on this topic

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I said above, I'd prefer to get rid of Kind and rely on Option. Even grepping in clang shows it serves as binary switch: on/off. But if you think it will grow with time to cover multiple kinds, I'm not against it.

What pointer_authentication_functions does is it checks if both pointer authentication config and function pointers schema are present. -Zpointer-authentication=-calls would result in the former being set, but not the later. Whether this would make for a sane use of the option is a different matter.

return llfn;
}

Expand All @@ -68,16 +54,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 +317,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 @@ -387,7 +373,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 Down
48 changes: 29 additions & 19 deletions compiler/rustc_codegen_llvm/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};
use rustc_span::Symbol;
use rustc_target::spec::{Arch, LlvmAbi};
use rustc_target::spec::Arch;
use tracing::{debug, instrument, trace};

use crate::common::CodegenCx;
Expand All @@ -32,6 +32,7 @@ pub(crate) enum IsStatic {
No,
}
/// Indicates whether a symbol is part of `.init_array` or `.fini_array`.
#[derive(PartialEq)]
pub(crate) enum IsInitOrFini {
Yes,
No,
Expand Down Expand Up @@ -120,31 +121,40 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
as u64;

let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx);
// Under pointer authentication, function pointers stored in init/fini arrays need special
// handling.
let pac_metadata = Some(
if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest
&& matches!(is_init_fini, IsInitOrFini::Yes)
{
PacMetadata {
// Must correspond to ptrauth_key_init_fini_pointer from `ptrauth.h`.
key: 0,
// ptrauth_string_discriminator("init_fini")
disc: 0xd9d4,
addr_diversity: AddressDiversity::Synthetic(1),
let schema = if cx.sess().pointer_authentication() {
match is_init_fini {
IsInitOrFini::Yes => {
if cx.sess().pointer_authentication_init_fini() {
cx.sess()
.pointer_auth_config
.as_ref()
.and_then(|cfg| cfg.init_fini.as_ref())
} else {
None
}
}
} else {
PacMetadata::default()
},
);
IsInitOrFini::No => {
if cx.sess().pointer_authentication_functions() {
cx.sess()
.pointer_auth_config
.as_ref()
.and_then(|cfg| cfg.function_pointers.as_ref())
} else {
None
}
}
}
} else {
None
};
llvals.push(cx.scalar_to_backend_with_pac(
InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx),
Scalar::Initialized {
value: Primitive::Pointer(address_space),
valid_range: WrappingRange::full(pointer_size),
},
cx.type_ptr_ext(address_space),
pac_metadata,
schema,
));
next_offset = offset + pointer_size_bytes;
}
Expand Down Expand Up @@ -221,7 +231,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
let fn_sig = sig.with(*header);
let fn_abi = cx.fn_abi_of_fn_ptr(fn_sig, ty::List::empty());
// Decide if the initializer needs to be signed
if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest
if cx.sess().pointer_authentication()
&& matches!(fn_sig.abi(), ExternAbi::C { .. } | ExternAbi::System { .. })
{
should_sign = true;
Expand Down
Loading
Loading