Skip to content

Commit cbc7f94

Browse files
committed
Add a flag to disable leak backtraces
1 parent 606ca4d commit cbc7f94

9 files changed

+52
-9
lines changed

src/tools/miri/README.md

+9-5
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,22 @@ environment variable. We first document the most relevant and most commonly used
301301
* `-Zmiri-disable-isolation` disables host isolation. As a consequence,
302302
the program has access to host resources such as environment variables, file
303303
systems, and randomness.
304+
* `-Zmiri-disable-leak-backtraces` disables backtraces reports for memory leaks. By default, a
305+
backtrace is captured for every allocation when it is created, just in case it leaks. This incurs
306+
some memory overhead to store data that is almost never used. This flag is implied by
307+
`-Zmiri-ignore-leaks`.
308+
* `-Zmiri-env-forward=<var>` forwards the `var` environment variable to the interpreted program. Can
309+
be used multiple times to forward several variables. Execution will still be deterministic if the
310+
value of forwarded variables stays the same. Has no effect if `-Zmiri-disable-isolation` is set.
311+
* `-Zmiri-ignore-leaks` disables the memory leak checker, and also allows some
312+
remaining threads to exist when the main thread exits.
304313
* `-Zmiri-isolation-error=<action>` configures Miri's response to operations
305314
requiring host access while isolation is enabled. `abort`, `hide`, `warn`,
306315
and `warn-nobacktrace` are the supported actions. The default is to `abort`,
307316
which halts the machine. Some (but not all) operations also support continuing
308317
execution with a "permission denied" error being returned to the program.
309318
`warn` prints a full backtrace when that happens; `warn-nobacktrace` is less
310319
verbose. `hide` hides the warning entirely.
311-
* `-Zmiri-env-forward=<var>` forwards the `var` environment variable to the interpreted program. Can
312-
be used multiple times to forward several variables. Execution will still be deterministic if the
313-
value of forwarded variables stays the same. Has no effect if `-Zmiri-disable-isolation` is set.
314-
* `-Zmiri-ignore-leaks` disables the memory leak checker, and also allows some
315-
remaining threads to exist when the main thread exits.
316320
* `-Zmiri-num-cpus` states the number of available CPUs to be reported by miri. By default, the
317321
number of available CPUs is `1`. Note that this flag does not affect how miri handles threads in
318322
any way.

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

