Skip to content

Commit 3315105

Browse files
committed
core/ptr: Add simulate_realloc()
Add a `simulate_realloc()` helper function to core/ptr to simulate reallocating memory from a pointer to some arbitrary address. The function is intended to be used with architecture features such as AArch64 Top-Byte Ignore where two different 64-bit addresses can point to the same chunk of memory due to some bits being ignored. To make the function accurately simulate an allocator, its return value needs to be annotated with `noalias` in LLVM the same way as it is done by actual allocator functions. To make that possible, add a new rustc built-in attribute `rustc_simulate_allocator` that does the annotating.
1 parent 17a19e6 commit 3315105

File tree

6 files changed

+45
-0
lines changed

6 files changed

+45
-0
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+4
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,10 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
482482
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
483483
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
484484
}
485+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::SIMULATE_ALLOCATOR) {
486+
let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
487+
attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
488+
}
485489
if let Some(align) = codegen_fn_attrs.alignment {
486490
llvm::set_alignment(llfn, align);
487491
}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+3
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
110110
sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND,
111111
sym::rustc_reallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR,
112112
sym::rustc_deallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR,
113+
sym::rustc_simulate_allocator => {
114+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::SIMULATE_ALLOCATOR
115+
}
113116
sym::rustc_allocator_zeroed => {
114117
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
115118
}

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
691691
rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
692692
EncodeCrossCrate::No, IMPL_DETAIL
693693
),
694+
rustc_attr!(
695+
rustc_simulate_allocator, Normal, template!(Word), WarnFollowing,
696+
EncodeCrossCrate::No, IMPL_DETAIL
697+
),
694698
gated!(
695699
default_lib_allocator, Normal, template!(Word), WarnFollowing,
696700
EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator),

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ bitflags::bitflags! {
133133
const ALLOCATOR_ZEROED = 1 << 18;
134134
/// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
135135
const NO_BUILTINS = 1 << 19;
136+
/// `#[rustc_simulate_allocator]`: a hint to LLVM that the function simulates an allocation
137+
const SIMULATE_ALLOCATOR = 1 << 20;
136138
}
137139
}
138140
rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,7 @@ symbols! {
17351735
rustc_runtime,
17361736
rustc_safe_intrinsic,
17371737
rustc_serialize,
1738+
rustc_simulate_allocator,
17381739
rustc_skip_during_method_dispatch,
17391740
rustc_specialization_trait,
17401741
rustc_std_internal_symbol,

library/core/src/ptr/mod.rs

+31
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@
446446
// There are many unsafe functions taking pointers that don't dereference them.
447447
#![allow(clippy::not_unsafe_ptr_arg_deref)]
448448

449+
use crate::arch::asm;
449450
use crate::cmp::Ordering;
450451
use crate::marker::FnPtr;
451452
use crate::mem::{self, MaybeUninit};
@@ -2441,3 +2442,33 @@ pub macro addr_of($place:expr) {
24412442
pub macro addr_of_mut($place:expr) {
24422443
&raw mut $place
24432444
}
2445+
2446+
/// Simulate a realloc to a new address
2447+
///
2448+
/// Intended for use with pointer tagging architecture features such as AArch64 TBI.
2449+
/// This function creates a new pointer with the address `new_address` and a brand new provenance,
2450+
/// simulating a realloc from the original address to the new address.
2451+
/// Note that this is only a simulated realloc - nothing actually gets moved or reallocated.
2452+
///
2453+
/// SAFETY: Users *must* ensure that `new_address` actually contains the same memory as the original.
2454+
/// The primary use-case is working with various architecture pointer tagging schemes, where two
2455+
/// different 64-bit addresses can point to the same chunk of memory due to some bits being ignored.
2456+
/// When used incorrectly, this function can be used to violate the memory model in arbitrary ways.
2457+
/// Furthermore, after using this function, users must ensure that the underlying memory is only ever
2458+
/// accessed through the newly created pointer. Any accesses through the original pointer
2459+
/// (or any pointers derived from it) would be Undefined Behaviour.
2460+
#[inline(never)]
2461+
#[unstable(feature = "ptr_simulate_realloc", issue = "none")]
2462+
#[cfg_attr(not(bootstrap), rustc_simulate_allocator)]
2463+
#[allow(fuzzy_provenance_casts)]
2464+
pub unsafe fn simulate_realloc<T>(original: *mut T, new_address: usize) -> *mut T {
2465+
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
2466+
let mut ptr = new_address as *mut T;
2467+
// SAFETY: This does not do anything
2468+
unsafe {
2469+
asm!("/* simulate realloc from {original} to {ptr} */",
2470+
original = in(reg) original, ptr = inout(reg) ptr);
2471+
}
2472+
// FIXME: call Miri hooks to update the address of the original allocation
2473+
ptr
2474+
}

0 commit comments

Comments
 (0)