add a Miri extern fn to mark an allocation as being a static root for leak checking

This commit is contained in:
Ralf Jung 2020-07-23 15:47:33 +02:00
parent 4033358956
commit fef5fa2ae1
3 changed files with 20 additions and 3 deletions

View file

@ -5,6 +5,7 @@ use std::ffi::OsStr;
use rand::rngs::StdRng;
use rand::SeedableRng;
use log::info;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, layout::LayoutCx, TyCtxt};
@ -195,8 +196,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
/// Returns `Some(return_code)` if program executed completed.
/// Returns `None` if an evaluation error occured.
pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) -> Option<i64> {
// FIXME: on Windows, we ignore leaks (https://github.com/rust-lang/miri/issues/1302).
let ignore_leaks = config.ignore_leaks || tcx.sess.target.target.target_os == "windows";
// Copy setting before we move `config`.
let ignore_leaks = config.ignore_leaks;
let (mut ecx, ret_place) = match create_ecx(tcx, main_id, config) {
Ok(v) => v,
@ -244,7 +245,8 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) ->
match res {
Ok(return_code) => {
if !ignore_leaks {
let leaks = ecx.memory.leak_report();
info!("Additonal static roots: {:?}", ecx.machine.static_roots);
let leaks = ecx.memory.leak_report(&ecx.machine.static_roots);
if leaks != 0 {
tcx.sess.err("the evaluated program leaked memory");
// Ignore the provided return code - let the reported error

View file

@ -262,6 +262,9 @@ pub struct Evaluator<'mir, 'tcx> {
/// Precomputed `TyLayout`s for primitive data types that are commonly used inside Miri.
pub(crate) layouts: PrimitiveLayouts<'tcx>,
/// Allocations that are considered roots of static memory (that may leak).
pub(crate) static_roots: Vec<AllocId>,
}
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
@ -289,6 +292,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
time_anchor: Instant::now(),
layouts,
threads: ThreadManager::default(),
static_roots: Vec::new(),
}
}
}

View file

@ -197,6 +197,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Here we dispatch all the shims for foreign functions. If you have a platform specific
// shim, add it to the corresponding submodule.
match link_name {
// Miri-specific extern functions
"miri_static_root" => {
let &[ptr] = check_arg_count(args)?;
let ptr = this.read_scalar(ptr)?.not_undef()?;
let ptr = this.force_ptr(ptr)?;
if ptr.offset != Size::ZERO {
throw_unsup_format!("Pointer passed to miri_static_root must point to beginning of an allocated block");
}
this.machine.static_roots.push(ptr.alloc_id);
}
// Standard C allocation
"malloc" => {
let &[size] = check_arg_count(args)?;