@@ -347,7 +347,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
347347 /// Emulates calling the internal __rust_* allocator functions
348348 fn emulate_allocator (
349349 & mut self ,
350- symbol : Symbol ,
351350 default : impl FnOnce ( & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > ,
352351 ) -> InterpResult < ' tcx , EmulateByNameResult < ' mir , ' tcx > > {
353352 let this = self . eval_context_mut ( ) ;
@@ -359,11 +358,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
359358
360359 match allocator_kind {
361360 AllocatorKind :: Global => {
362- let ( body, instance) = this
363- . lookup_exported_symbol ( symbol) ?
364- . expect ( "symbol should be present if there is a global allocator" ) ;
365-
366- Ok ( EmulateByNameResult :: MirBody ( body, instance) )
361+ // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
362+ // of this attribute. As such we have to call an exported Rust function,
363+ // and not execute any Miri shim. Somewhat unintuitively doing so is done
364+ // by returning `NotSupported`, which triggers the `lookup_exported_symbol`
365+ // fallback case in `emulate_foreign_item`.
366+ return Ok ( EmulateByNameResult :: NotSupported ) ;
367367 }
368368 AllocatorKind :: Default => {
369369 default ( this) ?;
@@ -558,11 +558,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
558558
559559 // Rust allocation
560560 "__rust_alloc" | "miri_alloc" => {
561- let [ size, align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
562- let size = this. read_target_usize ( size) ?;
563- let align = this. read_target_usize ( align) ?;
564-
565561 let default = |this : & mut MiriInterpCx < ' mir , ' tcx > | {
562+ // Only call `check_shim` when `#[global_allocator]` isn't used. When that
563+ // macro is used, we act like no shim exists, so that the exported function can run.
564+ let [ size, align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
565+ let size = this. read_target_usize ( size) ?;
566+ let align = this. read_target_usize ( align) ?;
567+
566568 Self :: check_alloc_request ( size, align) ?;
567569
568570 let memory_kind = match link_name. as_str ( ) {
@@ -581,8 +583,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
581583 } ;
582584
583585 match link_name. as_str ( ) {
584- "__rust_alloc" =>
585- return this. emulate_allocator ( Symbol :: intern ( "__rg_alloc" ) , default) ,
586+ "__rust_alloc" => return this. emulate_allocator ( default) ,
586587 "miri_alloc" => {
587588 default ( this) ?;
588589 return Ok ( EmulateByNameResult :: NeedsJumping ) ;
@@ -591,11 +592,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
591592 }
592593 }
593594 "__rust_alloc_zeroed" => {
594- let [ size, align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
595- let size = this. read_target_usize ( size) ?;
596- let align = this. read_target_usize ( align) ?;
595+ return this. emulate_allocator ( |this| {
596+ // See the comment for `__rust_alloc` why `check_shim` is only called in the
597+ // default case.
598+ let [ size, align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
599+ let size = this. read_target_usize ( size) ?;
600+ let align = this. read_target_usize ( align) ?;
597601
598- return this. emulate_allocator ( Symbol :: intern ( "__rg_alloc_zeroed" ) , |this| {
599602 Self :: check_alloc_request ( size, align) ?;
600603
601604 let ptr = this. allocate_ptr (
@@ -614,12 +617,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
614617 } ) ;
615618 }
616619 "__rust_dealloc" | "miri_dealloc" => {
617- let [ ptr, old_size, align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
618- let ptr = this. read_pointer ( ptr) ?;
619- let old_size = this. read_target_usize ( old_size) ?;
620- let align = this. read_target_usize ( align) ?;
621-
622620 let default = |this : & mut MiriInterpCx < ' mir , ' tcx > | {
621+ // See the comment for `__rust_alloc` why `check_shim` is only called in the
622+ // default case.
623+ let [ ptr, old_size, align] =
624+ this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
625+ let ptr = this. read_pointer ( ptr) ?;
626+ let old_size = this. read_target_usize ( old_size) ?;
627+ let align = this. read_target_usize ( align) ?;
628+
623629 let memory_kind = match link_name. as_str ( ) {
624630 "__rust_dealloc" => MiriMemoryKind :: Rust ,
625631 "miri_dealloc" => MiriMemoryKind :: Miri ,
@@ -635,8 +641,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
635641 } ;
636642
637643 match link_name. as_str ( ) {
638- "__rust_dealloc" =>
639- return this. emulate_allocator ( Symbol :: intern ( "__rg_dealloc" ) , default) ,
644+ "__rust_dealloc" => {
645+ return this. emulate_allocator ( default) ;
646+ }
640647 "miri_dealloc" => {
641648 default ( this) ?;
642649 return Ok ( EmulateByNameResult :: NeedsJumping ) ;
@@ -645,15 +652,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
645652 }
646653 }
647654 "__rust_realloc" => {
648- let [ ptr, old_size, align, new_size] =
649- this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
650- let ptr = this. read_pointer ( ptr) ?;
651- let old_size = this. read_target_usize ( old_size) ?;
652- let align = this. read_target_usize ( align) ?;
653- let new_size = this. read_target_usize ( new_size) ?;
654- // No need to check old_size; we anyway check that they match the allocation.
655+ return this. emulate_allocator ( |this| {
656+ // See the comment for `__rust_alloc` why `check_shim` is only called in the
657+ // default case.
658+ let [ ptr, old_size, align, new_size] =
659+ this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
660+ let ptr = this. read_pointer ( ptr) ?;
661+ let old_size = this. read_target_usize ( old_size) ?;
662+ let align = this. read_target_usize ( align) ?;
663+ let new_size = this. read_target_usize ( new_size) ?;
664+ // No need to check old_size; we anyway check that they match the allocation.
655665
656- return this. emulate_allocator ( Symbol :: intern ( "__rg_realloc" ) , |this| {
657666 Self :: check_alloc_request ( new_size, align) ?;
658667
659668 let align = Align :: from_bytes ( align) . unwrap ( ) ;
0 commit comments