Skip to content

Commit 4abf250

Browse files
committed
Revert some miri changes
1 parent c7cf080 commit 4abf250

File tree

7 files changed

+169
-31
lines changed

7 files changed

+169
-31
lines changed

library/alloc/src/alloc.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use core::ptr::{self, NonNull};
1212

1313
extern "Rust" {
1414
// These are the magic symbols to call the global allocator. rustc generates
15-
// them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute
16-
// (the code expanding that attribute macro generates those functions), or to call
15+
// them to call `GLOBAL.alloc` etc. if there is a `#[global_allocator]` attribute
16+
// (the code expanding that attribute macro generates those functions), or if not
1717
// the default implementations in std (weak symbols in `library/std/src/alloc.rs`)
18-
// otherwise.
19-
// The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them
20-
// like `malloc`, `realloc`, and `free`, respectively.
18+
// is used otherwise.
19+
// The rustc fork of LLVM 14 and earlier also special-cases these function names to
20+
// be able to optimize them like `malloc`, `realloc`, and `free`, respectively.
2121
#[rustc_allocator]
2222
#[rustc_nounwind]
2323
fn __rust_alloc(size: usize, align: usize) -> *mut u8;

src/tools/miri/src/helpers.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
980980
return interp_ok(());
981981
}
982982

983+
if ["__rust_alloc", "__rust_alloc_zeroed", "__rust_realloc", "__rust_dealloc"]
984+
.contains(&link_name.as_str())
985+
{
986+
let attrs = self.eval_context_ref().tcx.codegen_fn_attrs(instance.def_id());
987+
if attrs
988+
.linkage
989+
.map_or(false, |linkage| linkage == rustc_middle::mir::mono::Linkage::WeakAny)
990+
&& attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
991+
{
992+
// We intentionally intercept the allocator methods even though libstd provides
993+
// default implementations.
994+
return interp_ok(());
995+
}
996+
}
997+
983998
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
984999
link_name,
9851000
span: body.span.data(),

src/tools/miri/src/shims/alloc.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::{Align, Size};
2+
use rustc_ast::expand::allocator::AllocatorKind;
23

34
use crate::*;
45

@@ -49,6 +50,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
4950
Align::from_bytes(prev_power_of_two(size)).unwrap()
5051
}
5152

53+
/// Emulates calling the internal __rust_* allocator functions
54+
fn emulate_allocator(
55+
&mut self,
56+
default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>,
57+
) -> InterpResult<'tcx, EmulateItemResult> {
58+
let this = self.eval_context_mut();
59+
60+
let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
61+
// in real code, this symbol does not exist without an allocator
62+
return interp_ok(EmulateItemResult::NotSupported);
63+
};
64+
65+
match allocator_kind {
66+
AllocatorKind::Global => {
67+
// When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
68+
// of this attribute. As such we have to call an exported Rust function,
69+
// and not execute any Miri shim. Somewhat unintuitively doing so is done
70+
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
71+
// fallback case in `emulate_foreign_item`.
72+
interp_ok(EmulateItemResult::NotSupported)
73+
}
74+
AllocatorKind::Default => {
75+
default(this)?;
76+
interp_ok(EmulateItemResult::NeedsReturn)
77+
}
78+
}
79+
}
80+
5281
fn malloc(&mut self, size: u64, init: AllocInit) -> InterpResult<'tcx, Pointer> {
5382
let this = self.eval_context_mut();
5483
let align = this.malloc_align(size);

src/tools/miri/src/shims/foreign_items.rs

Lines changed: 117 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::hash_map::Entry;
22
use std::io::Write;
3+
use std::iter;
34
use std::path::Path;
45

56
use rustc_abi::{Align, AlignFromBytesError, Size};
@@ -502,34 +503,127 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
502503
}
503504

