Skip to content

Commit c72af45

Browse files
committed
Auto merge of #1209 - RalfJung:track-alloc-id, r=oli-obk
Add option to print when an AllocId gets created r? @oli-obk
2 parents af451e2 + ade4c4e commit c72af45

File tree

7 files changed

+53
-33
lines changed

7 files changed

+53
-33
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ Several `-Z` flags are relevant for Miri:
180180
is popped from a borrow stack (which is where the tag becomes invalid and any
181181
future use of it will error). This helps you in finding out why UB is
182182
happening and where in your code would be a good place to look for it.
183+
* `-Zmiri-track-alloc-id=<id>` shows a backtrace when the given allocation is
184+
being allocated. This helps in debugging memory leaks.
183185

184186
Moreover, Miri recognizes some environment variables:
185187

benches/helpers/miri_helper.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls<'_> {
2929
tcx.entry_fn(LOCAL_CRATE).expect("no main or start function found");
3030

3131
self.bencher.iter(|| {
32-
let config = miri::MiriConfig {
33-
validate: true,
34-
stacked_borrows: true,
35-
communicate: false,
36-
ignore_leaks: false,
37-
excluded_env_vars: vec![],
38-
args: vec![],
39-
seed: None,
40-
tracked_pointer_tag: None,
41-
};
32+
let config = miri::MiriConfig::default();
4233
eval_main(tcx, entry_def_id, config);
4334
});
4435
});

src/bin/miri-rustc-tests.rs

