Skip to content

Commit

Permalink
Resolve merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
teryror committed Jan 27, 2021
2 parents a815a42 + e23e0b2 commit 154fb52
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 75 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,5 +130,11 @@ jobs:
ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
run: |
~/.local/bin/zulip-send --stream miri --subject "Cron Job Failure" \
--message 'Dear @**RalfJ** and @**oli**\n\nIt would appear that the Miri cron job build failed. Would you mind investigating this issue?\n\nThanks in advance!\nSincerely,\nThe Miri Cronjobs Bot' \
--message 'Dear @**RalfJ** and @**oli**
It would appear that the Miri cron job build failed. Would you mind investigating this issue?
Thanks in advance!
Sincerely,
The Miri Cronjobs Bot' \
--user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ environment variable:
* `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you
can focus on other failures, but it means Miri can miss bugs in your program.
Using this flag is **unsound**.
* `-Zmiri-disable-data-race-detector` disables checking for data races. Using
this flag is **unsound**.
* `-Zmiri-disable-stacked-borrows` disables checking the experimental
[Stacked Borrows] aliasing rules. This can make Miri run faster, but it also
means no aliasing violations will be detected. Using this flag is **unsound**
Expand Down
154 changes: 110 additions & 44 deletions cargo-miri/bin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::iter::TakeWhile;
use std::io::{self, BufRead, BufReader, BufWriter, Read, Write};
use std::ops::Not;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -36,9 +37,9 @@ enum MiriCommand {
Setup,
}

/// The inforamtion Miri needs to run a crate. Stored as JSON when the crate is "compiled".
/// The information to run a crate with the given environment.
#[derive(Serialize, Deserialize)]
struct CrateRunInfo {
struct CrateRunEnv {
/// The command-line arguments.
args: Vec<String>,
/// The environment.
Expand All @@ -49,6 +50,15 @@ struct CrateRunInfo {
stdin: Vec<u8>,
}

/// The information Miri needs to run a crate. Stored as JSON when the crate is "compiled".
#[derive(Serialize, Deserialize)]
enum CrateRunInfo {
/// Run it with the given environment.
RunWith(CrateRunEnv),
/// Skip it as Miri does not support interpreting such kind of crates.
SkipProcMacroTest,
}

impl CrateRunInfo {
/// Gather all the information we need.
fn collect(args: env::Args) -> Self {
Expand All @@ -61,7 +71,7 @@ impl CrateRunInfo {
std::io::stdin().lock().read_to_end(&mut stdin).expect("cannot read stdin");
}

CrateRunInfo { args, env, current_dir, stdin }
Self::RunWith(CrateRunEnv { args, env, current_dir, stdin })
}

fn store(&self, filename: &Path) {
Expand Down Expand Up @@ -97,31 +107,50 @@ fn has_arg_flag(name: &str) -> bool {
args.any(|val| val == name)
}

/// Gets the value of a `--flag`.
fn get_arg_flag_value(name: &str) -> Option<String> {
// Stop searching at `--`.
let mut args = std::env::args().take_while(|val| val != "--");
loop {
let arg = match args.next() {
Some(arg) => arg,
None => return None,
};
if !arg.starts_with(name) {
continue;
/// Yields all values of command line flag `name`.
struct ArgFlagValueIter<'a> {
args: TakeWhile<env::Args, fn(&String) -> bool>,
name: &'a str,
}

impl<'a> ArgFlagValueIter<'a> {
fn new(name: &'a str) -> Self {
Self {
// Stop searching at `--`.
args: env::args().take_while(|val| val != "--"),
name,
}
// Strip leading `name`.
let suffix = &arg[name.len()..];
if suffix.is_empty() {
// This argument is exactly `name`; the next one is the value.
return args.next();
} else if suffix.starts_with('=') {
// This argument is `name=value`; get the value.
// Strip leading `=`.
return Some(suffix[1..].to_owned());
}
}

impl Iterator for ArgFlagValueIter<'_> {
type Item = String;

fn next(&mut self) -> Option<Self::Item> {
loop {
let arg = self.args.next()?;
if !arg.starts_with(self.name) {
continue;
}
// Strip leading `name`.
let suffix = &arg[self.name.len()..];
if suffix.is_empty() {
// This argument is exactly `name`; the next one is the value.
return self.args.next();
} else if suffix.starts_with('=') {
// This argument is `name=value`; get the value.
// Strip leading `=`.
return Some(suffix[1..].to_owned());
}
}
}
}

/// Gets the value of a `--flag`.
fn get_arg_flag_value(name: &str) -> Option<String> {
ArgFlagValueIter::new(name).next()
}

/// Returns the path to the `miri` binary
fn find_miri() -> PathBuf {
if let Some(path) = env::var_os("MIRI") {
Expand Down Expand Up @@ -460,14 +489,15 @@ fn phase_cargo_miri(mut args: env::Args) {
// This is needed to make the `CARGO_TARGET_*_RUNNER` env var do something,
// and it later helps us detect which crates are proc-macro/build-script
// (host crates) and which crates are needed for the program itself.
let target = if let Some(target) = get_arg_flag_value("--target") {
let host = version_info().host;
let target = get_arg_flag_value("--target");
let target = if let Some(ref target) = target {
target
} else {
// No target given. Pick default and tell cargo about it.
let host = version_info().host;
cmd.arg("--target");
cmd.arg(&host);
host
&host
};

// Forward all further arguments. We do some processing here because we want to
Expand Down Expand Up @@ -519,17 +549,27 @@ fn phase_cargo_miri(mut args: env::Args) {
}
cmd.env("RUSTC_WRAPPER", &cargo_miri_path);

// Set the runner for the current target to us as well, so we can interpret the binaries.
let runner_env_name = format!("CARGO_TARGET_{}_RUNNER", target.to_uppercase().replace('-', "_"));
cmd.env(&runner_env_name, &cargo_miri_path);
let runner_env_name = |triple: &str| {
format!("CARGO_TARGET_{}_RUNNER", triple.to_uppercase().replace('-', "_"))
};
let host_runner_env_name = runner_env_name(&host);
let target_runner_env_name = runner_env_name(target);
// Set the target runner to us, so we can interpret the binaries.
cmd.env(&target_runner_env_name, &cargo_miri_path);
// Unit tests of `proc-macro` crates are run on the host, so we set the host runner to
// us in order to skip them.
cmd.env(&host_runner_env_name, &cargo_miri_path);

// Set rustdoc to us as well, so we can make it do nothing (see issue #584).
cmd.env("RUSTDOC", &cargo_miri_path);

// Run cargo.
if verbose {
eprintln!("[cargo-miri miri] RUSTC_WRAPPER={:?}", cargo_miri_path);
eprintln!("[cargo-miri miri] {}={:?}", runner_env_name, cargo_miri_path);
eprintln!("[cargo-miri miri] {}={:?}", target_runner_env_name, cargo_miri_path);
if *target != host {
eprintln!("[cargo-miri miri] {}={:?}", host_runner_env_name, cargo_miri_path);
}
eprintln!("[cargo-miri miri] RUSTDOC={:?}", cargo_miri_path);
eprintln!("[cargo-miri miri] {:?}", cmd);
cmd.env("MIRI_VERBOSE", ""); // This makes the other phases verbose.
Expand Down Expand Up @@ -597,28 +637,38 @@ fn phase_cargo_rustc(args: env::Args) {
_ => {},
}

if !print && target_crate && is_runnable_crate() {
// This is the binary or test crate that we want to interpret under Miri.
// But we cannot run it here, as cargo invoked us as a compiler -- our stdin and stdout are not
// like we want them.
// Instead of compiling, we write JSON into the output file with all the relevant command-line flags
// and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
let info = CrateRunInfo::collect(args);
let store_json = |info: &CrateRunInfo| {
let filename = out_filename("", "");
if verbose {
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
}

info.store(&filename);
// For Windows, do the same thing again with `.exe` appended to the filename.
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
info.store(&out_filename("", ".exe"));
};

let runnable_crate = !print && is_runnable_crate();

if runnable_crate && target_crate {
// This is the binary or test crate that we want to interpret under Miri.
// But we cannot run it here, as cargo invoked us as a compiler -- our stdin and stdout are not
// like we want them.
// Instead of compiling, we write JSON into the output file with all the relevant command-line flags
// and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
let info = CrateRunInfo::collect(args);
store_json(&info);

// Rustdoc expects us to exit with an error code if the test is marked as `compile_fail`,
// just creating the JSON file is not enough: we need to detect syntax errors,
// so we need to run Miri with `MIRI_BE_RUSTC` for a check-only build.
if std::env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_some() {
let mut cmd = miri();
let env = if let CrateRunInfo::RunWith(env) = info {
env
} else {
return;
};

// use our own sysroot
if !has_arg_flag("--sysroot") {
Expand All @@ -628,28 +678,36 @@ fn phase_cargo_rustc(args: env::Args) {
}

// ensure --emit argument for a check-only build is present
if let Some(i) = info.args.iter().position(|arg| arg.starts_with("--emit=")) {
if let Some(i) = env.args.iter().position(|arg| arg.starts_with("--emit=")) {
// We need to make sure we're not producing a binary that overwrites the JSON file.
// rustdoc should only ever pass an --emit=metadata argument for tests marked as `no_run`:
assert_eq!(info.args[i], "--emit=metadata");
assert_eq!(env.args[i], "--emit=metadata");
} else {
cmd.arg("--emit=dep-info,metadata");
}

cmd.args(info.args);
cmd.args(env.args);
cmd.env("MIRI_BE_RUSTC", "1");

if verbose {
eprintln!("[cargo-miri rustc] captured input:\n{}", std::str::from_utf8(&info.stdin).unwrap());
eprintln!("[cargo-miri rustc] captured input:\n{}", std::str::from_utf8(&env.stdin).unwrap());
eprintln!("[cargo-miri rustc] {:?}", cmd);
}

exec_with_pipe(cmd, &info.stdin);
exec_with_pipe(cmd, &env.stdin);
}

return;
}

if runnable_crate && ArgFlagValueIter::new("--extern").any(|krate| krate == "proc_macro") {
// This is a "runnable" `proc-macro` crate (unit tests). We do not support
// interpreting that under Miri now, so we write a JSON file to (display a
// helpful message and) skip it in the runner phase.
store_json(&CrateRunInfo::SkipProcMacroTest);
return;
}

let mut cmd = miri();
let mut emit_link_hack = false;
// Arguments are treated very differently depending on whether this crate is
Expand Down Expand Up @@ -726,8 +784,16 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
let file = File::open(&binary)
.unwrap_or_else(|_| show_error(format!("file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`", binary)));
let file = BufReader::new(file);
let info: CrateRunInfo = serde_json::from_reader(file)

