diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/miri/README.md | 9 | ||||
| -rw-r--r-- | src/tools/miri/src/concurrency/data_race.rs | 5 | ||||
| -rw-r--r-- | src/tools/miri/src/machine.rs | 5 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/foreign_items.rs | 46 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/miri-alloc.rs | 29 |
5 files changed, 84 insertions, 10 deletions
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 7ca58cb3f80..939d7b19fa9 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -568,6 +568,15 @@ extern "Rust" { /// program) the contents of a section of program memory, as bytes. Bytes /// written using this function will emerge from the interpreter's stderr. fn miri_write_to_stderr(bytes: &[u8]); + + /// Miri-provided extern function to allocate memory from the interpreter. + /// + /// This is useful when no fundamental way of allocating memory is + /// available, e.g. when using `no_std` + `alloc`. + fn miri_alloc(size: usize, align: usize) -> *mut u8; + + /// Miri-provided extern function to deallocate memory. + fn miri_dealloc(ptr: *mut u8, size: usize, align: usize); } ``` diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 69514395bc9..b0f76646212 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -686,7 +686,10 @@ impl VClockAlloc { let (alloc_timestamp, alloc_index) = match kind { // User allocated and stack memory should track allocation. MemoryKind::Machine( - MiriMemoryKind::Rust | MiriMemoryKind::C | MiriMemoryKind::WinHeap, + MiriMemoryKind::Rust + | MiriMemoryKind::Miri + | MiriMemoryKind::C + | MiriMemoryKind::WinHeap, ) | MemoryKind::Stack => { let (alloc_index, clocks) = global.current_thread_state(thread_mgr); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 231a99c1d03..9a822bb0849 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -77,6 +77,8 @@ impl VisitTags for FrameData<'_> { pub enum MiriMemoryKind { /// `__rust_alloc` memory. Rust, + /// `miri_alloc` memory. + Miri, /// `malloc` memory. C, /// Windows `HeapAlloc` memory. @@ -110,7 +112,7 @@ impl MayLeak for MiriMemoryKind { fn may_leak(self) -> bool { use self::MiriMemoryKind::*; match self { - Rust | C | WinHeap | Runtime => false, + Rust | Miri | C | WinHeap | Runtime => false, Machine | Global | ExternStatic | Tls => true, } } @@ -121,6 +123,7 @@ impl fmt::Display for MiriMemoryKind { use self::MiriMemoryKind::*; match self { Rust => write!(f, "Rust heap"), + Miri => write!(f, "Miri bare-metal heap"), C => write!(f, "C heap"), WinHeap => write!(f, "Windows heap"), Machine => write!(f, "machine-managed memory"), diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 1b3205aabc9..058f730833b 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -513,22 +513,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Rust allocation - "__rust_alloc" => { + "__rust_alloc" | "miri_alloc" => { let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let size = this.read_scalar(size)?.to_machine_usize(this)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; - return this.emulate_allocator(Symbol::intern("__rg_alloc"), |this| { + let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { Self::check_alloc_request(size, align)?; + let memory_kind = match link_name.as_str() { + "__rust_alloc" => MiriMemoryKind::Rust, + "miri_alloc" => MiriMemoryKind::Miri, + _ => unreachable!(), + }; + let ptr = this.allocate_ptr( Size::from_bytes(size), Align::from_bytes(align).unwrap(), - MiriMemoryKind::Rust.into(), + memory_kind.into(), )?; this.write_pointer(ptr, dest) - }); + }; + + match link_name.as_str() { + "__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default), + "miri_alloc" => { + default(this)?; + return Ok(EmulateByNameResult::NeedsJumping); + }, + _ => unreachable!(), + } } "__rust_alloc_zeroed" => { let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; @@ -549,20 +564,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_pointer(ptr, dest) }); } - "__rust_dealloc" => { + "__rust_dealloc" | "miri_dealloc" => { let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; - return this.emulate_allocator(Symbol::intern("__rg_dealloc"), |this| { + let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { + let memory_kind = match link_name.as_str() { + "__rust_dealloc" => MiriMemoryKind::Rust, + "miri_dealloc" => MiriMemoryKind::Miri, + _ => unreachable!(), + }; + // No need to check old_size/align; we anyway check that they match the allocation. this.deallocate_ptr( ptr, Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())), - MiriMemoryKind::Rust.into(), + memory_kind.into(), ) - }); + }; + + match link_name.as_str() { + "__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default), + "miri_dealloc" => { + default(this)?; + return Ok(EmulateByNameResult::NeedsJumping); + } + _ => unreachable!(), + } } "__rust_realloc" => { let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?; diff --git a/src/tools/miri/tests/pass/miri-alloc.rs b/src/tools/miri/tests/pass/miri-alloc.rs new file mode 100644 index 00000000000..f6464b5bd01 --- /dev/null +++ b/src/tools/miri/tests/pass/miri-alloc.rs @@ -0,0 +1,29 @@ +#![feature(lang_items, start)] +#![no_std] +// windows tls dtors go through libstd right now, thus this test +// cannot pass. When windows tls dtors go through the special magic +// windows linker section, we can run this test on windows again. +//@ignore-target-windows: no-std not supported on Windows + +extern "Rust" { + fn miri_alloc(size: usize, align: usize) -> *mut u8; + fn miri_dealloc(ptr: *mut u8, size: usize, align: usize); +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + unsafe { + let ptr = miri_alloc(123, 1); + core::ptr::write_bytes(ptr, 0u8, 123); + miri_dealloc(ptr, 123, 1); + } + 0 +} + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[lang = "eh_personality"] +fn eh_personality() {} |