+2-20
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
4646
.iter()
4747
.any(|attr| attr.check_name(rustc_span::symbol::sym::test))
4848
{
49-
let config = MiriConfig {
50-
validate: true,
51-
stacked_borrows: true,
52-
communicate: false,
53-
ignore_leaks: false,
54-
excluded_env_vars: vec![],
55-
args: vec![],
56-
seed: None,
57-
tracked_pointer_tag: None,
58-
};
49+
let config = MiriConfig::default();
5950
let did = self.0.hir().body_owner_def_id(body_id);
6051
println!("running test: {}", self.0.def_path_debug_str(did));
6152
miri::eval_main(self.0, did, config);
@@ -68,16 +59,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
6859
}
6960
tcx.hir().krate().visit_all_item_likes(&mut Visitor(tcx));
7061
} else if let Some((entry_def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
71-
let config = MiriConfig {
72-
validate: true,
73-
stacked_borrows: true,
74-
communicate: false,
75-
ignore_leaks: false,
76-
excluded_env_vars: vec![],
77-
args: vec![],
78-
seed: None,
79-
tracked_pointer_tag: None,
80-
};
62+
let config = MiriConfig::default();
8163
miri::eval_main(tcx, entry_def_id, config);
8264

8365
compiler.session().abort_if_errors();

src/bin/miri.rs

+13
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ fn main() {
135135
let mut ignore_leaks = false;
136136
let mut seed: Option<u64> = None;
137137
let mut tracked_pointer_tag: Option<miri::PtrId> = None;
138+
let mut tracked_alloc_id: Option<miri::AllocId> = None;
138139
let mut rustc_args = vec![];
139140
let mut miri_args = vec![];
140141
let mut after_dashdash = false;
@@ -206,6 +207,17 @@ fn main() {
206207
panic!("-Zmiri-track-pointer-tag must be a nonzero id");
207208
}
208209
}
210+
arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
211+
let id: u64 = match arg.trim_start_matches("-Zmiri-track-alloc-id=").parse()
212+
{
213+
Ok(id) => id,
214+
Err(err) => panic!(
215+
"-Zmiri-track-alloc-id requires a valid `u64` as the argument: {}",
216+
err
217+
),
218+
};
219+
tracked_alloc_id = Some(miri::AllocId(id));
220+
}
209221
_ => {
210222
rustc_args.push(arg);
211223
}
@@ -240,6 +252,7 @@ fn main() {
240252
seed,
241253
args: miri_args,
242254
tracked_pointer_tag,
255+
tracked_alloc_id,
243256
};
244257
rustc_driver::install_ice_hook();
245258
let result = rustc_driver::catch_fatal_errors(move || {

src/diagnostics.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::*;
66
/// Miri specific diagnostics
77
pub enum NonHaltingDiagnostic {
88
PoppedTrackedPointerTag(Item),
9+
CreatedAlloc(AllocId),
910
}
1011

1112
/// Emit a custom diagnostic without going through the miri-engine machinery
@@ -97,9 +98,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9798
let this = self.eval_context_ref();
9899
DIAGNOSTICS.with(|diagnostics| {
99100
for e in diagnostics.borrow_mut().drain(..) {
101+
use NonHaltingDiagnostic::*;
100102
let msg = match e {
101-
NonHaltingDiagnostic::PoppedTrackedPointerTag(item) =>
103+
PoppedTrackedPointerTag(item) =>
102104
format!("popped tracked tag for item {:?}", item),
105+
CreatedAlloc(AllocId(id)) =>
106+
format!("created allocation with id {}", id),
103107
};
104108
report_msg(this, msg, false);
105109
}

src/eval.rs

+19
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,24 @@ pub struct MiriConfig {
3030
pub seed: Option<u64>,
3131
/// The stacked borrow id to report about
3232
pub tracked_pointer_tag: Option<PtrId>,
33+
/// The allocation id to report about.
34+
pub tracked_alloc_id: Option<AllocId>,
35+
}
36+
37+
impl Default for MiriConfig {
38+
fn default() -> MiriConfig {
39+
MiriConfig {
40+
validate: true,
41+
stacked_borrows: true,
42+
communicate: false,
43+
ignore_leaks: false,
44+
excluded_env_vars: vec![],
45+
args: vec![],
46+
seed: None,
47+
tracked_pointer_tag: None,
48+
tracked_alloc_id: None,
49+
}
50+
}
3351
}
3452

3553
/// Details of premature program termination.
@@ -55,6 +73,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
5573
StdRng::seed_from_u64(config.seed.unwrap_or(0)),
5674
config.stacked_borrows,
5775
config.tracked_pointer_tag,
76+
config.tracked_alloc_id,
5877
),
5978
);
6079
// Complete initialization.

src/machine.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,19 @@ pub struct MemoryExtra {
7575
pub intptrcast: intptrcast::MemoryExtra,
7676

7777
/// Mapping extern static names to their canonical allocation.
78-
pub(crate) extern_statics: FxHashMap<Symbol, AllocId>,
78+
extern_statics: FxHashMap<Symbol, AllocId>,
7979

8080
/// The random number generator used for resolving non-determinism.
8181
/// Needs to be queried by ptr_to_int, hence needs interior mutability.
8282
pub(crate) rng: RefCell<StdRng>,
83+
84+
/// An allocation ID to report when it is being allocated
85+
/// (helps for debugging memory leaks).
86+
tracked_alloc_id: Option<AllocId>,
8387
}
8488

8589
impl MemoryExtra {
86-
pub fn new(rng: StdRng, stacked_borrows: bool, tracked_pointer_tag: Option<PtrId>) -> Self {
90+
pub fn new(rng: StdRng, stacked_borrows: bool, tracked_pointer_tag: Option<PtrId>, tracked_alloc_id: Option<AllocId>) -> Self {
8791
let stacked_borrows = if stacked_borrows {
8892
Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(tracked_pointer_tag))))
8993
} else {
@@ -94,6 +98,7 @@ impl MemoryExtra {
9498
intptrcast: Default::default(),
9599
extern_statics: FxHashMap::default(),
96100
rng: RefCell::new(rng),
101+
tracked_alloc_id,
97102
}
98103
}
99104

@@ -329,6 +334,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
329334
alloc: Cow<'b, Allocation>,
330335
kind: Option<MemoryKind<Self::MemoryKinds>>,
331336
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
337+
if Some(id) == memory_extra.tracked_alloc_id {
338+
register_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id));
339+
}
340+
332341
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
333342
let alloc = alloc.into_owned();
334343
let (stacks, base_tag) =

0 commit comments

Comments
 (0)