Previously the command line string would have been incorrectly constructed if argv[0] contained a doublequote (`"`) or ended in a trailing backslash (`\`). This is a very rare edge case because, by convention, argv[0] is the path to the application and Windows file names cannot contain doublequotes.
Fixes#1881
add support for `#[start]`
This PR adds support for the `#[start]` attribute and fixes#1825.
It also renames `eval_main` to `eval_entry` to reflect that it can evaluate any entry function.
also ignore 'thread leaks' with -Zmiri-ignore-leaks
This is a step towards https://github.com/rust-lang/miri/issues/1371. The remaining hard part would be supporting checking for memory leaks when there are threads still running. For now we elegantly avoid this problem by using the same flag to control both of these checks. :)
Add support for panicking in the emulated application when unsupported functionality is encountered
This PR fixes#1807 and allows an optional flag to be specified to panic when an unsupported syscall is encountered. In essence, instead of bubbling up an error in the context of the Miri application Miri will panic within the context of the *emulated* application. This feature is desired to allow CI pipelines to determine if a Miri failure is unsupported functionality or actual UB. Please read [this comment](https://github.com/rust-lang/miri/issues/1807#issuecomment-845425076) for the rationale behind this change.
Note: this change does not cover all cases where unsupported functionality errors may be raised. If you search the repo for `throw_unsup_format!` there are many cases that I think are less likely to occur and may still be problematic for some folks.
TODO:
- [x] README documentation on this new flag
- [x] Add tests
In user interface, added a new flag `-Zmiri-isolation-error` which
takes one of the four values -- hide, warn, warn-nobacktrace, and
abort. This option can be used to configure Miri to either abort or
return an error code upon executing isolated op. If not aborted, Miri
prints a warning, whose verbosity can be configured using this flag.
In implementation, added a new enum `IsolatedOp` to capture all the
settings related to ops requiring communication with the
host. Old `communicate` flag in both miri configs and machine
stats is replaced with a new helper function `communicate()` which
checks `isolated_op` internally.
Added a new helper function `reject_in_isolation` which can be called
by shims to reject ops according to the reject_with settings. Use miri
specific diagnostics function `report_msg` to print backtrace in the
warning. Update it to take an enum value instead of a bool, indicating
the level of diagnostics.
Updated shims related to current dir to use the new APIs. Added a new
test for current dir ops in isolation without halting machine.
This PR uses the `measureme` crate to profile the call stack of the
program being interpreted by Miri. This is accomplished by starting a
measureme 'event' when we enter a function call, and ending the event
when we exit the call. The `measureme` tooling can be used to produce a
call stack from the generated profile data.
Limitations:
* We currently record every single entry/exit. This might generate very
large profile outputs for programs with a large number of function
calls. In follow-up work, we might want to explore sampling (e.g. only
recording every N function calls).
* This does not integrate very well with Miri's concurrency support.
Each event we record starts when we push a frame, and ends when we pop
a frame. As a result, switching between virtual threads will cause
events from different threads to be interleaved. Additionally, the
recorded for a particular frame will include all of the work Miri does
before that frame completes, including executing another thread.
The `measureme` integration is off by default, and must be enabled via
`-Zmiri-measureme=<output_name>`
add empty line before backtrace, to separate it from help text
I think this improves how things look, and makes it easier to see the help text (it currently kind of drowns next to the backtrace).
Before:
```
error: unsupported operation: Miri does not support threading
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
|
68 | let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Miri does not support threading
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
= note: inside `std::sys::unix:🧵:Thread::new` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
= note: inside `std:🧵:Builder::spawn_unchecked::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:492:26
= note: inside `std:🧵:Builder::spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:386:18
= note: inside `std:🧵:spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:619:5
note: inside `main` at tests/compile-fail/thread-spawn.rs:6:5
--> tests/compile-fail/thread-spawn.rs:6:5
|
6 | thread::spawn(|| {});
| ^^^^^^^^^^^^^^^^^^^^
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:34
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:73
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1:6030 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys_common/backtrace.rs:130:5
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:13
= note: inside `std::panicking::try::do_call::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:331:40
= note: inside `std::panicking::try::<i32, [closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:274:15
= note: inside `std::panic::catch_unwind::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panic.rs:394:14
= note: inside `std::rt::lang_start_internal` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:51:25
= note: inside `std::rt::lang_start::<()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:5
```
After:
```
error: unsupported operation: Miri does not support threading
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
|
68 | let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Miri does not support threading
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
= note: inside `std::sys::unix:🧵:Thread::new` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
= note: inside `std:🧵:Builder::spawn_unchecked::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:492:26
= note: inside `std:🧵:Builder::spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:386:18
= note: inside `std:🧵:spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:619:5
note: inside `main` at tests/compile-fail/thread-spawn.rs:6:5
--> tests/compile-fail/thread-spawn.rs:6:5
|
6 | thread::spawn(|| {});
| ^^^^^^^^^^^^^^^^^^^^
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:34
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:73
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1:6030 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys_common/backtrace.rs:130:5
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:13
= note: inside `std::panicking::try::do_call::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:331:40
= note: inside `std::panicking::try::<i32, [closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:274:15
= note: inside `std::panic::catch_unwind::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panic.rs:394:14
= note: inside `std::rt::lang_start_internal` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:51:25
= note: inside `std::rt::lang_start::<()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:5
```
What do you think?