add option to track all read/write accesses to tracked allocations
This commit is contained in:
parent
fe9dede3e2
commit
fe545d62db
@ -534,6 +534,8 @@ fn main() {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
miri_config.tracked_alloc_ids.extend(ids);
|
miri_config.tracked_alloc_ids.extend(ids);
|
||||||
|
} else if arg == "-Zmiri-track-alloc-accesses" {
|
||||||
|
miri_config.track_alloc_accesses = true;
|
||||||
} else if let Some(param) = arg.strip_prefix("-Zmiri-compare-exchange-weak-failure-rate=") {
|
} else if let Some(param) = arg.strip_prefix("-Zmiri-compare-exchange-weak-failure-rate=") {
|
||||||
let rate = match param.parse::<f64>() {
|
let rate = match param.parse::<f64>() {
|
||||||
Ok(rate) if rate >= 0.0 && rate <= 1.0 => rate,
|
Ok(rate) if rate >= 0.0 && rate <= 1.0 => rate,
|
||||||
|
@ -122,13 +122,6 @@ impl VisitProvenance for GlobalStateInner {
|
|||||||
/// We need interior mutable access to the global state.
|
/// We need interior mutable access to the global state.
|
||||||
pub type GlobalState = RefCell<GlobalStateInner>;
|
pub type GlobalState = RefCell<GlobalStateInner>;
|
||||||
|
|
||||||
/// Indicates which kind of access is being performed.
|
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub enum AccessKind {
|
|
||||||
Read,
|
|
||||||
Write,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for AccessKind {
|
impl fmt::Display for AccessKind {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||||||
use rustc_span::{Span, SpanData};
|
use rustc_span::{Span, SpanData};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
|
|
||||||
use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind};
|
use crate::borrow_tracker::{GlobalStateInner, ProtectorKind};
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Error reporting
|
/// Error reporting
|
||||||
|
@ -16,7 +16,7 @@ use rustc_target::abi::{Abi, Size};
|
|||||||
|
|
||||||
use crate::borrow_tracker::{
|
use crate::borrow_tracker::{
|
||||||
stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder},
|
stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder},
|
||||||
AccessKind, GlobalStateInner, ProtectorKind,
|
GlobalStateInner, ProtectorKind,
|
||||||
};
|
};
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use crate::borrow_tracker::tree_borrows::{
|
|||||||
tree::LocationState,
|
tree::LocationState,
|
||||||
unimap::UniIndex,
|
unimap::UniIndex,
|
||||||
};
|
};
|
||||||
use crate::borrow_tracker::{AccessKind, ProtectorKind};
|
use crate::borrow_tracker::ProtectorKind;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Cause of an access: either a real access or one
|
/// Cause of an access: either a real access or one
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc_target::abi::{Abi, Size};
|
use rustc_target::abi::{Abi, Size};
|
||||||
|
|
||||||
use crate::borrow_tracker::{AccessKind, GlobalState, GlobalStateInner, ProtectorKind};
|
use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind};
|
||||||
use rustc_middle::{
|
use rustc_middle::{
|
||||||
mir::{Mutability, RetagKind},
|
mir::{Mutability, RetagKind},
|
||||||
ty::{
|
ty::{
|
||||||
|
@ -3,7 +3,7 @@ use std::fmt;
|
|||||||
|
|
||||||
use crate::borrow_tracker::tree_borrows::diagnostics::TransitionError;
|
use crate::borrow_tracker::tree_borrows::diagnostics::TransitionError;
|
||||||
use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness;
|
use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness;
|
||||||
use crate::borrow_tracker::AccessKind;
|
use crate::AccessKind;
|
||||||
|
|
||||||
/// The activation states of a pointer.
|
/// The activation states of a pointer.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -24,7 +24,7 @@ use crate::borrow_tracker::tree_borrows::{
|
|||||||
unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap},
|
unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap},
|
||||||
Permission,
|
Permission,
|
||||||
};
|
};
|
||||||
use crate::borrow_tracker::{AccessKind, GlobalState, ProtectorKind};
|
use crate::borrow_tracker::{GlobalState, ProtectorKind};
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -116,6 +116,7 @@ pub enum NonHaltingDiagnostic {
|
|||||||
CreatedCallId(CallId),
|
CreatedCallId(CallId),
|
||||||
CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
|
CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
|
||||||
FreedAlloc(AllocId),
|
FreedAlloc(AllocId),
|
||||||
|
AccessedAlloc(AllocId, AccessKind),
|
||||||
RejectedIsolatedOp(String),
|
RejectedIsolatedOp(String),
|
||||||
ProgressReport {
|
ProgressReport {
|
||||||
block_count: u64, // how many basic blocks have been run so far
|
block_count: u64, // how many basic blocks have been run so far
|
||||||
@ -538,6 +539,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
| PoppedPointerTag(..)
|
| PoppedPointerTag(..)
|
||||||
| CreatedCallId(..)
|
| CreatedCallId(..)
|
||||||
| CreatedAlloc(..)
|
| CreatedAlloc(..)
|
||||||
|
| AccessedAlloc(..)
|
||||||
| FreedAlloc(..)
|
| FreedAlloc(..)
|
||||||
| ProgressReport { .. }
|
| ProgressReport { .. }
|
||||||
| WeakMemoryOutdatedLoad => ("tracking was triggered".to_string(), DiagLevel::Note),
|
| WeakMemoryOutdatedLoad => ("tracking was triggered".to_string(), DiagLevel::Note),
|
||||||
@ -559,6 +561,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
size = size.bytes(),
|
size = size.bytes(),
|
||||||
align = align.bytes(),
|
align = align.bytes(),
|
||||||
),
|
),
|
||||||
|
AccessedAlloc(AllocId(id), access_kind) =>
|
||||||
|
format!("{access_kind} access to allocation with id {id}"),
|
||||||
FreedAlloc(AllocId(id)) => format!("freed allocation with id {id}"),
|
FreedAlloc(AllocId(id)) => format!("freed allocation with id {id}"),
|
||||||
RejectedIsolatedOp(ref op) =>
|
RejectedIsolatedOp(ref op) =>
|
||||||
format!("{op} was made to return an error due to isolation"),
|
format!("{op} was made to return an error due to isolation"),
|
||||||
|
@ -112,6 +112,8 @@ pub struct MiriConfig {
|
|||||||
pub tracked_call_ids: FxHashSet<CallId>,
|
pub tracked_call_ids: FxHashSet<CallId>,
|
||||||
/// The allocation ids to report about.
|
/// The allocation ids to report about.
|
||||||
pub tracked_alloc_ids: FxHashSet<AllocId>,
|
pub tracked_alloc_ids: FxHashSet<AllocId>,
|
||||||
|
/// For the tracked alloc ids, also report read/write accesses.
|
||||||
|
pub track_alloc_accesses: bool,
|
||||||
/// Determine if data race detection should be enabled
|
/// Determine if data race detection should be enabled
|
||||||
pub data_race_detector: bool,
|
pub data_race_detector: bool,
|
||||||
/// Determine if weak memory emulation should be enabled. Requires data race detection to be enabled
|
/// Determine if weak memory emulation should be enabled. Requires data race detection to be enabled
|
||||||
@ -169,6 +171,7 @@ impl Default for MiriConfig {
|
|||||||
tracked_pointer_tags: FxHashSet::default(),
|
tracked_pointer_tags: FxHashSet::default(),
|
||||||
tracked_call_ids: FxHashSet::default(),
|
tracked_call_ids: FxHashSet::default(),
|
||||||
tracked_alloc_ids: FxHashSet::default(),
|
tracked_alloc_ids: FxHashSet::default(),
|
||||||
|
track_alloc_accesses: false,
|
||||||
data_race_detector: true,
|
data_race_detector: true,
|
||||||
weak_memory_emulation: true,
|
weak_memory_emulation: true,
|
||||||
track_outdated_loads: false,
|
track_outdated_loads: false,
|
||||||
|
@ -22,6 +22,13 @@ use rand::RngCore;
|
|||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
/// Indicates which kind of access is being performed.
|
||||||
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
|
||||||
|
pub enum AccessKind {
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
}
|
||||||
|
|
||||||
// This mapping should match `decode_error_kind` in
|
// This mapping should match `decode_error_kind` in
|
||||||
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/unix/mod.rs>.
|
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/unix/mod.rs>.
|
||||||
const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
|
const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
|
||||||
|
@ -120,7 +120,7 @@ pub use crate::diagnostics::{
|
|||||||
pub use crate::eval::{
|
pub use crate::eval::{
|
||||||
create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
|
create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
|
||||||
};
|
};
|
||||||
pub use crate::helpers::EvalContextExt as _;
|
pub use crate::helpers::{AccessKind, EvalContextExt as _};
|
||||||
pub use crate::intptrcast::{EvalContextExt as _, ProvenanceMode};
|
pub use crate::intptrcast::{EvalContextExt as _, ProvenanceMode};
|
||||||
pub use crate::machine::{
|
pub use crate::machine::{
|
||||||
AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
|
AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
|
||||||
|
@ -512,6 +512,8 @@ pub struct MiriMachine<'mir, 'tcx> {
|
|||||||
/// The allocation IDs to report when they are being allocated
|
/// The allocation IDs to report when they are being allocated
|
||||||
/// (helps for debugging memory leaks and use after free bugs).
|
/// (helps for debugging memory leaks and use after free bugs).
|
||||||
tracked_alloc_ids: FxHashSet<AllocId>,
|
tracked_alloc_ids: FxHashSet<AllocId>,
|
||||||
|
/// For the tracked alloc ids, also report read/write accesses.
|
||||||
|
track_alloc_accesses: bool,
|
||||||
|
|
||||||
/// Controls whether alignment of memory accesses is being checked.
|
/// Controls whether alignment of memory accesses is being checked.
|
||||||
pub(crate) check_alignment: AlignmentCheck,
|
pub(crate) check_alignment: AlignmentCheck,
|
||||||
@ -654,6 +656,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
extern_statics: FxHashMap::default(),
|
extern_statics: FxHashMap::default(),
|
||||||
rng: RefCell::new(rng),
|
rng: RefCell::new(rng),
|
||||||
tracked_alloc_ids: config.tracked_alloc_ids.clone(),
|
tracked_alloc_ids: config.tracked_alloc_ids.clone(),
|
||||||
|
track_alloc_accesses: config.track_alloc_accesses,
|
||||||
check_alignment: config.check_alignment,
|
check_alignment: config.check_alignment,
|
||||||
cmpxchg_weak_failure_rate: config.cmpxchg_weak_failure_rate,
|
cmpxchg_weak_failure_rate: config.cmpxchg_weak_failure_rate,
|
||||||
mute_stdout_stderr: config.mute_stdout_stderr,
|
mute_stdout_stderr: config.mute_stdout_stderr,
|
||||||
@ -793,6 +796,7 @@ impl VisitProvenance for MiriMachine<'_, '_> {
|
|||||||
local_crates: _,
|
local_crates: _,
|
||||||
rng: _,
|
rng: _,
|
||||||
tracked_alloc_ids: _,
|
tracked_alloc_ids: _,
|
||||||
|
track_alloc_accesses: _,
|
||||||
check_alignment: _,
|
check_alignment: _,
|
||||||
cmpxchg_weak_failure_rate: _,
|
cmpxchg_weak_failure_rate: _,
|
||||||
mute_stdout_stderr: _,
|
mute_stdout_stderr: _,
|
||||||
@ -1235,6 +1239,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
|
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
|
||||||
range: AllocRange,
|
range: AllocRange,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
if machine.track_alloc_accesses && machine.tracked_alloc_ids.contains(&alloc_id) {
|
||||||
|
machine
|
||||||
|
.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc(alloc_id, AccessKind::Read));
|
||||||
|
}
|
||||||
if let Some(data_race) = &alloc_extra.data_race {
|
if let Some(data_race) = &alloc_extra.data_race {
|
||||||
data_race.read(alloc_id, range, machine)?;
|
data_race.read(alloc_id, range, machine)?;
|
||||||
}
|
}
|
||||||
@ -1255,6 +1263,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
|
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
|
||||||
range: AllocRange,
|
range: AllocRange,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
if machine.track_alloc_accesses && machine.tracked_alloc_ids.contains(&alloc_id) {
|
||||||
|
machine
|
||||||
|
.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc(alloc_id, AccessKind::Write));
|
||||||
|
}
|
||||||
if let Some(data_race) = &mut alloc_extra.data_race {
|
if let Some(data_race) = &mut alloc_extra.data_race {
|
||||||
data_race.write(alloc_id, range, machine)?;
|
data_race.write(alloc_id, range, machine)?;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ error: deadlock: the evaluated program deadlocked
|
|||||||
LL | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0);
|
LL | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked
|
||||||
|
|
|
|
||||||
|
= note: BACKTRACE on thread `unnamed-ID`:
|
||||||
= note: inside closure at RUSTLIB/core/src/macros/mod.rs:LL:CC
|
= note: inside closure at RUSTLIB/core/src/macros/mod.rs:LL:CC
|
||||||
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ error: deadlock: the evaluated program deadlocked
|
|||||||
LL | assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0);
|
LL | assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0);
|
||||||
| ^ the evaluated program deadlocked
|
| ^ the evaluated program deadlocked
|
||||||
|
|
|
|
||||||
|
= note: BACKTRACE on thread `unnamed-ID`:
|
||||||
= note: inside closure at $DIR/windows_join_self.rs:LL:CC
|
= note: inside closure at $DIR/windows_join_self.rs:LL:CC
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
@ -4,6 +4,7 @@ error: memory leaked: ALLOC (Rust heap, size: 16, align: 4), allocated here:
|
|||||||
LL | __rust_alloc(layout.size(), layout.align())
|
LL | __rust_alloc(layout.size(), layout.align())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
= note: BACKTRACE:
|
||||||
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||||
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||||
= note: inside `<std::alloc::Global as std::alloc::Allocator>::allocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
= note: inside `<std::alloc::Global as std::alloc::Allocator>::allocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||||
|
Loading…
x
Reference in New Issue
Block a user