qemu-nyx-runner/build.rs

102 lines
3.0 KiB
Rust

use std::env;
use std::path::Path;
use std::process::Command;
fn main() {
println!("cargo:rerun-if-changed=client");
let out_dir = env::var("OUT_DIR").unwrap();
let client_bin = build_client(&out_dir);
setup_nyx(&out_dir);
create_nyx_workdir(&out_dir, &client_bin);
}
#[track_caller]
fn shell(cwd: impl AsRef<Path>, command_string: &str) {
println!(
"cargo:warning=Running ({}) {command_string}",
cwd.as_ref().display()
);
let cwd = cwd.as_ref();
let mut parts = command_string.split(" ");
let command_name = parts.next().unwrap();
let mut command = Command::new(command_name);
command.current_dir(cwd);
command.stdout(std::process::Stdio::inherit());
command.stderr(std::process::Stdio::inherit());
command.args(parts);
let mut process = command.spawn().unwrap();
let exit_status = process.wait().unwrap();
if !exit_status.success() {
panic!(
"Command failed with {exit_status}: {}> {command_string}",
cwd.display()
);
}
}
/// Builds the client and returns the path to its binary
fn build_client(out_dir: &str) -> String {
// Change the target dir to avoid a cargo target dir deadlock
shell(
"client",
&format!("cargo build --release --target-dir {out_dir}/client_target"),
);
format!("{out_dir}/client_target/release/client")
}
/// Downloads and compiles qemu-nyx and packer and compiles them for the current architecture
/// This means that cross-compilation is not supported
fn setup_nyx(out_dir: &str) {
let packer_path = std::path::PathBuf::from(format!("{out_dir}/packer"));
let qemu_path = std::path::PathBuf::from(format!("{out_dir}/QEMU-Nyx"));
if !packer_path.exists() {
shell(out_dir, "git clone https://github.com/nyx-fuzz/packer/");
}
if !qemu_path.exists() {
println!("cargo:warning=Cloning and building QEMU-Nyx. This may take a while...");
shell(
out_dir,
"git clone https://github.com/nyx-fuzz/QEMU-Nyx --depth 1",
);
let is_debug_build = match env::var("DEBUG").unwrap().as_str() {
"true" => true,
"false" => false,
other => panic!("Invalid value for DEBUG: {other}"),
};
let qemu_compile_mode = if is_debug_build {
"debug_static"
} else {
"lto"
};
shell(
qemu_path,
&format!("bash compile_qemu_nyx.sh {qemu_compile_mode}"),
);
}
}
fn create_nyx_workdir(out_dir: &str, client_bin: &str) {
// Create the directory and move required binaries to it
shell(
out_dir,
&format!(
"python3 packer/packer/nyx_packer.py {client_bin} build afl processor_trace --fast_reload_mode --purge"
),
);
// Create the nyx config
shell(
out_dir,
"python3 packer/packer/nyx_config_gen.py build Kernel",
);
// Pass the path to the build directory to src/main.rs
println!("cargo:rustc-env=NYX_SHAREDIR={out_dir}/build")
}