504505
// Rust allocation
505-
"miri_alloc" => {
506-
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
507-
let size = this.read_target_usize(size)?;
508-
let align = this.read_target_usize(align)?;
506+
"__rust_alloc" | "miri_alloc" => {
507+
let default = |ecx: &mut MiriInterpCx<'tcx>| {
508+
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
509+
// macro is used, we act like no shim exists, so that the exported function can run.
510+
let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?;
511+
let size = ecx.read_target_usize(size)?;
512+
let align = ecx.read_target_usize(align)?;
513+
514+
ecx.check_rustc_alloc_request(size, align)?;
515+
516+
let memory_kind = match link_name.as_str() {
517+
"__rust_alloc" => MiriMemoryKind::Rust,
518+
"miri_alloc" => MiriMemoryKind::Miri,
519+
_ => unreachable!(),
520+
};
509521

510-
this.check_rustc_alloc_request(size, align)?;
522+
let ptr = ecx.allocate_ptr(
523+
Size::from_bytes(size),
524+
Align::from_bytes(align).unwrap(),
525+
memory_kind.into(),
526+
AllocInit::Uninit,
527+
)?;
511528

512-
let ptr = this.allocate_ptr(
513-
Size::from_bytes(size),
514-
Align::from_bytes(align).unwrap(),
515-
MiriMemoryKind::Miri.into(),
516-
AllocInit::Uninit,
517-
)?;
529+
ecx.write_pointer(ptr, dest)
530+
};
518531

519-
this.write_pointer(ptr, dest)?;
532+
match link_name.as_str() {
533+
"__rust_alloc" => return this.emulate_allocator(default),
534+
"miri_alloc" => {
535+
default(this)?;
536+
return interp_ok(EmulateItemResult::NeedsReturn);
537+
}
538+
_ => unreachable!(),
539+
}
520540
}
521-
"miri_dealloc" => {
522-
let [ptr, old_size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
523-
let ptr = this.read_pointer(ptr)?;
524-
let old_size = this.read_target_usize(old_size)?;
525-
let align = this.read_target_usize(align)?;
541+
"__rust_alloc_zeroed" => {
542+
return this.emulate_allocator(|this| {
543+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
544+
// default case.
545+
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
546+
let size = this.read_target_usize(size)?;
547+
let align = this.read_target_usize(align)?;
548+
549+
this.check_rustc_alloc_request(size, align)?;
550+
551+
let ptr = this.allocate_ptr(
552+
Size::from_bytes(size),
553+
Align::from_bytes(align).unwrap(),
554+
MiriMemoryKind::Rust.into(),
555+
AllocInit::Zero,
556+
)?;
526557

527-
// No need to check old_size/align; we anyway check that they match the allocation.
528-
this.deallocate_ptr(
529-
ptr,
530-
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
531-
MiriMemoryKind::Miri.into(),
532-
)?;
558+
// We just allocated this, the access is definitely in-bounds.
559+
this.write_bytes_ptr(
560+
ptr.into(),
561+
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
562+
)
563+
.unwrap();
564+
this.write_pointer(ptr, dest)
565+
});
566+
}
567+
"__rust_dealloc" | "miri_dealloc" => {
568+
let default = |ecx: &mut MiriInterpCx<'tcx>| {
569+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
570+
// default case.
571+
let [ptr, old_size, align] =
572+
ecx.check_shim(abi, Conv::Rust, link_name, args)?;
573+
let ptr = ecx.read_pointer(ptr)?;
574+
let old_size = ecx.read_target_usize(old_size)?;
575+
let align = ecx.read_target_usize(align)?;
576+
577+
let memory_kind = match link_name.as_str() {
578+
"__rust_dealloc" => MiriMemoryKind::Rust,
579+
"miri_dealloc" => MiriMemoryKind::Miri,
580+
_ => unreachable!(),
581+
};
582+
583+
// No need to check old_size/align; we anyway check that they match the allocation.
584+
ecx.deallocate_ptr(
585+
ptr,
586+
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
587+
memory_kind.into(),
588+
)
589+
};
590+
591+
match link_name.as_str() {
592+
"__rust_dealloc" => {
593+
return this.emulate_allocator(default);
594+
}
595+
"miri_dealloc" => {
596+
default(this)?;
597+
return interp_ok(EmulateItemResult::NeedsReturn);
598+
}
599+
_ => unreachable!(),
600+
}
601+
}
602+
"__rust_realloc" => {
603+
return this.emulate_allocator(|this| {
604+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
605+
// default case.
606+
let [ptr, old_size, align, new_size] =
607+
this.check_shim(abi, Conv::Rust, link_name, args)?;
608+
let ptr = this.read_pointer(ptr)?;
609+
let old_size = this.read_target_usize(old_size)?;
610+
let align = this.read_target_usize(align)?;
611+
let new_size = this.read_target_usize(new_size)?;
612+
// No need to check old_size; we anyway check that they match the allocation.
613+
614+
this.check_rustc_alloc_request(new_size, align)?;
615+
616+
let align = Align::from_bytes(align).unwrap();
617+
let new_ptr = this.reallocate_ptr(
618+
ptr,
619+
Some((Size::from_bytes(old_size), align)),
620+
Size::from_bytes(new_size),
621+
align,
622+
MiriMemoryKind::Rust.into(),
623+
AllocInit::Uninit,
624+
)?;
625+
this.write_pointer(new_ptr, dest)
626+
});
533627
}
534628

535629
// C memory handling functions

src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | ABORT();
99
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
1010
= note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC
1111
= note: inside `std::alloc::rust_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
12-
= note: inside `std::alloc::_::__rg_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
12+
= note: inside `std::alloc::_::__rust_alloc_error_handler` at RUSTLIB/std/src/alloc.rs:LL:CC
1313
= note: inside `std::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1414
= note: inside `std::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1515
note: inside `main`

src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | core::intrinsics::abort();
77
|
88
= note: BACKTRACE:
99
= note: inside `alloc_error_handler` at tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
10-
note: inside `_::__rg_oom`
10+
note: inside `_::__rust_alloc_error_handler`
1111
--> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
1212
|
1313
LL | #[alloc_error_handler]

src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | core::intrinsics::abort();
99
|
1010
= note: BACKTRACE:
1111
= note: inside `panic_handler` at tests/fail/alloc/alloc_error_handler_no_std.rs:LL:CC
12-
= note: inside `alloc::alloc::__alloc_error_handler::__rdl_oom` at RUSTLIB/alloc/src/alloc.rs:LL:CC
12+
= note: inside `alloc::alloc::__alloc_error_handler::__rust_alloc_error_handler` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1313
= note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1414
= note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1515
note: inside `miri_start`

0 commit comments

Comments
 (0)