mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-18 20:58:06 +00:00
embed coverage debugger scripts (#783)
This commit is contained in:
@ -188,7 +188,7 @@ impl CoverageProcessor {
|
|||||||
pub async fn new(config: Arc<Config>) -> Result<Self> {
|
pub async fn new(config: Arc<Config>) -> Result<Self> {
|
||||||
let heartbeat_client = config.common.init_heartbeat().await?;
|
let heartbeat_client = config.common.init_heartbeat().await?;
|
||||||
let total = TotalCoverage::new(config.coverage.path.join(TOTAL_COVERAGE));
|
let total = TotalCoverage::new(config.coverage.path.join(TOTAL_COVERAGE));
|
||||||
let recorder = CoverageRecorder::new(config.clone());
|
let recorder = CoverageRecorder::new(config.clone()).await?;
|
||||||
let module_totals = BTreeMap::default();
|
let module_totals = BTreeMap::default();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -9,10 +9,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use onefuzz::{
|
use onefuzz::{fs::has_files, sha256::digest_file};
|
||||||
fs::{has_files, OwnedDir},
|
use tempfile::{tempdir, TempDir};
|
||||||
sha256::digest_file,
|
|
||||||
};
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
fs,
|
fs,
|
||||||
process::{Child, Command},
|
process::{Child, Command},
|
||||||
@ -22,17 +20,71 @@ use crate::tasks::coverage::libfuzzer_coverage::Config;
|
|||||||
|
|
||||||
pub struct CoverageRecorder {
|
pub struct CoverageRecorder {
|
||||||
config: Arc<Config>,
|
config: Arc<Config>,
|
||||||
script_dir: OwnedDir,
|
script_path: PathBuf,
|
||||||
|
// keep _temp_dir such that Drop cleans up temporary files
|
||||||
|
_temp_dir: Option<TempDir>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SYMBOL_EXTRACT_ERROR: &str = "Target appears to be missing sancov instrumentation. This error can also happen if symbols for the target are not available.";
|
const SYMBOL_EXTRACT_ERROR: &str = "Target appears to be missing sancov instrumentation. This error can also happen if symbols for the target are not available.";
|
||||||
|
|
||||||
impl CoverageRecorder {
|
impl CoverageRecorder {
|
||||||
pub fn new(config: Arc<Config>) -> Self {
|
pub async fn new(config: Arc<Config>) -> Result<Self> {
|
||||||
let script_dir =
|
let (script_path, _temp_dir) = match env::var("ONEFUZZ_TOOLS") {
|
||||||
OwnedDir::new(env::var("ONEFUZZ_TOOLS").unwrap_or_else(|_| "script".to_string()));
|
Ok(tools_dir) => {
|
||||||
|
let script_path = PathBuf::from(tools_dir);
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
(
|
||||||
|
script_path
|
||||||
|
.join("linux")
|
||||||
|
.join("libfuzzer-coverage")
|
||||||
|
.join("coverage_cmd.py"),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
} else if cfg!(target_os = "windows") {
|
||||||
|
(
|
||||||
|
script_path
|
||||||
|
.join("win64")
|
||||||
|
.join("libfuzzer-coverage")
|
||||||
|
.join("DumpCounters.js"),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
bail!("coverage recorder not implemented for target os");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
let temp_dir = tempdir()?;
|
||||||
|
let script_path = if cfg!(target_os = "linux") {
|
||||||
|
let script_path = temp_dir.path().join("coverage_cmd.py");
|
||||||
|
let content = include_bytes!(
|
||||||
|
"../../../../script/linux/libfuzzer-coverage/coverage_cmd.py"
|
||||||
|
);
|
||||||
|
fs::write(&script_path, content).await.with_context(|| {
|
||||||
|
format!("unable to write file: {}", script_path.display())
|
||||||
|
})?;
|
||||||
|
script_path
|
||||||
|
} else if cfg!(target_os = "windows") {
|
||||||
|
let script_path = temp_dir.path().join("DumpCounters.js");
|
||||||
|
let content = include_bytes!(
|
||||||
|
"../../../../script/win64/libfuzzer-coverage/DumpCounters.js"
|
||||||
|
);
|
||||||
|
fs::write(&script_path, content).await.with_context(|| {
|
||||||
|
format!("unable to write file: {}", script_path.display())
|
||||||
|
})?;
|
||||||
|
script_path
|
||||||
|
} else {
|
||||||
|
bail!("coverage recorder not implemented for target os");
|
||||||
|
};
|
||||||
|
|
||||||
Self { config, script_dir }
|
(script_path, Some(temp_dir))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
config,
|
||||||
|
script_path,
|
||||||
|
_temp_dir,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoke a script to write coverage to a file.
|
/// Invoke a script to write coverage to a file.
|
||||||
@ -103,19 +155,12 @@ impl CoverageRecorder {
|
|||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn invoke_debugger_script(&self, test_input: &Path, output: &Path) -> Result<Child> {
|
fn invoke_debugger_script(&self, test_input: &Path, output: &Path) -> Result<Child> {
|
||||||
let script_path = self
|
|
||||||
.script_dir
|
|
||||||
.path()
|
|
||||||
.join("linux")
|
|
||||||
.join("libfuzzer-coverage")
|
|
||||||
.join("coverage_cmd.py");
|
|
||||||
|
|
||||||
let mut cmd = Command::new("gdb");
|
let mut cmd = Command::new("gdb");
|
||||||
cmd.arg(&self.config.target_exe)
|
cmd.arg(&self.config.target_exe)
|
||||||
.arg("-nh")
|
.arg("-nh")
|
||||||
.arg("-batch")
|
.arg("-batch")
|
||||||
.arg("-x")
|
.arg("-x")
|
||||||
.arg(script_path)
|
.arg(&self.script_path)
|
||||||
.arg("-ex")
|
.arg("-ex")
|
||||||
.arg(format!(
|
.arg(format!(
|
||||||
"coverage {} {} {}",
|
"coverage {} {} {}",
|
||||||
@ -139,18 +184,11 @@ impl CoverageRecorder {
|
|||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn invoke_debugger_script(&self, test_input: &Path, output: &Path) -> Result<Child> {
|
fn invoke_debugger_script(&self, test_input: &Path, output: &Path) -> Result<Child> {
|
||||||
let script_path = self
|
|
||||||
.script_dir
|
|
||||||
.path()
|
|
||||||
.join("win64")
|
|
||||||
.join("libfuzzer-coverage")
|
|
||||||
.join("DumpCounters.js");
|
|
||||||
|
|
||||||
let should_disable_sympath = !self.config.target_env.contains_key("_NT_SYMBOL_PATH");
|
let should_disable_sympath = !self.config.target_env.contains_key("_NT_SYMBOL_PATH");
|
||||||
|
|
||||||
let cdb_cmd = format!(
|
let cdb_cmd = format!(
|
||||||
".scriptload {}; !dumpcounters {:?}, {}; q",
|
".scriptload {}; !dumpcounters {:?}, {}; q",
|
||||||
script_path.to_string_lossy(),
|
self.script_path.to_string_lossy(),
|
||||||
output.to_string_lossy(),
|
output.to_string_lossy(),
|
||||||
should_disable_sympath,
|
should_disable_sympath,
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user