]> git.lizzy.rs Git - rust.git/blobdiff - README.md
Merge pull request #766 from RalfJung/sysroot
[rust.git] / README.md
index 5e5a7a23c6afe04441ab31b0b6d343c2b293d8fa..090694128e3ae047ead08649b0381d86f38bf524 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Miri [![Build Status](https://travis-ci.org/solson/miri.svg?branch=master)](https://travis-ci.org/solson/miri) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/solson/miri?svg=true)](https://ci.appveyor.com/project/solson63299/miri)
+# Miri [![Build Status](https://travis-ci.com/rust-lang/miri.svg?branch=master)](https://travis-ci.com/rust-lang/miri) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang/miri?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/miri)
 
 
 An experimental interpreter for [Rust][rust]'s
@@ -15,187 +15,258 @@ for example:
   or an invalid enum discriminant)
 * WIP: Violations of the rules governing aliasing for reference types
 
+Miri has already discovered some [real-world bugs](#bugs-found-by-miri).  If you
+found a bug with Miri, we'd appreciate if you tell us and we'll add it to the
+list!
+
+Be aware that Miri will not catch all possible errors in your program, and
+cannot run all programs:
+
+* There are still plenty of open questions around the basic invariants for some
+  types and when these invariants even have to hold. Miri tries to avoid false
+  positives here, so if you program runs fine in Miri right now that is by no
+  means a guarantee that it is UB-free when these questions get answered. In
+  particular, Miri does currently not check that integers are initialized or
+  that references point to valid data.
+* If the program relies on unspecified details of how data is laid out, it will
+  still run fine in Miri -- but might break (including causing UB) on different
+  compiler versions or different platforms.
+* Miri is fully deterministic and does not actually pick a base address in
+  virtual memory for the program's allocations.  If program behavior depends on
+  the base address of an allocation, Miri will stop execution (with a few
+  exceptions to make some common pointer comparisons work).
+* Miri runs the program as a platform-independent interpreter, so the program
+  has no access to any platform-specific APIs or FFI. A few APIs have been
+  implemented (such as printing to stdout) but most have not: for example, Miri
+  currently does not support concurrency, or networking, or file system access,
+  or gathering entropy from the system.
+
 [rust]: https://www.rust-lang.org/
 [mir]: https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md
 [`unreachable_unchecked`]: https://doc.rust-lang.org/stable/std/hint/fn.unreachable_unchecked.html
 [`copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapping.html
 
-## Building Miri
 
-We recommend that you install [rustup] to obtain Rust. Then all you have
-to do is:
+## Running Miri on your own project (and its test suite)
+
+Install Miri via `rustup`:
 
 ```sh
-cargo +nightly build
+rustup component add miri
 ```
 
-This uses the very latest Rust version.  If you experience any problem, refer to
-the `rust-version` file which contains a particular Rust nightly version that
-has been tested against the version of miri you are using.  Make sure to use
-that particular `nightly-YYYY-MM-DD` whenever the instructions just say
-`nightly`.
+If `rustup` says the `miri` component is unavailable, that's because not all nightly releases come with all tools. Check out [this website](https://rust-lang.github.io/rustup-components-history) to determine a nightly version that comes with Miri and install that, e.g. using `rustup install nightly-2019-03-28`.
+
+Now you can run your project in Miri:
+
+1. Run `cargo clean` to eliminate any cached dependencies.  Miri needs your
+   dependencies to be compiled the right way, that would not happen if they have
+   previously already been compiled.
+2. To run all tests in your project through Miri, use `cargo miri test`.
+3. If you have a binary project, you can run it through Miri using `cargo miri run`.
+
+The first time you run Miri, it will perform some extra setup and install some
+dependencies.  It will ask you for confirmation before installing anything.  If
+you run Miri on CI, run `cargo miri setup` to avoid getting interactive
+questions.
+
+You can pass arguments to Miri after the first `--`, and pass arguments to the
+interpreted program or test suite after the second `--`.  For example, `cargo
+miri run -- -Zmiri-disable-validation` runs the program without validation of
+basic type invariants and references.  `cargo miri test -- -- -Zunstable-options
+--exclude-should-panic` skips `#[should_panic]` tests, which is a good idea
+because Miri does not support unwinding or catching panics.
+
+When running code via `cargo miri`, the `miri` config flag is set.  You can
+use this to exclude test cases that will fail under Miri because they do things
+Miri does not support:
+
+```rust
+#[cfg(not(miri))]
+#[test]
+fn does_not_work_on_miri() {
+    let x = 0u8;
+    assert!(&x as *const _ as usize % 4 < 4);
+}
+```
 
-To avoid repeating the nightly version all the time, you can use
-`rustup override set nightly` (or `rustup override set nightly-YYYY-MM-DD`),
-which means `nightly` Rust will automatically be used whenever you are working
-in this directory.
+### Common Problems
 
-[rustup]: https://www.rustup.rs
+When using the above instructions, you may encounter a number of confusing compiler
+errors.
 
-## Running Miri
+#### "found possibly newer version of crate `std` which `<dependency>` depends on"
 
-```sh
-cargo +nightly run -- -Zmiri-disable-validation tests/run-pass/vecs.rs # Or whatever test you like.
-```
+Your build directory may contain artifacts from an earlier build that have/have
+not been built for Miri. Run `cargo clean` before switching from non-Miri to
+Miri builds and vice-versa.
 
-We have to disable validation because that can lead to errors when libstd is not
-compiled the right way.
+#### "found crate `std` compiled by an incompatible version of rustc"
 
-## Running Miri with full libstd
+You may be running `cargo miri` with a different compiler version than the one
+used to build the custom libstd that Miri uses, and Miri failed to detect that.
+Try deleting `~/.cache/miri`.
 
-Per default libstd does not contain the MIR of non-polymorphic functions, and
-also does not contain some extra MIR statements that miri needs for validation.
-When Miri hits a call to such a function, execution terminates, and even when
-the MIR is present, validation can fail.  To fix this, it is possible to compile
-libstd with full MIR:
+#### "no mir for `std::rt::lang_start_internal`"
 
-```sh
-rustup component add --toolchain nightly rust-src
-cargo +nightly install xargo
-rustup run nightly xargo/build.sh
-```
+This means the sysroot you are using was not compiled with Miri in mind.  This
+should never happen when you use `cargo miri` because that takes care of setting
+up the sysroot.  If you are using `miri` (the Miri driver) directly, see
+[below][testing-miri] for how to set up the sysroot.
+
+## Development and Debugging
+
+If you want to hack on miri yourself, great!  Here are some resources you might
+find useful.
+
+### Using a nightly rustc
 
-Now you can run Miri against the libstd compiled by xargo:
+Miri heavily relies on internal rustc interfaces to execute MIR.  Still, some
+things (like adding support for a new intrinsic or a shim for an external
+function being called) can be done by working just on the Miri side.
+
+To prepare, make sure you are using a nightly Rust compiler.  Then you should be
+able to just `cargo build` Miri.
+
+In case this fails, your nightly might be incompatible with Miri master.  The
+`rust-version` file contains the commit hash of rustc that Miri is currently
+tested against; you can use that to find a nightly that works or you might have
+to wait for the next nightly to get released.
+
+### Testing the Miri driver
+[testing-miri]: #testing-the-miri-driver
+
+The Miri driver in the `miri` binary is the "heart" of Miri: it is basically a
+version of `rustc` that, instead of compiling your code, runs it.  It accepts
+all the same flags as `rustc` (though the ones only affecting code generation
+and linking obviously will have no effect) [and more][miri-flags].
+
+Running the Miri driver requires some fiddling with environment variables, so
+the `miri` script helps you do that.  For example, you can run the driver on a
+particular file by doing
 
 ```sh
-MIRI_SYSROOT=~/.xargo/HOST cargo +nightly run tests/run-pass-fullmir/hashmap.rs
+./miri run tests/run-pass/format.rs
+./miri run tests/run-pass/hello.rs --target i686-unknown-linux-gnu
 ```
 
-Notice that you will have to re-run the last step of the preparations above
-(`xargo/build.sh`) when your toolchain changes (e.g., when you update the
-nightly).
-
-## Running Miri on your own project('s test suite)
-
-Install Miri as a cargo subcommand with `cargo +nightly install --all-features
---path .`.  Be aware that if you used `rustup override set` to fix a particular
-Rust version for the miri directory, that will *not* apply to your own project
-directory!  You have to use a consistent Rust version for building miri and your
-project for this to work, so remember to either always specify the nightly
-version manually, overriding it in your project directory as well, or use
-`rustup default nightly` (or `rustup default nightly-YYYY-MM-DD`) to globally
-make `nightly` the default toolchain.
-
-We assume that you have prepared a MIR-enabled libstd as described above.  Now
-compile your project and its dependencies against that libstd:
-
-1. Run `cargo clean` to eliminate any cached dependencies that were built against
-the non-MIR `libstd`.
-2. To run all tests in your project through, Miri, use
-`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri test`. **NOTE**: This is
-currently broken, see the discussion in
-[#479](https://github.com/solson/miri/issues/479).
-3. If you have a binary project, you can run it through Miri using
-`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri`.
+and you can run the test suite using:
 
-### Common Problems
+```
+./miri test
+```
 
-When using the above instructions, you may encounter a number of confusing compiler
-errors.
+`./miri test FILTER` only runs those tests that contain `FILTER` in their
+filename (including the base directory, e.g. `./miri test fail` will run all
+compile-fail tests).
 
-#### "constant evaluation error: no mir for `<function>`"
+You can get a trace of which MIR statements are being executed by setting the
+`MIRI_LOG` environment variable.  For example:
 
-You may have forgotten to set `MIRI_SYSROOT` when calling `cargo miri`, and
-your program called into `std` or `core`. Be sure to set `MIRI_SYSROOT=~/.xargo/HOST`.
+```sh
+MIRI_LOG=info ./miri run tests/run-pass/vecs.rs
+```
 
-#### "found possibly newer version of crate `std` which `<dependency>` depends on"
+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. the following helps debug the
+stacked borrows implementation:
 
-Your build directory may contain artifacts from an earlier build that did/did not
-have `MIRI_SYSROOT` set. Run `cargo clean` before switching from non-Miri to Miri
-builds and vice-versa.
+```sh
+MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows ./miri run tests/run-pass/vecs.rs
+```
 
-#### "found crate `std` compiled by an incompatible version of rustc"
+In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
+evaluation error was originally raised.
 
-You may be running `cargo miri` with a different compiler version than the one
-used to build the MIR-enabled `std`. Be sure to consistently use the same toolchain,
-which should be the toolchain specified in the `rust-version` file.
+### Testing `cargo miri`
 
-## Miri `-Z` flags
+Working with the driver directly gives you full control, but you also lose all
+the convenience provided by cargo.  Once your test case depends on a crate, it
+is probably easier to test it with the cargo wrapper.  You can install your
+development version of Miri using
 
-Several `-Z` flags are relevant for miri:
+```
+./miri install
+```
 
-* `-Zmir-opt-level` controls how many MIR optimizations are performed.  miri
-  overrides the default to be `0`; be advised that using any higher level can
-  make miri miss bugs in your program because they got optimized away.
-* `-Zalways-encode-mir` makes rustc dump MIR even for completely monomorphic
-  functions.  This is needed so that miri can execute such functions, so miri
-  sets this flag per default.
-* `-Zmiri-disable-validation` is a custom `-Z` flag added by miri.  It disables
-  enforcing the validity invariant, which is enforced by default.  This is
-  mostly useful for debugging; it means miri will miss bugs in your program.
+and then you can use it as if it was installed by `rustup`.  Make sure you use
+the same toolchain when calling `cargo miri` that you used when installing Miri!
 
-## Development and Debugging
+There's a test for the cargo wrapper in the `test-cargo-miri` directory; run
+`./run-test.py` in there to execute it.
+
+### 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. This includes getting a
-trace of the execution, as distributed rustc has `debug!` and `trace!` disabled.
+A big part of the Miri driver lives in rustc, so working on Miri will sometimes
+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
+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 first-time setup for a local rustc looks as follows:
+The setup for a local rustc works as follows:
 ```sh
 git clone https://github.com/rust-lang/rust/ rustc
 cd rustc
 cp config.toml.example config.toml
 # Now edit `config.toml` and set `debug-assertions = true` and `test-miri = true`.
 # The latter is important to build libstd with the right flags for miri.
+# This step can take 30 minutes and more.
 ./x.py build src/rustc
+# If you change something, you can get a faster rebuild by doing
+./x.py --keep-stage 0 build src/rustc
 # You may have to change the architecture in the next command
 rustup toolchain link custom build/x86_64-unknown-linux-gnu/stage2
-# Now cd to your Miri directory
+# Now cd to your Miri directory, then configure rustup
 rustup override set custom
 ```
-The `build` step can take 30 minutes and more.
-
-Now you can `cargo build` Miri, and you can `cargo test --release` it.  `cargo
-test --release FILTER` only runs those tests that contain `FILTER` in their
-filename (including the base directory, e.g. `cargo test --release fail` will
-run all compile-fail tests).  We recommend using `--release` to make test
-running take less time.
-
-Notice that the "fullmir" tests only run if you have `MIRI_SYSROOT` set, the
-test runner does not realized that your libstd comes with full MIR.  The
-following will set it correctly:
-```sh
-MIRI_SYSROOT=$(rustc --print sysroot) cargo test --release
-```
-
-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
-```
+With this, you should now have a working development setup!  See
+[above][testing-miri] for how to proceed working with the Miri driver.
+
+### Miri `-Z` flags and environment variables
+[miri-flags]: #miri--z-flags-and-environment-variables
+
+Several `-Z` flags are relevant for Miri:
+
+* `-Zmiri-seed=<hex>` is a custom `-Z` flag added by Miri.  It enables the
+  interpreted program to seed an RNG with system entropy.  Miri will keep an RNG
+  on its own that is seeded with the given seed, and use that to generate the
+  "system entropy" that seeds the RNG(s) in the interpreted program.
+  **NOTE**: This entropy is not good enough for cryptographic use!  Do not
+  generate secret keys in Miri or perform other kinds of cryptographic
+  operations that rely on proper random numbers.
+* `-Zmiri-disable-validation` disables enforcing the validity invariant, which
+  is enforced by default.  This is mostly useful for debugging; it means Miri
+  will miss bugs in your program.  However, this can also help to make Miri run
+  faster.
+* `-Zmir-opt-level` controls how many MIR optimizations are performed.  Miri
+  overrides the default to be `0`; be advised that using any higher level can
+  make Miri miss bugs in your program because they got optimized away.
+* `-Zalways-encode-mir` makes rustc dump MIR even for completely monomorphic
+  functions.  This is needed so that Miri can execute such functions, so Miri
+  sets this flag per default.
 
-In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
-evaluation error was originally created.
+Moreover, Miri recognizes some environment variables:
 
-If you changed something in rustc and want to re-build, run
-```
-./x.py --keep-stage 0 build src/rustc
-```
-This avoids rebuilding the entire stage 0, which can save a lot of time.
+* `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during
+  Miri executions, also [see above][testing-miri].
+* `MIRI_SYSROOT` (recognized by `cargo miri` and the test suite)
+  indicates the sysroot to use.  To do the same thing with `miri`
+  directly, use the `--sysroot` flag.
+* `MIRI_TEST_TARGET` (recognized by the test suite) indicates which target
+  architecture to test against.  `miri` and `cargo miri` accept the `--target`
+  flag for the same purpose.
 
 ## Contributing and getting help
 
 Check out the issues on this GitHub repository for some ideas. There's lots that
 needs to be done that I haven't documented in the issues yet, however. For more
-ideas or help with running or hacking on Miri, you can contact me (`scott`) on
-Mozilla IRC in any of the Rust IRC channels (`#rust`, `#rust-offtopic`, etc).
+ideas or help with running or hacking on Miri, you can open an issue here on
+GitHub or contact us (`oli-obk` and `RalfJ`) on the [Rust Zulip].
+
+[Rust Zulip]: https://rust-lang.zulipchat.com
 
 ## History
 
@@ -217,6 +288,27 @@ used according to their aliasing restrictions.
 [slides]: https://solson.me/miri-slides.pdf
 [report]: https://solson.me/miri-report.pdf
 
+## Bugs found by Miri
+
+Miri has already found a number of bugs in the Rust standard library and beyond, which we collect here.
+
+Definite bugs found:
+
+* [`Debug for vec_deque::Iter` accessing uninitialized memory](https://github.com/rust-lang/rust/issues/53566)
+* [`From<&[T]> for Rc` creating a not sufficiently aligned reference](https://github.com/rust-lang/rust/issues/54908)
+* [`BTreeMap` creating a shared reference pointing to a too small allocation](https://github.com/rust-lang/rust/issues/54957)
+* [`Vec::append` creating a dangling reference](https://github.com/rust-lang/rust/pull/61082)
+* [Futures turning a shared reference into a mutable one](https://github.com/rust-lang/rust/pull/56319)
+* [`str` turning a shared reference into a mutable one](https://github.com/rust-lang/rust/pull/58200)
+* [`rand` performing unaligned reads](https://github.com/rust-random/rand/issues/779)
+
+Violations of Stacked Borrows found that are likely bugs (but Stacked Borrows is currently just an experiment):
+
+* [`VecDeque` creating overlapping mutable references](https://github.com/rust-lang/rust/pull/56161)
+* [`BTreeMap` creating mutable references that overlap with shared references](https://github.com/rust-lang/rust/pull/58431)
+* [`LinkedList` creating overlapping mutable references](https://github.com/rust-lang/rust/pull/60072)
+* [`Vec::push` invalidating existing references into the vector](https://github.com/rust-lang/rust/issues/60847)
+
 ## License
 
 Licensed under either of