Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for infallible allocation #586

Merged
merged 3 commits into from
Dec 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 24 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ things (like adding support for a new intrinsic) can be done by working just on
the miri side.

To prepare, make sure you are using a nightly Rust compiler. You also need to
set up a libstd that enables execution with miri:
set up a libstd that enables execution with Miri:

```sh
rustup override set nightly # or the nightly in `rust-version`
cargo run --bin cargo-miri -- miri setup
```

The last command should end in printing the directory where the libstd was
built. Set that as your MIRI_SYSROOT environment variable:
built. Set that as your `MIRI_SYSROOT` environment variable:

```sh
export MIRI_SYSROOT=~/.cache/miri/HOST # or whatever the previous command said
Expand All @@ -109,7 +109,7 @@ export MIRI_SYSROOT=~/.cache/miri/HOST # or whatever the previous command said
Now you can run Miri directly, without going through `cargo miri`:

```sh
cargo run tests/run-pass-fullmir/format.rs # or whatever test you like
cargo run tests/run-pass/format.rs # or whatever test you like
```

You can also run the test suite with `cargo test --release`. `cargo test
Expand All @@ -120,14 +120,33 @@ less time.

Now you are set up! You can write a failing test case, and tweak miri until it
fails no more.
You can get a trace of which MIR statements are being executed by setting the
`MIRI_LOG` environment variable. For example:

```sh
MIRI_LOG=info cargo run tests/run-pass/vecs.rs
```

Setting `MIRI_LOG` like this will configure logging for miri itself as well as
the `rustc::mir::interpret` and `rustc_mir::interpret` modules in rustc. You
can also do more targeted configuration, e.g. to debug the stacked borrows
implementation:
```sh
MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows cargo run tests/run-pass/vecs.rs
```

In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
evaluation error was originally created.


### Using a locally built rustc

Since the heart of Miri (the main interpreter engine) lives in rustc, working on
Miri will often require using a locally built rustc. The bug you want to fix
may actually be on the rustc side, or you just need to get more detailed trace
of the execution -- in both cases, you should develop miri against a rustc you
compiled yourself, with debug assertions (and hence tracing) enabled.
of the execution than what is possible with release builds -- in both cases, you
should develop miri against a rustc you compiled yourself, with debug assertions
(and hence tracing) enabled.

The setup for a local rustc works as follows:
```sh
Expand All @@ -149,22 +168,6 @@ rustup override set custom
With this, you should now have a working development setup! See
["Testing Miri"](#testing-miri) above for how to proceed.

Moreover, you can now run Miri with a trace of all execution steps:
```sh
MIRI_LOG=debug cargo run tests/run-pass/vecs.rs
```

Setting `MIRI_LOG` like this will configure logging for miri itself as well as
the `rustc::mir::interpret` and `rustc_mir::interpret` modules in rustc. You
can also do more targeted configuration, e.g. to debug the stacked borrows
implementation:
```sh
MIRI_LOG=rustc_mir::interpret=debug,miri::stacked_borrows cargo run tests/run-pass/vecs.rs
```

In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
evaluation error was originally created.

### Miri `-Z` flags and environment variables

Several `-Z` flags are relevant for Miri:
Expand Down
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2018-12-22
nightly-2018-12-24
8 changes: 4 additions & 4 deletions src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
this.write_null(dest)?;
} else {
let align = this.tcx.data_layout.pointer_align.abi;
let ptr = this.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into())?;
let ptr = this.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into());
this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?;
}
}
Expand Down Expand Up @@ -114,7 +114,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Rust.into()
)?
)
.with_default_tag();
this.write_scalar(Scalar::Ptr(ptr), dest)?;
}
Expand All @@ -132,7 +132,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Rust.into()
)?
)
.with_default_tag();
this.memory_mut()
.get_mut(ptr.alloc_id)?
Expand Down Expand Up @@ -358,7 +358,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
Size::from_bytes((value.len() + 1) as u64),
Align::from_bytes(1).unwrap(),
MiriMemoryKind::Env.into(),
)?.with_default_tag();
).with_default_tag();
{
let alloc = this.memory_mut().get_mut(value_copy.alloc_id)?;
alloc.write_bytes(tcx, value_copy, &value)?;
Expand Down
16 changes: 8 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(

// Return value (in static memory so that it does not count as leak)
let ret = ecx.layout_of(start_mir.return_ty())?;
let ret_ptr = ecx.allocate(ret, MiriMemoryKind::MutStatic.into())?;
let ret_ptr = ecx.allocate(ret, MiriMemoryKind::MutStatic.into());

// Push our stack frame
ecx.push_stack_frame(
Expand All @@ -125,7 +125,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
ecx.write_scalar(argc, dest)?;
// Store argc for macOS _NSGetArgc
{
let argc_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?;
let argc_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into());
ecx.write_scalar(argc, argc_place.into())?;
ecx.machine.argc = Some(argc_place.ptr.to_ptr()?);
}
Expand All @@ -136,14 +136,14 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
let cmd = ecx.memory_mut().allocate_static_bytes(CMD.as_bytes()).with_default_tag();
let raw_str_layout = ecx.layout_of(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8))?;
let cmd_place = ecx.allocate(raw_str_layout, MiriMemoryKind::Env.into())?;
let cmd_place = ecx.allocate(raw_str_layout, MiriMemoryKind::Env.into());
ecx.write_scalar(Scalar::Ptr(cmd), cmd_place.into())?;
ecx.memory_mut().mark_immutable(cmd_place.to_ptr()?.alloc_id)?;
// Store argv for macOS _NSGetArgv
{
let argv = cmd_place.ptr;
ecx.write_scalar(argv, dest)?;
let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?;
let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into());
ecx.write_scalar(argv, argv_place.into())?;
ecx.machine.argv = Some(argv_place.ptr.to_ptr()?);
}
Expand All @@ -155,7 +155,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
Size::from_bytes(cmd_utf16.len() as u64 * 2),
Align::from_bytes(2).unwrap(),
MiriMemoryKind::Env.into(),
)?.with_default_tag();
).with_default_tag();
ecx.machine.cmd_line = Some(cmd_ptr);
// store the UTF-16 string
let char_size = Size::from_bytes(2);
Expand Down Expand Up @@ -516,13 +516,13 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
ptr: Pointer,
kind: MemoryKind<Self::MemoryKinds>,
) -> EvalResult<'tcx, Pointer<Borrow>> {
) -> Pointer<Borrow> {
if !ecx.machine.validate {
// No tracking
Ok(ptr.with_default_tag())
ptr.with_default_tag()
} else {
let tag = ecx.tag_new_allocation(ptr.alloc_id, kind);
Ok(Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag))
Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag)
}
}

Expand Down