+3
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ fn main() {
359359
isolation_enabled = Some(false);
360360
}
361361
miri_config.isolated_op = miri::IsolatedOp::Allow;
362+
} else if arg == "-Zmiri-disable-leak-backtraces" {
363+
miri_config.collect_leak_backtraces = false;
362364
} else if arg == "-Zmiri-disable-weak-memory-emulation" {
363365
miri_config.weak_memory_emulation = false;
364366
} else if arg == "-Zmiri-track-weak-memory-loads" {
@@ -385,6 +387,7 @@ fn main() {
385387
};
386388
} else if arg == "-Zmiri-ignore-leaks" {
387389
miri_config.ignore_leaks = true;
390+
miri_config.collect_leak_backtraces = false;
388391
} else if arg == "-Zmiri-panic-on-unsupported" {
389392
miri_config.panic_on_unsupported = true;
390393
} else if arg == "-Zmiri-tag-raw-pointers" {

src/tools/miri/src/eval.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ pub struct MiriConfig {
146146
pub num_cpus: u32,
147147
/// Requires Miri to emulate pages of a certain size
148148
pub page_size: Option<u64>,
149+
/// Whether to collect a backtrace when each allocation is created, just in case it leaks.
150+
pub collect_leak_backtraces: bool,
149151
}
150152

151153
impl Default for MiriConfig {
@@ -180,6 +182,7 @@ impl Default for MiriConfig {
180182
gc_interval: 10_000,
181183
num_cpus: 1,
182184
page_size: None,
185+
collect_leak_backtraces: true,
183186
}
184187
}
185188
}
@@ -461,9 +464,14 @@ pub fn eval_entry<'tcx>(
461464
let leaks = ecx.find_leaked_allocations(&ecx.machine.static_roots);
462465
if !leaks.is_empty() {
463466
report_leaks(&ecx, leaks);
464-
tcx.sess.note_without_error(
465-
"the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check",
466-
);
467+
let leak_message = "the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check";
468+
if ecx.machine.collect_leak_backtraces {
469+
// If we are collecting leak backtraces, each leak is a distinct error diagnostic.
470+
tcx.sess.note_without_error(leak_message);
471+
} else {
472+
// If we do not have backtraces, we just report an error without any span.
473+
tcx.sess.err(leak_message);
474+
};
467475
// Ignore the provided return code - let the reported error
468476
// determine the return code.
469477
return None;

src/tools/miri/src/machine.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,17 @@ pub struct MiriMachine<'mir, 'tcx> {
471471
pub(crate) gc_interval: u32,
472472
/// The number of blocks that passed since the last BorTag GC pass.
473473
pub(crate) since_gc: u32,
474+
474475
/// The number of CPUs to be reported by miri.
475476
pub(crate) num_cpus: u32,
477+
476478
/// Determines Miri's page size and associated values
477479
pub(crate) page_size: u64,
478480
pub(crate) stack_addr: u64,
479481
pub(crate) stack_size: u64,
482+
483+
/// Whether to collect a backtrace when each allocation is created, just in case it leaks.
484+
pub(crate) collect_leak_backtraces: bool,
480485
}
481486

482487
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
@@ -585,6 +590,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
585590
page_size,
586591
stack_addr,
587592
stack_size,
593+
collect_leak_backtraces: config.collect_leak_backtraces,
588594
}
589595
}
590596

@@ -732,6 +738,7 @@ impl VisitTags for MiriMachine<'_, '_> {
732738
page_size: _,
733739
stack_addr: _,
734740
stack_size: _,
741+
collect_leak_backtraces: _,
735742
} = self;
736743

737744
threads.visit_tags(visit);
@@ -975,7 +982,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
975982
// If an allocation is leaked, we want to report a backtrace to indicate where it was
976983
// allocated. We don't need to record a backtrace for allocations which are allowed to
977984
// leak.
978-
let backtrace = if kind.may_leak() { None } else { Some(ecx.generate_stacktrace()) };
985+
let backtrace = if kind.may_leak() || !ecx.machine.collect_leak_backtraces {
986+
None
987+
} else {
988+
Some(ecx.generate_stacktrace())
989+
};
979990

980991
let alloc: Allocation<Provenance, Self::AllocExtra> = alloc.adjust_from_tcx(
981992
&ecx.tcx,

src/tools/miri/tests/fail/memleak.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ note: inside `main`
1515
LL | std::mem::forget(Box::new(42));
1616
| ^^^^^^^^^^^^
1717

18+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
19+
1820
note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check
1921

2022
error: aborting due to previous error
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//@compile-flags: -Zmiri-disable-leak-backtraces
2+
//@error-pattern: the evaluated program leaked memory
3+
//@normalize-stderr-test: ".*│.*" -> "$$stripped$$"
4+
5+
fn main() {
6+
std::mem::forget(Box::new(42));
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check
2+
3+
error: aborting due to previous error
4+

src/tools/miri/tests/fail/memleak_rc.32bit.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ note: inside `main`
1616
LL | let x = Dummy(Rc::new(RefCell::new(None)));
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

19+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
20+
1921
note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check
2022

2123
error: aborting due to previous error

src/tools/miri/tests/fail/memleak_rc.64bit.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ note: inside `main`
1616
LL | let x = Dummy(Rc::new(RefCell::new(None)));
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

19+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
20+
1921
note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check
2022

2123
error: aborting due to previous error

0 commit comments

Comments
 (0)