Move install nyx functionality from build script to runtime
It did not make a lot of sense to have that in the buildscript, as that will make nyx_runner dependent on the target directory. This also allows specifying a binary to trace at runtime
This commit is contained in:
parent
57ff2f187c
commit
2d88a8539f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
/target
|
||||
*.log
|
||||
/nyx_data
|
31
Cargo.lock
generated
31
Cargo.lock
generated
@ -130,7 +130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"heck",
|
||||
"heck 0.4.1",
|
||||
"indexmap",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
@ -180,18 +180,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.42"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882"
|
||||
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.42"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966"
|
||||
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@ -199,6 +200,18 @@ dependencies = [
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.5"
|
||||
@ -426,6 +439,12 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.10.0"
|
||||
@ -673,7 +692,7 @@ dependencies = [
|
||||
name = "qemu-nyx-runner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"client",
|
||||
"clap",
|
||||
"csv",
|
||||
"libnyx",
|
||||
"pt-dump-decoder",
|
||||
|
@ -8,7 +8,7 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
client = { path = "client" }
|
||||
libnyx = { git = "https://git.cs.tu-dortmund.de/david.venhoff/libnyx-fork" }
|
||||
pt-dump-decoder = { path = "pt-dump-decoder" }
|
||||
csv = "1.3.1"
|
||||
clap = { version = "4.5.47", features = ["derive"] }
|
||||
|
101
build.rs
101
build.rs
@ -1,101 +0,0 @@
|
||||
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")
|
||||
}
|
@ -30,7 +30,7 @@ const BENCHMARKS: &[&str] = &[
|
||||
];
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=coremark/");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
Command::new("git")
|
||||
|
@ -1,21 +1,23 @@
|
||||
use crate::benchmark::{Benchmark, ToCsv};
|
||||
use crate::nyx;
|
||||
use csv::Writer;
|
||||
use libnyx::{NyxConfig, NyxProcess, NyxProcessRole, NyxReturnValue};
|
||||
use pt_dump_decoder::{AnalyzeData, analyze_dump};
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
const WORKDIR_PATH: &str = "/tmp/wdir";
|
||||
// The sharedir path gets set by the build script
|
||||
const SHAREDIR_PATH: &str = env!("NYX_SHAREDIR");
|
||||
|
||||
pub struct NyxRunner(NyxProcess);
|
||||
|
||||
impl NyxRunner {
|
||||
pub fn setup() -> Result<Self, Box<dyn Error>> {
|
||||
pub fn setup(client_bin: &Path) -> Result<Self, Box<dyn Error>> {
|
||||
let _ = std::fs::remove_dir_all(WORKDIR_PATH);
|
||||
let sharedir = nyx::setup_nyx(&PathBuf::from("nyx_data"), client_bin)?;
|
||||
let sharedir = sharedir.to_str().expect("Expected unicode path");
|
||||
|
||||
let mut nyx_config = NyxConfig::load(SHAREDIR_PATH)?;
|
||||
let mut nyx_config = NyxConfig::load(sharedir)?;
|
||||
nyx_config.set_workdir_path(WORKDIR_PATH.to_string());
|
||||
nyx_config.set_input_buffer_size(0x2000);
|
||||
nyx_config.set_nyx_debug_log_path("qemu_nyx.log".to_string());
|
||||
|
16
src/main.rs
16
src/main.rs
@ -1,19 +1,27 @@
|
||||
//! Translated from libnyx/test.c
|
||||
|
||||
mod benchmark;
|
||||
mod benchmark_baseline;
|
||||
mod benchmark_nyx_pt;
|
||||
mod nyx;
|
||||
|
||||
use crate::benchmark::{Benchmark, ToCsv};
|
||||
use crate::benchmark_baseline::Baseline;
|
||||
use crate::benchmark_nyx_pt::NyxRunner;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
use std::time::{Duration, Instant};
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(about="Tool to execute a program with nyx and trace it with intel pt")]
|
||||
struct Args {
|
||||
/// Path to the client binary to execute
|
||||
client: PathBuf
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let nyx_runner = NyxRunner::setup()?;
|
||||
let args = Args::parse();
|
||||
let nyx_runner = NyxRunner::setup(&args.client)?;
|
||||
benchmark(nyx_runner)?;
|
||||
benchmark(Baseline)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
109
src/nyx.rs
Normal file
109
src/nyx.rs
Normal file
@ -0,0 +1,109 @@
|
||||
//! This module contains functionality to download and setup nyx,
|
||||
//! so that it can be used to execute a binary.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::{fs, io};
|
||||
|
||||
/// Downloads and installs nyx
|
||||
///
|
||||
/// [out_dir] Is the directory to which all tools get downloaded and
|
||||
/// where the working directory gets created.
|
||||
///
|
||||
/// [client] Is the path to the client binary.
|
||||
///
|
||||
/// Returns the path to the working directory
|
||||
pub fn setup_nyx(out_dir: &Path, client: &Path) -> Result<PathBuf, io::Error> {
|
||||
fn inner(out_dir: &Path, client: &Path) -> Result<PathBuf, io::Error> {
|
||||
if out_dir.exists() {
|
||||
println!("Nyx is already installed, skipping setup");
|
||||
} else {
|
||||
println!("Installing nxx...");
|
||||
fs::create_dir(out_dir)?;
|
||||
setup_nyx_tools(&out_dir)?;
|
||||
}
|
||||
|
||||
create_nyx_workdir(&out_dir, &client)
|
||||
}
|
||||
|
||||
// Clean up the out directory if something went wrong
|
||||
match inner(out_dir, client) {
|
||||
Ok(path) => Ok(path),
|
||||
Err(err) => {
|
||||
fs::remove_dir_all(out_dir)?;
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn shell(cwd: impl AsRef<Path>, command_string: &str) -> Result<(), io::Error> {
|
||||
println!("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()?;
|
||||
let exit_status = process.wait()?;
|
||||
if !exit_status.success() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Command ({command_string}) failed with {exit_status}"),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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_tools(out_dir: &Path) -> Result<(), io::Error> {
|
||||
let packer_path = out_dir.join("packer");
|
||||
let qemu_path = out_dir.join("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",
|
||||
)?;
|
||||
|
||||
// Compile with maximum optimizations
|
||||
let qemu_compile_mode = "lto";
|
||||
shell(
|
||||
qemu_path,
|
||||
&format!("bash compile_qemu_nyx.sh {qemu_compile_mode}"),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_nyx_workdir(out_dir: &Path, client_bin: &Path) -> Result<PathBuf, io::Error> {
|
||||
let client_bin = fs::canonicalize(client_bin)?;
|
||||
let client_bin = client_bin.to_str().expect("Expected unicode path");
|
||||
// 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",
|
||||
)?;
|
||||
|
||||
Ok(out_dir.join("build"))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user