Add anyhow for better errors
This commit is contained in:
parent
9a08103872
commit
d7cf79a092
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -2,6 +2,21 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.24.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
@ -61,12 +76,36 @@ dependencies = [
|
|||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.74"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base-x"
|
name = "base-x"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@ -421,6 +460,12 @@ dependencies = [
|
|||||||
"wasi 0.14.5+wasi-0.2.4",
|
"wasi 0.14.5+wasi-0.2.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.31.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -573,6 +618,15 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.4"
|
version = "0.26.4"
|
||||||
@ -618,6 +672,15 @@ dependencies = [
|
|||||||
"syn 2.0.106",
|
"syn 2.0.106",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.36.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
@ -692,6 +755,7 @@ dependencies = [
|
|||||||
name = "qemu-nyx-runner"
|
name = "qemu-nyx-runner"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"csv",
|
"csv",
|
||||||
"libnyx",
|
"libnyx",
|
||||||
@ -809,6 +873,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
|
@ -12,6 +12,7 @@ libnyx = { git = "https://git.cs.tu-dortmund.de/david.venhoff/libnyx-fork" }
|
|||||||
pt-dump-decoder = { path = "pt-dump-decoder" }
|
pt-dump-decoder = { path = "pt-dump-decoder" }
|
||||||
csv = "1.3.1"
|
csv = "1.3.1"
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
|
anyhow = { version = "1.0.99", features = ["backtrace"] }
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
clap = { version = "4.5.47", features = ["derive"] }
|
clap = { version = "4.5.47", features = ["derive"] }
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use crate::benchmark::Benchmark;
|
use crate::benchmark::Benchmark;
|
||||||
use crate::nyx::{NyxRunner, TraceMode};
|
use crate::nyx::{NyxRunner, TraceMode};
|
||||||
use std::error::Error;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct BenchmarkNyxNoPt(NyxRunner);
|
pub struct BenchmarkNyxNoPt(NyxRunner);
|
||||||
|
|
||||||
impl BenchmarkNyxNoPt {
|
impl BenchmarkNyxNoPt {
|
||||||
pub fn new(client_path: &Path) -> Result<Self, Box<dyn Error>> {
|
pub fn new(client_path: &Path) -> anyhow::Result<Self> {
|
||||||
Ok(BenchmarkNyxNoPt(NyxRunner::setup(
|
Ok(BenchmarkNyxNoPt(NyxRunner::setup(
|
||||||
client_path,
|
client_path,
|
||||||
TraceMode::Disabled,
|
TraceMode::Disabled,
|
||||||
|
@ -2,14 +2,13 @@ use crate::benchmark::{Benchmark, ToCsv};
|
|||||||
use crate::nyx::{NyxRunner, TraceMode};
|
use crate::nyx::{NyxRunner, TraceMode};
|
||||||
use csv::Writer;
|
use csv::Writer;
|
||||||
use pt_dump_decoder::{AnalyzeData, analyze_dump};
|
use pt_dump_decoder::{AnalyzeData, analyze_dump};
|
||||||
use std::error::Error;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub struct BenchmarkNyx(NyxRunner);
|
pub struct BenchmarkNyx(NyxRunner);
|
||||||
|
|
||||||
impl BenchmarkNyx {
|
impl BenchmarkNyx {
|
||||||
pub fn new(client_bin: &Path) -> Result<Self, Box<dyn Error>> {
|
pub fn new(client_bin: &Path) -> anyhow::Result<Self> {
|
||||||
Ok(BenchmarkNyx(NyxRunner::setup(
|
Ok(BenchmarkNyx(NyxRunner::setup(
|
||||||
client_bin,
|
client_bin,
|
||||||
TraceMode::Enabled,
|
TraceMode::Enabled,
|
||||||
|
@ -11,7 +11,6 @@ use crate::benchmark_baseline::Baseline;
|
|||||||
use crate::benchmark_nyx_no_pt::BenchmarkNyxNoPt;
|
use crate::benchmark_nyx_no_pt::BenchmarkNyxNoPt;
|
||||||
use crate::benchmark_nyx_pt::BenchmarkNyx;
|
use crate::benchmark_nyx_pt::BenchmarkNyx;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -30,7 +29,7 @@ struct Args {
|
|||||||
debug: bool,
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
if args.debug {
|
if args.debug {
|
||||||
@ -56,7 +55,7 @@ fn benchmark<B: Benchmark>(
|
|||||||
binary_name: &str,
|
binary_name: &str,
|
||||||
output_dir: &Path,
|
output_dir: &Path,
|
||||||
mut benchmark: B,
|
mut benchmark: B,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> anyhow::Result<()> {
|
||||||
warmup(&mut benchmark);
|
warmup(&mut benchmark);
|
||||||
let results = benchmark_loop(&mut benchmark);
|
let results = benchmark_loop(&mut benchmark);
|
||||||
write_results::<B>(binary_name, output_dir, &results)?;
|
write_results::<B>(binary_name, output_dir, &results)?;
|
||||||
@ -89,10 +88,10 @@ fn write_results<B: Benchmark>(
|
|||||||
binary_name: &str,
|
binary_name: &str,
|
||||||
output_dir: &Path,
|
output_dir: &Path,
|
||||||
results: &[B::BenchmarkResult],
|
results: &[B::BenchmarkResult],
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> anyhow::Result<()> {
|
||||||
fs::create_dir_all(output_dir)?;
|
fs::create_dir_all(output_dir)?;
|
||||||
let filename = format!("benchmark_{binary_name}_{}", B::TITLE);
|
let filename = format!("benchmark_{binary_name}_{}", B::TITLE);
|
||||||
let file = std::fs::File::create(output_dir.join(filename))?;
|
let file = fs::File::create(output_dir.join(filename))?;
|
||||||
let mut writer = csv::WriterBuilder::new().from_writer(file);
|
let mut writer = csv::WriterBuilder::new().from_writer(file);
|
||||||
writer.write_record(B::BenchmarkResult::HEADERS)?;
|
writer.write_record(B::BenchmarkResult::HEADERS)?;
|
||||||
for result in results {
|
for result in results {
|
||||||
|
38
src/nyx.rs
38
src/nyx.rs
@ -1,8 +1,8 @@
|
|||||||
//! This module contains functionality to download and setup nyx,
|
//! This module contains functionality to download and setup nyx,
|
||||||
//! so that it can be used to execute a binary.
|
//! so that it can be used to execute a binary.
|
||||||
|
|
||||||
|
use anyhow::{Context, anyhow, bail};
|
||||||
use libnyx::{NyxConfig, NyxProcess, NyxProcessRole, NyxReturnValue};
|
use libnyx::{NyxConfig, NyxProcess, NyxProcessRole, NyxReturnValue};
|
||||||
use std::error::Error;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -19,7 +19,7 @@ pub enum TraceMode {
|
|||||||
pub struct NyxRunner(NyxProcess);
|
pub struct NyxRunner(NyxProcess);
|
||||||
|
|
||||||
impl NyxRunner {
|
impl NyxRunner {
|
||||||
pub fn setup(client_bin: &Path, trace_mode: TraceMode) -> Result<Self, Box<dyn Error>> {
|
pub fn setup(client_bin: &Path, trace_mode: TraceMode) -> anyhow::Result<Self> {
|
||||||
if let Err(e) = fs::remove_dir_all(WORKDIR_PATH)
|
if let Err(e) = fs::remove_dir_all(WORKDIR_PATH)
|
||||||
&& !matches!(e.kind(), io::ErrorKind::NotFound)
|
&& !matches!(e.kind(), io::ErrorKind::NotFound)
|
||||||
{
|
{
|
||||||
@ -28,7 +28,9 @@ impl NyxRunner {
|
|||||||
let sharedir = setup_nyx(&PathBuf::from("nyx_data"), client_bin)?;
|
let sharedir = setup_nyx(&PathBuf::from("nyx_data"), client_bin)?;
|
||||||
let sharedir = sharedir.to_str().expect("Expected unicode path");
|
let sharedir = sharedir.to_str().expect("Expected unicode path");
|
||||||
|
|
||||||
let mut nyx_config = NyxConfig::load(sharedir)?;
|
let mut nyx_config = NyxConfig::load(sharedir)
|
||||||
|
.map_err(|err| anyhow!(err))
|
||||||
|
.with_context(|| "Creating nyx config")?;
|
||||||
nyx_config.set_workdir_path(WORKDIR_PATH.to_string());
|
nyx_config.set_workdir_path(WORKDIR_PATH.to_string());
|
||||||
nyx_config.set_input_buffer_size(0x2000);
|
nyx_config.set_input_buffer_size(0x2000);
|
||||||
nyx_config.set_nyx_debug_log_path("qemu_nyx.log".to_string());
|
nyx_config.set_nyx_debug_log_path("qemu_nyx.log".to_string());
|
||||||
@ -37,7 +39,9 @@ impl NyxRunner {
|
|||||||
nyx_config.set_process_role(NyxProcessRole::StandAlone);
|
nyx_config.set_process_role(NyxProcessRole::StandAlone);
|
||||||
nyx_config.print();
|
nyx_config.print();
|
||||||
|
|
||||||
let mut nyx_runner = NyxProcess::new(&mut nyx_config, 0)?;
|
let mut nyx_runner = NyxProcess::new(&mut nyx_config, 0)
|
||||||
|
.map_err(|err| anyhow!(err))
|
||||||
|
.with_context(|| "Creating Nyx Process")?;
|
||||||
|
|
||||||
nyx_runner.option_set_trace_mode(true);
|
nyx_runner.option_set_trace_mode(true);
|
||||||
nyx_runner.option_set_reload_mode(false);
|
nyx_runner.option_set_reload_mode(false);
|
||||||
@ -79,30 +83,31 @@ impl Drop for NyxRunner {
|
|||||||
/// [client] Is the path to the client binary.
|
/// [client] Is the path to the client binary.
|
||||||
///
|
///
|
||||||
/// Returns the path to the working directory
|
/// Returns the path to the working directory
|
||||||
pub fn setup_nyx(out_dir: &Path, client: &Path) -> Result<PathBuf, io::Error> {
|
pub fn setup_nyx(out_dir: &Path, client: &Path) -> anyhow::Result<PathBuf> {
|
||||||
fn inner(out_dir: &Path, client: &Path) -> Result<PathBuf, io::Error> {
|
fn inner(out_dir: &Path, client: &Path) -> anyhow::Result<PathBuf> {
|
||||||
if !out_dir.exists() {
|
if !out_dir.exists() {
|
||||||
fs::create_dir(out_dir)?;
|
fs::create_dir(out_dir)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Installing nyx...");
|
println!("Installing nyx...");
|
||||||
setup_nyx_tools(out_dir)?;
|
setup_nyx_tools(out_dir).with_context(|| "Setting up nyx tools")?;
|
||||||
|
|
||||||
create_nyx_workdir(out_dir, client)
|
create_nyx_workdir(out_dir, client).with_context(|| "Creating the nyx working directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up the out directory if something went wrong
|
// Clean up the out directory if something went wrong
|
||||||
match inner(out_dir, client) {
|
match inner(out_dir, client) {
|
||||||
Ok(path) => Ok(path),
|
Ok(path) => Ok(path),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
fs::remove_dir_all(out_dir)?;
|
fs::remove_dir_all(out_dir)
|
||||||
|
.with_context(|| format!("Error while handling error: {err}"))?;
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn shell(cwd: impl AsRef<Path>, command_string: &str) -> Result<(), io::Error> {
|
fn shell(cwd: impl AsRef<Path>, command_string: &str) -> anyhow::Result<()> {
|
||||||
println!("Running ({}) {command_string}", cwd.as_ref().display());
|
println!("Running ({}) {command_string}", cwd.as_ref().display());
|
||||||
|
|
||||||
let cwd = cwd.as_ref();
|
let cwd = cwd.as_ref();
|
||||||
@ -118,9 +123,7 @@ fn shell(cwd: impl AsRef<Path>, command_string: &str) -> Result<(), io::Error> {
|
|||||||
let mut process = command.spawn()?;
|
let mut process = command.spawn()?;
|
||||||
let exit_status = process.wait()?;
|
let exit_status = process.wait()?;
|
||||||
if !exit_status.success() {
|
if !exit_status.success() {
|
||||||
return Err(io::Error::other(format!(
|
bail!("Command ({command_string}) failed with {exit_status}");
|
||||||
"Command ({command_string}) failed with {exit_status}"
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -128,7 +131,7 @@ fn shell(cwd: impl AsRef<Path>, command_string: &str) -> Result<(), io::Error> {
|
|||||||
|
|
||||||
/// Downloads and compiles qemu-nyx and packer and compiles them for the current architecture
|
/// Downloads and compiles qemu-nyx and packer and compiles them for the current architecture
|
||||||
/// This means that cross-compilation is not supported
|
/// This means that cross-compilation is not supported
|
||||||
fn setup_nyx_tools(out_dir: &Path) -> Result<(), io::Error> {
|
fn setup_nyx_tools(out_dir: &Path) -> anyhow::Result<()> {
|
||||||
let packer_path = out_dir.join("packer");
|
let packer_path = out_dir.join("packer");
|
||||||
let qemu_path = out_dir.join("QEMU-Nyx");
|
let qemu_path = out_dir.join("QEMU-Nyx");
|
||||||
if !packer_path.exists() {
|
if !packer_path.exists() {
|
||||||
@ -142,7 +145,7 @@ fn setup_nyx_tools(out_dir: &Path) -> Result<(), io::Error> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Compile with maximum optimizations
|
// Compile with maximum optimizations
|
||||||
let qemu_compile_mode = "lto";
|
let qemu_compile_mode = "debug_static";
|
||||||
shell(
|
shell(
|
||||||
qemu_path,
|
qemu_path,
|
||||||
&format!("bash compile_qemu_nyx.sh {qemu_compile_mode}"),
|
&format!("bash compile_qemu_nyx.sh {qemu_compile_mode}"),
|
||||||
@ -152,8 +155,9 @@ fn setup_nyx_tools(out_dir: &Path) -> Result<(), io::Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_nyx_workdir(out_dir: &Path, client_bin: &Path) -> Result<PathBuf, io::Error> {
|
fn create_nyx_workdir(out_dir: &Path, client_bin: &Path) -> anyhow::Result<PathBuf> {
|
||||||
let client_bin = fs::canonicalize(client_bin)?;
|
let client_bin =
|
||||||
|
fs::canonicalize(client_bin).with_context(|| format!("canonicalizing {client_bin:?}"))?;
|
||||||
let client_bin = client_bin.to_str().expect("Expected unicode path");
|
let client_bin = client_bin.to_str().expect("Expected unicode path");
|
||||||
// Create the directory and move required binaries to it
|
// Create the directory and move required binaries to it
|
||||||
shell(
|
shell(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user