File scoping and reporting works

This commit is contained in:
Audrey 2024-04-17 09:43:56 -07:00
parent 6926711e83
commit 62f7e40c64
4 changed files with 54 additions and 13 deletions

View File

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nix = { version = "0.28.0", features = ["ptrace", "process"] }
nix = { version = "0.28.0", features = ["ptrace", "process", "fs"] }
linux-personality = "1.0.0"
anyhow = { version = "1", features = ["backtrace"] }
log = "0.4"

View File

@ -4,7 +4,7 @@ use std::{
path::PathBuf, borrow::Cow,
};
use gimli::{constants, AttributeValue, DW_TAG_compile_unit};
use gimli::{constants, DW_TAG_compile_unit};
use serde::{Deserialize, Serialize};
use sha2::{digest::generic_array::{GenericArray, typenum::U32}, Digest, Sha256};
use object::{Object, ReadCache, ObjectSection};
@ -110,7 +110,7 @@ impl FileStore {
self.files
.get_mut(*e.get())
.unwrap()
.output_names
.input_names
.insert(filename.clone());
*e.get()
}
@ -130,7 +130,7 @@ impl FileStore {
}
let fp = fs::File::open(&filename)?;
self.ingest_output(filename, fp);
self.ingest_output(filename, fp)?;
Ok(())
}

View File

@ -1,5 +1,6 @@
mod tracer;
mod filestore;
mod reports;
use std::path::PathBuf;
@ -13,18 +14,30 @@ struct Cli {
#[derive(Subcommand, Debug, Clone)]
enum Subcommands {
/// Run a command and record its execution
Run {
/// Any number of filepaths to treat as inputs. They will be hashed and accesses to
/// equivalent files will be treated specially.
#[arg(short, long)]
input: Vec<PathBuf>,
file_scope: Vec<PathBuf>,
/// The filepath to dump the json report to. will dump to stdout if unspecified.
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(short, long)]
mute: bool,
/// The command to run. Have fun!
cmd: Vec<String>,
},
/// Query from the report how in-scope items were used
QueryParameters {
/// The filepath of the report ot open. will read from stdin if unspecified.
input: Option<PathBuf>,
/// The filepath to dump the json report to. will dump to stdout if unspecified.
output: Option<PathBuf>,
}
}
@ -32,20 +45,41 @@ fn main() {
env_logger::init();
let cli = Cli::parse();
match cli.cmd {
Subcommands::Run { input, output, cmd } => {
Subcommands::Run { file_scope, output, cmd, mute } => {
let fp: Box<dyn std::io::Write> = if let Some(output) = &output {
Box::new(std::fs::File::options().write(true).create(true).open(output).unwrap())
} else {
Box::new(std::io::stdout())
};
let mut t = tracer::Tracer::new(input).unwrap();
t.start_root_process(cmd).unwrap();
let mut t = tracer::Tracer::new(file_scope).unwrap();
t.start_root_process(cmd, mute).unwrap();
if output.is_none() {
serde_json::to_writer_pretty(fp, &t.report).unwrap();
serde_json::to_writer_pretty(fp, &t.report)
} else {
serde_json::to_writer(fp, &t.report).unwrap();
}
serde_json::to_writer(fp, &t.report)
}.expect("Could not serialize json trace report");
}
Subcommands::QueryParameters { input, output } => {
let fp: Box<dyn std::io::Write> = if let Some(output) = &output {
Box::new(std::fs::File::options().write(true).create(true).open(output).unwrap())
} else {
Box::new(std::io::stdout())
};
let in_report: tracer::TracerReport = if let Some(input) = &input {
serde_json::from_reader(std::fs::File::open(input).unwrap())
} else {
serde_json::from_reader(std::io::stdin())
}.expect("Could not deserialize json trace report");
let out_report = reports::parameters::run(&in_report).unwrap();
if output.is_none() {
serde_json::to_writer_pretty(fp, &out_report)
} else {
serde_json::to_writer(fp, &out_report)
}.expect("Could not serialize json parameter report");
}
}
}

View File

@ -2,7 +2,7 @@ use std::{
collections::HashMap,
ffi::CString,
ffi::OsString,
os::unix::prelude::OsStringExt,
os::{fd::{AsRawFd}, unix::prelude::OsStringExt},
path::PathBuf,
process::exit,
time::{Duration, Instant},
@ -465,7 +465,7 @@ impl Tracer {
}
}
pub fn start_root_process(&mut self, args: Vec<String>) -> anyhow::Result<()> {
pub fn start_root_process(&mut self, args: Vec<String>, mute: bool) -> anyhow::Result<()> {
log::trace!("start_root_process: {:?}", args);
if let ForkResult::Parent { child: root_child } = unsafe { nix::unistd::fork()? } {
@ -633,6 +633,13 @@ impl Tracer {
exit(-1);
}
if mute {
let null = std::fs::File::options().read(true).write(true).open("/dev/null").expect("Could not open /dev/null");
nix::unistd::dup2(null.as_raw_fd(), 0).expect("Could not dup /dev/null to /dev/stdin");
nix::unistd::dup2(null.as_raw_fd(), 1).expect("Could not dup /dev/null to /dev/stdout");
nix::unistd::dup2(null.as_raw_fd(), 2).expect("Could not dup /dev/null to /dev/stderr");
}
let args = args
.into_iter()
.map(CString::new)