let info = serde_json::from_reader(file)
.unwrap_or_else(|_| show_error(format!("file {:?} contains outdated or invalid JSON; try `cargo clean`", binary)));
let info = match info {
CrateRunInfo::RunWith(info) => info,
CrateRunInfo::SkipProcMacroTest => {
eprintln!("Running unit tests of `proc-macro` crates is not currently supported by Miri.");
return;
}
};

let mut cmd = miri();

Expand Down
2 changes: 1 addition & 1 deletion ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ run_tests
case $HOST_TARGET in
x86_64-unknown-linux-gnu)
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=x86_64-apple-darwin run_tests
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
;;
x86_64-apple-darwin)
Expand Down
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
dc1eee2f256efbd1d3b50b6b090232f81cac6d72
78e22069d018e83915201c8a218a0a94227f6420
12 changes: 12 additions & 0 deletions src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let &[] = check_arg_count(args)?;
this.yield_active_thread();
}
"llvm.aarch64.hint" if this.tcx.sess.target.arch == "aarch64" => {
let &[hint] = check_arg_count(args)?;
let hint = this.read_scalar(hint)?.to_i32()?;
match hint {
1 => { // HINT_YIELD
this.yield_active_thread();
}
_ => {
throw_unsup_format!("unsupported llvm.aarch64.hint argument {}", hint);
}
}
}

