Drcov remodelling (#415)

* drcov remodelling

* fmt

* fix

Co-authored-by: tokatoka <tokazerkje@outlook.com>
This commit is contained in:
Dominik Maier 2021-12-23 17:13:18 +01:00 committed by GitHub
parent 6274ad4594
commit 6b5181250c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 38 deletions

View File

@ -76,7 +76,7 @@ where
libc::raise(libc::SIGABRT); libc::raise(libc::SIGABRT);
} }
} }
self.helper.post_exec(input); self.helper.post_exec(input)?;
res res
} }
} }

View File

@ -2,7 +2,7 @@ use ahash::AHasher;
use std::hash::Hasher; use std::hash::Hasher;
use libafl::inputs::{HasTargetBytes, Input}; use libafl::inputs::{HasTargetBytes, Input};
use libafl::Error;
use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter}; use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter};
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@ -69,7 +69,7 @@ pub trait FridaHelper<'a> {
fn pre_exec<I: Input + HasTargetBytes>(&mut self, input: &I); fn pre_exec<I: Input + HasTargetBytes>(&mut self, input: &I);
/// Called after execution of an input /// Called after execution of an input
fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I); fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error>;
/// Returns `true` if stalker is enabled /// Returns `true` if stalker is enabled
fn stalker_enabled(&self) -> bool; fn stalker_enabled(&self) -> bool;
@ -124,13 +124,14 @@ impl<'a> FridaHelper<'a> for FridaInstrumentationHelper<'a> {
} }
} }
fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) { fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
if self.options.drcov_enabled() { if self.options.drcov_enabled() {
let mut hasher = AHasher::new_with_keys(0, 0); let mut hasher = AHasher::new_with_keys(0, 0);
hasher.write(input.target_bytes().as_slice()); hasher.write(input.target_bytes().as_slice());
let filename = format!("./coverage/{:016x}.drcov", hasher.finish(),); let filename = format!("./coverage/{:016x}.drcov", hasher.finish(),);
DrCovWriter::new(&filename, &self.ranges, &mut self.drcov_basic_blocks).write(); DrCovWriter::new(&self.ranges).write(&filename, &self.drcov_basic_blocks)?;
self.drcov_basic_blocks.clear();
} }
#[cfg(unix)] #[cfg(unix)]
@ -145,6 +146,7 @@ impl<'a> FridaHelper<'a> for FridaInstrumentationHelper<'a> {
.poison(slice.as_ptr() as usize, slice.len()); .poison(slice.as_ptr() as usize, slice.len());
self.asan_runtime.reset_allocations(); self.asan_runtime.reset_allocations();
} }
Ok(())
} }
fn stalker_enabled(&self) -> bool { fn stalker_enabled(&self) -> bool {

View File

@ -2,26 +2,22 @@
//! writing basic-block trace files to be read by coverage analysis tools, such as [Lighthouse](https://github.com/gaasedelen/lighthouse), //! writing basic-block trace files to be read by coverage analysis tools, such as [Lighthouse](https://github.com/gaasedelen/lighthouse),
//! [bncov](https://github.com/ForAllSecure/bncov), [dragondance](https://github.com/0ffffffffh/dragondance), etc. //! [bncov](https://github.com/ForAllSecure/bncov), [dragondance](https://github.com/0ffffffffh/dragondance), etc.
use libafl::Error;
use rangemap::RangeMap; use rangemap::RangeMap;
use std::{ use std::{
fs::File, fs::File,
io::{BufWriter, Write}, io::{BufWriter, Write},
path::Path,
}; };
/// A basic block struct /// A basic block struct
#[derive(Clone, Copy)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DrCovBasicBlock { pub struct DrCovBasicBlock {
start: usize, pub start: usize,
end: usize, pub end: usize,
}
/// A writer for `DrCov` files
pub struct DrCovWriter<'a> {
writer: BufWriter<File>,
module_mapping: &'a RangeMap<usize, (u16, String)>,
basic_blocks: &'a mut Vec<DrCovBasicBlock>,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)] #[repr(C)]
struct DrCovBasicBlockEntry { struct DrCovBasicBlockEntry {
start: u32, start: u32,
@ -29,46 +25,54 @@ struct DrCovBasicBlockEntry {
mod_id: u16, mod_id: u16,
} }
/// A writer for `DrCov` files
pub struct DrCovWriter<'a> {
module_mapping: &'a RangeMap<usize, (u16, String)>,
}
impl DrCovBasicBlock { impl DrCovBasicBlock {
/// Create a new [`DrCovBasicBlock`] with the given `start` and `end` addresses. /// Create a new [`DrCovBasicBlock`] with the given `start` and `end` addresses.
#[must_use] #[must_use]
pub fn new(start: usize, end: usize) -> Self { pub fn new(start: usize, end: usize) -> Self {
Self { start, end } Self { start, end }
} }
/// Create a new [`DrCovBasicBlock`] with a given `start` address and a block size.
#[must_use]
pub fn new_with_size(start: usize, size: usize) -> Self {
Self::new(start, start + size)
}
} }
impl<'a> DrCovWriter<'a> { impl<'a> DrCovWriter<'a> {
/// Create a new [`DrCovWriter`] /// Create a new [`DrCovWriter`]
pub fn new( #[must_use]
path: &str, pub fn new(module_mapping: &'a RangeMap<usize, (u16, String)>) -> Self {
module_mapping: &'a RangeMap<usize, (u16, String)>, Self { module_mapping }
basic_blocks: &'a mut Vec<DrCovBasicBlock>,
) -> Self {
Self {
writer: BufWriter::new(
File::create(path).expect("Unable to create file for coverage data"),
),
module_mapping,
basic_blocks,
}
} }
/// Write the `DrCov` file. /// Write the list of basic blocks to a `DrCov` file.
pub fn write(&mut self) { pub fn write<P>(&mut self, path: P, basic_blocks: &[DrCovBasicBlock]) -> Result<(), Error>
self.writer where
P: AsRef<Path>,
{
let mut writer = BufWriter::new(File::create(path)?);
writer
.write_all(b"DRCOV VERSION: 2\nDRCOV FLAVOR: libafl\n") .write_all(b"DRCOV VERSION: 2\nDRCOV FLAVOR: libafl\n")
.unwrap(); .unwrap();
let modules: Vec<(&std::ops::Range<usize>, &(u16, String))> = let modules: Vec<(&std::ops::Range<usize>, &(u16, String))> =
self.module_mapping.iter().collect(); self.module_mapping.iter().collect();
self.writer writer
.write_all(format!("Module Table: version 2, count {}\n", modules.len()).as_bytes()) .write_all(format!("Module Table: version 2, count {}\n", modules.len()).as_bytes())
.unwrap(); .unwrap();
self.writer writer
.write_all(b"Columns: id, base, end, entry, checksum, timestamp, path\n") .write_all(b"Columns: id, base, end, entry, checksum, timestamp, path\n")
.unwrap(); .unwrap();
for module in modules { for module in modules {
let (range, (id, path)) = module; let (range, (id, path)) = module;
self.writer writer
.write_all( .write_all(
format!( format!(
"{:03}, 0x{:x}, 0x{:x}, 0x00000000, 0x00000000, 0x00000000, {}\n", "{:03}, 0x{:x}, 0x{:x}, 0x00000000, 0x00000000, 0x00000000, {}\n",
@ -78,23 +82,24 @@ impl<'a> DrCovWriter<'a> {
) )
.unwrap(); .unwrap();
} }
self.writer writer
.write_all(format!("BB Table: {} bbs\n", self.basic_blocks.len()).as_bytes()) .write_all(format!("BB Table: {} bbs\n", basic_blocks.len()).as_bytes())
.unwrap(); .unwrap();
for block in self.basic_blocks.drain(0..) { for block in basic_blocks {
let (range, (id, _)) = self.module_mapping.get_key_value(&block.start).unwrap(); let (range, (id, _)) = self.module_mapping.get_key_value(&block.start).unwrap();
let basic_block = DrCovBasicBlockEntry { let basic_block = DrCovBasicBlockEntry {
start: (block.start - range.start) as u32, start: (block.start - range.start) as u32,
size: (block.end - block.start) as u16, size: (block.end - block.start) as u16,
mod_id: *id, mod_id: *id,
}; };
self.writer writer
.write_all(unsafe { .write_all(unsafe {
std::slice::from_raw_parts(&basic_block as *const _ as *const u8, 8) std::slice::from_raw_parts(&basic_block as *const _ as *const u8, 8)
}) })
.unwrap(); .unwrap();
} }
self.writer.flush().unwrap(); writer.flush()?;
Ok(())
} }
} }