Skip to content

Commit

Permalink
Auto merge of #1463 - RalfJung:track-call-id, r=oli-obk
Browse files Browse the repository at this point in the history
add option to track call IDs
  • Loading branch information
bors committed Jul 2, 2020
2 parents b4ccb07 + c379793 commit e7ef64f
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 15 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ Miri adds its own set of `-Z` flags:
is popped from a borrow stack (which is where the tag becomes invalid and any
future use of it will error). This helps you in finding out why UB is
happening and where in your code would be a good place to look for it.
* `-Zmiri-track-call-id=<id>` shows a backtrace when the given call id is
assigned to a stack frame. This helps in debugging UB related to Stacked
Borrows "protectors".

[alignment-false-positives]: https://github.com/rust-lang/miri/issues/1074

Expand Down
28 changes: 21 additions & 7 deletions src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ fn main() {
let mut ignore_leaks = false;
let mut seed: Option<u64> = None;
let mut tracked_pointer_tag: Option<miri::PtrId> = None;
let mut tracked_call_id: Option<miri::CallId> = None;
let mut tracked_alloc_id: Option<miri::AllocId> = None;
let mut rustc_args = vec![];
let mut crate_args = vec![];
Expand Down Expand Up @@ -233,26 +234,38 @@ fn main() {
.push(arg.strip_prefix("-Zmiri-env-exclude=").unwrap().to_owned());
}
arg if arg.starts_with("-Zmiri-track-pointer-tag=") => {
let id: u64 = match arg.strip_prefix("-Zmiri-track-pointer-tag=").unwrap().parse()
{
let id: u64 = match arg.strip_prefix("-Zmiri-track-pointer-tag=").unwrap().parse() {
Ok(id) => id,
Err(err) => panic!(
"-Zmiri-track-pointer-tag requires a valid `u64` as the argument: {}",
"-Zmiri-track-pointer-tag requires a valid `u64` argument: {}",
err
),
};
if let Some(id) = miri::PtrId::new(id) {
tracked_pointer_tag = Some(id);
} else {
panic!("-Zmiri-track-pointer-tag must be a nonzero id");
panic!("-Zmiri-track-pointer-tag requires a nonzero argument");
}
}
arg if arg.starts_with("-Zmiri-track-call-id=") => {
let id: u64 = match arg.strip_prefix("-Zmiri-track-call-id=").unwrap().parse() {
Ok(id) => id,
Err(err) => panic!(
"-Zmiri-track-call-id requires a valid `u64` argument: {}",
err
),
};
if let Some(id) = miri::CallId::new(id) {
tracked_call_id = Some(id);
} else {
panic!("-Zmiri-track-call-id requires a nonzero argument");
}
}
arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
let id: u64 = match arg.strip_prefix("-Zmiri-track-alloc-id=").unwrap().parse()
{
let id: u64 = match arg.strip_prefix("-Zmiri-track-alloc-id=").unwrap().parse() {
Ok(id) => id,
Err(err) => panic!(
"-Zmiri-track-alloc-id requires a valid `u64` as the argument: {}",
"-Zmiri-track-alloc-id requires a valid `u64` argument: {}",
err
),
};
Expand All @@ -278,6 +291,7 @@ fn main() {
seed,
args: crate_args,
tracked_pointer_tag,
tracked_call_id,
tracked_alloc_id,
};
run_compiler(rustc_args, &mut MiriCompilerCalls { miri_config })
Expand Down
7 changes: 5 additions & 2 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
PoppedTrackedPointerTag(Item),
PoppedPointerTag(Item),
CreatedCallId(CallId),
CreatedAlloc(AllocId),
FreedAlloc(AllocId),
}
Expand Down Expand Up @@ -204,8 +205,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
for e in diagnostics.borrow_mut().drain(..) {
use NonHaltingDiagnostic::*;
let msg = match e {
PoppedTrackedPointerTag(item) =>
PoppedPointerTag(item) =>
format!("popped tracked tag for item {:?}", item),
CreatedCallId(id) =>
format!("function call with id {}", id),
CreatedAlloc(AllocId(id)) =>
format!("created allocation with id {}", id),
FreedAlloc(AllocId(id)) =>
Expand Down
6 changes: 5 additions & 1 deletion src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ pub struct MiriConfig {
pub args: Vec<String>,
/// The seed to use when non-determinism or randomness are required (e.g. ptr-to-int cast, `getrandom()`).
pub seed: Option<u64>,
/// The stacked borrow id to report about
/// The stacked borrows pointer id to report about
pub tracked_pointer_tag: Option<PtrId>,
/// The stacked borrows call ID to report about
pub tracked_call_id: Option<CallId>,
/// The allocation id to report about.
pub tracked_alloc_id: Option<AllocId>,
}
Expand All @@ -49,6 +51,7 @@ impl Default for MiriConfig {
args: vec![],
seed: None,
tracked_pointer_tag: None,
tracked_call_id: None,
tracked_alloc_id: None,
}
}
Expand All @@ -74,6 +77,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
StdRng::seed_from_u64(config.seed.unwrap_or(0)),
config.stacked_borrows,
config.tracked_pointer_tag,
config.tracked_call_id,
config.tracked_alloc_id,
config.check_alignment,
),
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
pub use crate::range_map::RangeMap;
pub use crate::stacked_borrows::{
EvalContextExt as StackedBorEvalContextExt, Item, Permission, PtrId, Stack, Stacks, Tag,
EvalContextExt as StackedBorEvalContextExt, Item, Permission, CallId, PtrId, Stack, Stacks, Tag,
};
pub use crate::thread::{
EvalContextExt as ThreadsEvalContextExt, SchedulingAction, ThreadId, ThreadManager, ThreadState,
Expand Down
3 changes: 2 additions & 1 deletion src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ impl MemoryExtra {
rng: StdRng,
stacked_borrows: bool,
tracked_pointer_tag: Option<PtrId>,
tracked_call_id: Option<CallId>,
tracked_alloc_id: Option<AllocId>,
check_alignment: bool,
) -> Self {
let stacked_borrows = if stacked_borrows {
Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(tracked_pointer_tag))))
Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(tracked_pointer_tag, tracked_call_id))))
} else {
None
};
Expand Down
12 changes: 9 additions & 3 deletions src/stacked_borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,10 @@ pub struct GlobalState {
next_call_id: CallId,
/// Those call IDs corresponding to functions that are still running.
active_calls: FxHashSet<CallId>,
/// The id to trace in this execution run
/// The pointer id to trace
tracked_pointer_tag: Option<PtrId>,
/// The call id to trace
tracked_call_id: Option<CallId>,
}
/// Memory extra state gives us interior mutable access to the global state.
pub type MemoryExtra = Rc<RefCell<GlobalState>>;
Expand Down Expand Up @@ -153,13 +155,14 @@ impl fmt::Display for RefKind {

/// Utilities for initialization and ID generation
impl GlobalState {
pub fn new(tracked_pointer_tag: Option<PtrId>) -> Self {
pub fn new(tracked_pointer_tag: Option<PtrId>, tracked_call_id: Option<CallId>) -> Self {
GlobalState {
next_ptr_id: NonZeroU64::new(1).unwrap(),
base_ptr_ids: FxHashMap::default(),
next_call_id: NonZeroU64::new(1).unwrap(),
active_calls: FxHashSet::default(),
tracked_pointer_tag,
tracked_call_id,
}
}

Expand All @@ -172,6 +175,9 @@ impl GlobalState {
pub fn new_call(&mut self) -> CallId {
let id = self.next_call_id;
trace!("new_call: Assigning ID {}", id);
if Some(id) == self.tracked_call_id {
register_diagnostic(NonHaltingDiagnostic::CreatedCallId(id));
}
assert!(self.active_calls.insert(id));
self.next_call_id = NonZeroU64::new(id.get() + 1).unwrap();
id
Expand Down Expand Up @@ -277,7 +283,7 @@ impl<'tcx> Stack {
fn check_protector(item: &Item, tag: Option<Tag>, global: &GlobalState) -> InterpResult<'tcx> {
if let Tag::Tagged(id) = item.tag {
if Some(id) == global.tracked_pointer_tag {
register_diagnostic(NonHaltingDiagnostic::PoppedTrackedPointerTag(item.clone()));
register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(item.clone()));
}
}
if let Some(call) = item.protector {
Expand Down

0 comments on commit e7ef64f

Please sign in to comment.