Skip to content

Commit 8bbb040

Browse files
committed
TB: integration
1 parent 0afab59 commit 8bbb040

File tree

6 files changed

+54
-16
lines changed

6 files changed

+54
-16
lines changed

src/tools/miri/src/bin/miri.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_middle::{
3232
};
3333
use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace};
3434

35-
use miri::{BacktraceStyle, ProvenanceMode, RetagFields};
35+
use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields};
3636

3737
struct MiriCompilerCalls {
3838
miri_config: miri::MiriConfig,
@@ -317,6 +317,8 @@ fn main() {
317317
miri_config.validate = false;
318318
} else if arg == "-Zmiri-disable-stacked-borrows" {
319319
miri_config.borrow_tracker = None;
320+
} else if arg == "-Zmiri-tree-borrows" {
321+
miri_config.borrow_tracker = Some(BorrowTrackerMethod::TreeBorrows);
320322
} else if arg == "-Zmiri-disable-data-race-detector" {
321323
miri_config.data_race_detector = false;
322324
miri_config.weak_memory_emulation = false;

src/tools/miri/src/diagnostics.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ pub enum TerminationInfo {
2222
help: Option<String>,
2323
history: Option<TagHistory>,
2424
},
25+
TreeBorrowsUb {
26+
msg: String,
27+
// FIXME: incomplete
28+
},
2529
Int2PtrWithStrictProvenance,
2630
Deadlock,
2731
MultipleSymbolDefinitions {
@@ -61,6 +65,7 @@ impl fmt::Display for TerminationInfo {
6165
"integer-to-pointer casts and `ptr::from_exposed_addr` are not supported with `-Zmiri-strict-provenance`"
6266
),
6367
StackedBorrowsUb { msg, .. } => write!(f, "{msg}"),
68+
TreeBorrowsUb { msg } => write!(f, "{msg}"),
6469
Deadlock => write!(f, "the evaluated program deadlocked"),
6570
MultipleSymbolDefinitions { link_name, .. } =>
6671
write!(f, "multiple definitions of symbol `{link_name}`"),
@@ -184,7 +189,8 @@ pub fn report_error<'tcx, 'mir>(
184189
Abort(_) => Some("abnormal termination"),
185190
UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
186191
Some("unsupported operation"),
187-
StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
192+
StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>
193+
Some("Undefined Behavior"),
188194
Deadlock => Some("deadlock"),
189195
MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
190196
};
@@ -212,6 +218,12 @@ pub fn report_error<'tcx, 'mir>(
212218
}
213219
}
214220
helps
221+
},
222+
TreeBorrowsUb { .. } => {
223+
let helps = vec![
224+
(None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental")),
225+
];
226+
helps
215227
}
216228
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
217229
vec![

src/tools/miri/src/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub struct MiriConfig {
8787
pub env: Vec<(OsString, OsString)>,
8888
/// Determine if validity checking is enabled.
8989
pub validate: bool,
90-
/// Determines if Stacked Borrows is enabled.
90+
/// Determines if Stacked Borrows or Tree Borrows is enabled.
9191
pub borrow_tracker: Option<BorrowTrackerMethod>,
9292
/// Controls alignment checking.
9393
pub check_alignment: AlignmentCheck,
@@ -134,7 +134,7 @@ pub struct MiriConfig {
134134
pub preemption_rate: f64,
135135
/// Report the current instruction being executed every N basic blocks.
136136
pub report_progress: Option<u32>,
137-
/// Whether Stacked Borrows retagging should recurse into fields of datatypes.
137+
/// Whether Stacked Borrows and Tree Borrows retagging should recurse into fields of datatypes.
138138
pub retag_fields: RetagFields,
139139
/// The location of a shared object file to load when calling external functions
140140
/// FIXME! consider allowing users to specify paths to multiple SO files, or to a directory

src/tools/miri/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub use crate::shims::EvalContextExt as _;
9595
pub use crate::borrow_tracker::stacked_borrows::{
9696
EvalContextExt as _, Item, Permission, Stack, Stacks,
9797
};
98+
pub use crate::borrow_tracker::tree_borrows::{EvalContextExt as _, Tree};
9899
pub use crate::borrow_tracker::{
99100
BorTag, BorrowTrackerMethod, CallId, EvalContextExt as _, RetagFields,
100101
};

src/tools/miri/src/machine.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub const SIGRTMAX: i32 = 42;
3838

3939
/// Extra data stored with each stack frame
4040
pub struct FrameExtra<'tcx> {
41-
/// Extra data for Stacked Borrows.
41+
/// Extra data for the Borrow Tracker.
4242
pub borrow_tracker: Option<borrow_tracker::FrameState>,
4343

4444
/// If this is Some(), then this is a special "catch unwind" frame (the frame of `try_fn`
@@ -146,7 +146,7 @@ impl fmt::Display for MiriMemoryKind {
146146
pub enum Provenance {
147147
Concrete {
148148
alloc_id: AllocId,
149-
/// Stacked Borrows tag.
149+
/// Borrow Tracker tag.
150150
tag: BorTag,
151151
},
152152
Wildcard,
@@ -195,7 +195,7 @@ impl fmt::Debug for Provenance {
195195
} else {
196196
write!(f, "[{alloc_id:?}]")?;
197197
}
198-
// Print Stacked Borrows tag.
198+
// Print Borrow Tracker tag.
199199
write!(f, "{tag:?}")?;
200200
}
201201
Provenance::Wildcard => {

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

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
232232
}
233233
}
234234

235+
/// Read bytes from a `(ptr, len)` argument
236+
fn read_byte_slice<'i>(&'i self, bytes: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, &'i [u8]>
237+
where
238+
'mir: 'i,
239+
{
240+
let this = self.eval_context_ref();
241+
let (ptr, len) = this.read_immediate(bytes)?.to_scalar_pair();
242+
let ptr = ptr.to_pointer(this)?;
243+
let len = len.to_target_usize(this)?;
244+
let bytes = this.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
245+
Ok(bytes)
246+
}
247+
235248
/// Emulates calling a foreign item, failing if the item is not supported.
236249
/// This function will handle `goto_block` if needed.
237250
/// Returns Ok(None) if the foreign item was completely handled
@@ -427,13 +440,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
427440
})?;
428441
this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
429442
}
430-
"miri_print_borrow_stacks" => {
431-
let [id] = this.check_shim(abi, Abi::Rust, link_name, args)?;
443+
"miri_print_borrow_state" => {
444+
let [id, show_unnamed] = this.check_shim(abi, Abi::Rust, link_name, args)?;
432445
let id = this.read_scalar(id)?.to_u64()?;
446+
let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?;
433447
if let Some(id) = std::num::NonZeroU64::new(id) {
434-
this.print_stacks(AllocId(id))?;
448+
this.print_borrow_state(AllocId(id), show_unnamed)?;
435449
}
436450
}
451+
"miri_pointer_name" => {
452+
// This associates a name to a tag. Very useful for debugging, and also makes
453+
// tests more strict.
454+
let [ptr, nth_parent, name] = this.check_shim(abi, Abi::Rust, link_name, args)?;
455+
let ptr = this.read_pointer(ptr)?;
456+
let nth_parent = this.read_scalar(nth_parent)?.to_u8()?;
457+
let name = this.read_byte_slice(name)?;
458+
// We must make `name` owned because we need to
459+
// end the shared borrow from `read_byte_slice` before we can
460+
// start the mutable borrow for `give_pointer_debug_name`.
461+
let name = String::from_utf8_lossy(name).into_owned();
462+
this.give_pointer_debug_name(ptr, nth_parent, &name)?;
463+
}
437464
"miri_static_root" => {
438465
let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
439466
let ptr = this.read_pointer(ptr)?;
@@ -487,12 +514,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
487514
// Writes some bytes to the interpreter's stdout/stderr. See the
488515
// README for details.
489516
"miri_write_to_stdout" | "miri_write_to_stderr" => {
490-
let [bytes] = this.check_shim(abi, Abi::Rust, link_name, args)?;
491-
let (ptr, len) = this.read_immediate(bytes)?.to_scalar_pair();
492-
let ptr = ptr.to_pointer(this)?;
493-
let len = len.to_target_usize(this)?;
494-
let msg = this.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
495-
517+
let [msg] = this.check_shim(abi, Abi::Rust, link_name, args)?;
518+
let msg = this.read_byte_slice(msg)?;
496519
// Note: we're ignoring errors writing to host stdout/stderr.
497520
let _ignore = match link_name.as_str() {
498521
"miri_write_to_stdout" => std::io::stdout().write_all(msg),

0 commit comments

Comments
 (0)