From 79cd6f38f3546505f5e7a6e5ce4f696ea6b19d19 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 3 Jul 2022 21:54:45 -0400 Subject: [PATCH 1/4] Implement a crude stack printing mechanism --- src/tools/miri/src/range_map.rs | 4 ++++ src/tools/miri/src/shims/foreign_items.rs | 13 +++++++++++++ src/tools/miri/src/stacked_borrows/mod.rs | 15 +++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/tools/miri/src/range_map.rs b/src/tools/miri/src/range_map.rs index c77ea63b087..4742a365ec3 100644 --- a/src/tools/miri/src/range_map.rs +++ b/src/tools/miri/src/range_map.rs @@ -91,6 +91,10 @@ impl RangeMap { self.v.iter_mut().map(|elem| &mut elem.data) } + pub fn iter_all(&self) -> impl Iterator, &T)> { + self.v.iter().map(|elem| (elem.range.clone(), &elem.data)) + } + // Splits the element situated at the given `index`, such that the 2nd one starts at offset // `split_offset`. Do nothing if the element already starts there. // Returns whether a split was necessary. diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 26184fdc3c0..7e6a9595161 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -417,6 +417,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // shim, add it to the corresponding submodule. match link_name.as_str() { // Miri-specific extern functions + "miri_get_alloc_id" => { + let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr)?; + this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; + } + "miri_print_stacks" => { + let [id] = this.check_shim(abi, Abi::Rust, link_name, args)?; + let id = this.read_scalar(id)?.to_u64()?; + if let Some(id) = std::num::NonZeroU64::new(id) { + this.print_stacks(AllocId(id))?; + } + } "miri_static_root" => { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; diff --git a/src/tools/miri/src/stacked_borrows/mod.rs b/src/tools/miri/src/stacked_borrows/mod.rs index 09d36ca9dfd..f1dd38e5fc1 100644 --- a/src/tools/miri/src/stacked_borrows/mod.rs +++ b/src/tools/miri/src/stacked_borrows/mod.rs @@ -1123,4 +1123,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } Ok(()) } + + fn print_stacks(&mut self, alloc_id: AllocId) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let alloc_extra = this.get_alloc_extra(alloc_id)?; + let stacks = alloc_extra.stacked_borrows.as_ref().unwrap().borrow(); + for (range, stack) in stacks.stacks.iter_all() { + print!("{:?}: [", range); + for i in 0..stack.len() { + let item = stack.get(i).unwrap(); + print!(" {:?}{:?}", item.perm(), item.tag()); + } + println!(" ]"); + } + Ok(()) + } } From 26186d7ff247b74287f21dfebcd08d0d5e0152aa Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 14 Oct 2022 20:04:27 -0400 Subject: [PATCH 2/4] Add a test --- .../pass/stacked-borrows/stack-printing.rs | 29 +++++++++++++++++++ .../stacked-borrows/stack-printing.stdout | 5 ++++ 2 files changed, 34 insertions(+) create mode 100644 src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs create mode 100644 src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs new file mode 100644 index 00000000000..8d96a2e1ca9 --- /dev/null +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs @@ -0,0 +1,29 @@ +use std::{ + alloc::{self, Layout}, + mem::ManuallyDrop, +}; + +extern "Rust" { + fn miri_get_alloc_id(ptr: *const u8) -> u64; + fn miri_print_stacks(alloc_id: u64); +} + +fn main() { + let ptr = unsafe { alloc::alloc(Layout::new::()) }; + let alloc_id = unsafe { miri_get_alloc_id(ptr) }; + unsafe { miri_print_stacks(alloc_id) }; + + assert!(!ptr.is_null()); + unsafe { miri_print_stacks(alloc_id) }; + + unsafe { *ptr = 42 }; + unsafe { miri_print_stacks(alloc_id) }; + + let _b = unsafe { ManuallyDrop::new(Box::from_raw(ptr)) }; + unsafe { miri_print_stacks(alloc_id) }; + + let _ptr = unsafe { &*ptr }; + unsafe { miri_print_stacks(alloc_id) }; + + unsafe { alloc::dealloc(ptr, Layout::new::()) }; +} diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout new file mode 100644 index 00000000000..6d4f15453d2 --- /dev/null +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout @@ -0,0 +1,5 @@ +0..1: [ SharedReadWrite<2794> ] +0..1: [ SharedReadWrite<2794> ] +0..1: [ SharedReadWrite<2794> ] +0..1: [ SharedReadWrite<2794> Unique<2822> Unique<2823> Unique<2824> Unique<2828> Unique<2830> ] +0..1: [ SharedReadWrite<2794> Disabled<2822> Disabled<2823> Disabled<2824> Disabled<2828> Disabled<2830> SharedReadOnly<2832> ] From d287a0be79bc696523bf33d8159204ae4cc588ca Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 15 Oct 2022 19:19:12 -0400 Subject: [PATCH 3/4] Replace tags in stdout --- src/tools/miri/tests/compiletest.rs | 2 ++ .../tests/pass/stacked-borrows/stack-printing.stdout | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 4789d22eb4f..46c78df30b1 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -138,6 +138,8 @@ regexes! { STDOUT: // Windows file paths r"\\" => "/", + // erase Stacked Borrows tags + "<[0-9]+>" => "", } regexes! { diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout index 6d4f15453d2..660ee71e6f5 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout @@ -1,5 +1,5 @@ -0..1: [ SharedReadWrite<2794> ] -0..1: [ SharedReadWrite<2794> ] -0..1: [ SharedReadWrite<2794> ] -0..1: [ SharedReadWrite<2794> Unique<2822> Unique<2823> Unique<2824> Unique<2828> Unique<2830> ] -0..1: [ SharedReadWrite<2794> Disabled<2822> Disabled<2823> Disabled<2824> Disabled<2828> Disabled<2830> SharedReadOnly<2832> ] +0..1: [ SharedReadWrite ] +0..1: [ SharedReadWrite ] +0..1: [ SharedReadWrite ] +0..1: [ SharedReadWrite Unique Unique Unique Unique Unique ] +0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] From 2420d533f2cba3d940fe4ed9f04bfeb1a51bc689 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 18 Oct 2022 18:58:26 -0400 Subject: [PATCH 4/4] Add docs --- src/tools/miri/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 7ad51520a42..32e616cb074 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -531,6 +531,17 @@ extern "Rust" { /// This is internal and unstable and should not be used; we give it here /// just to be complete. fn miri_start_panic(payload: *mut u8) -> !; + + /// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer + /// points to. This is only useful as an input to `miri_print_stacks`, and it is a separate call because + /// getting a pointer to an allocation at runtime can change the borrow stacks in the allocation. + fn miri_get_alloc_id(ptr: *const ()) -> u64; + + /// Miri-provided extern function to print (from the interpreter, not the program) the contents of all + /// borrow stacks in an allocation. The format of what this emits is unstable and may change at any time. + /// In particular, users should be aware that Miri will periodically attempt to garbage collect the + /// contents of all stacks. Callers of this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC. + fn miri_print_stacks(alloc_id: u64); } ```