// Platform-specific shims
_ => match this.tcx.sess.target.os.as_str() {
Expand Down
1 change: 1 addition & 0 deletions src/shims/posix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx

let sysconfs = &[
("_SC_PAGESIZE", Scalar::from_int(PAGE_SIZE, this.pointer_size())),
("_SC_NPROCESSORS_CONF", Scalar::from_int(NUM_CPUS, this.pointer_size())),
("_SC_NPROCESSORS_ONLN", Scalar::from_int(NUM_CPUS, this.pointer_size())),
];
let mut result = None;
Expand Down
12 changes: 6 additions & 6 deletions src/shims/posix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}

// File related shims
"close$NOCANCEL" => {
"close" | "close$NOCANCEL" => {
let &[result] = check_arg_count(args)?;
let result = this.close(result)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"stat$INODE64" => {
"stat" | "stat$INODE64" => {
let &[path, buf] = check_arg_count(args)?;
let result = this.macos_stat(path, buf)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"lstat$INODE64" => {
"lstat" | "lstat$INODE64" => {
let &[path, buf] = check_arg_count(args)?;
let result = this.macos_lstat(path, buf)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"fstat$INODE64" => {
"fstat" | "fstat$INODE64" => {
let &[fd, buf] = check_arg_count(args)?;
let result = this.macos_fstat(fd, buf)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"opendir$INODE64" => {
"opendir" | "opendir$INODE64" => {
let &[name] = check_arg_count(args)?;
let result = this.opendir(name)?;
this.write_scalar(result, dest)?;
}
"readdir_r$INODE64" => {
"readdir_r" | "readdir_r$INODE64" => {
let &[dirp, entry, result] = check_arg_count(args)?;
let result = this.macos_readdir_r(dirp, entry, result)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
Expand Down
1 change: 0 additions & 1 deletion src/shims/windows/dlsym.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ impl Dlsym {
"AcquireSRWLockShared" => Some(Dlsym::AcquireSRWLockShared),
"ReleaseSRWLockShared" => Some(Dlsym::ReleaseSRWLockShared),
"TryAcquireSRWLockShared" => Some(Dlsym::TryAcquireSRWLockShared),
"SetThreadStackGuarantee" => None,
"GetSystemTimePreciseAsFileTime" => None,
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
})
Expand Down
Loading

0 comments on commit 154fb52

Please sign in to comment.