Re-add drcov for both usermode and systemmode. (#2573)
* re-add drcov for both usermode and systemmode.
This commit is contained in:
parent
27677a6461
commit
7344fdf059
@ -233,11 +233,11 @@ pub fn fuzz() {
|
|||||||
let core = core_id.0;
|
let core = core_id.0;
|
||||||
cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}"));
|
cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}"));
|
||||||
|
|
||||||
let emulator_modules = tuple_list!(DrCovModule::new(
|
let emulator_modules = tuple_list!(DrCovModule::builder()
|
||||||
StdAddressFilter::default(),
|
.filter(StdAddressFilter::default())
|
||||||
cov_path,
|
.filename(cov_path)
|
||||||
false,
|
.full_trace(false)
|
||||||
));
|
.build());
|
||||||
|
|
||||||
let emulator = Emulator::empty()
|
let emulator = Emulator::empty()
|
||||||
.qemu(qemu)
|
.qemu(qemu)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
use std::ptr::addr_of_mut;
|
||||||
use std::{path::PathBuf, sync::Mutex};
|
use std::{path::PathBuf, sync::Mutex};
|
||||||
|
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
@ -7,9 +9,11 @@ use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter};
|
|||||||
use rangemap::RangeMap;
|
use rangemap::RangeMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
use crate::modules::{NopPageFilter, NOP_PAGE_FILTER};
|
||||||
use crate::{
|
use crate::{
|
||||||
emu::EmulatorModules,
|
emu::EmulatorModules,
|
||||||
modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple},
|
modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple, NopAddressFilter},
|
||||||
qemu::Hook,
|
qemu::Hook,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,14 +39,86 @@ impl DrCovMetadata {
|
|||||||
|
|
||||||
libafl_bolts::impl_serdeany!(DrCovMetadata);
|
libafl_bolts::impl_serdeany!(DrCovMetadata);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DrCovModuleBuilder<F> {
|
||||||
|
filter: Option<F>,
|
||||||
|
module_mapping: Option<RangeMap<usize, (u16, String)>>,
|
||||||
|
filename: Option<PathBuf>,
|
||||||
|
full_trace: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> DrCovModuleBuilder<F>
|
||||||
|
where
|
||||||
|
F: AddressFilter,
|
||||||
|
{
|
||||||
|
pub fn build(self) -> DrCovModule<F> {
|
||||||
|
DrCovModule::new(
|
||||||
|
self.filter.unwrap(),
|
||||||
|
self.filename.unwrap(),
|
||||||
|
self.module_mapping,
|
||||||
|
self.full_trace.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filter<F2>(self, filter: F2) -> DrCovModuleBuilder<F2> {
|
||||||
|
DrCovModuleBuilder {
|
||||||
|
filter: Some(filter),
|
||||||
|
module_mapping: self.module_mapping,
|
||||||
|
filename: self.filename,
|
||||||
|
full_trace: self.full_trace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn module_mapping(self, module_mapping: RangeMap<usize, (u16, String)>) -> Self {
|
||||||
|
Self {
|
||||||
|
filter: self.filter,
|
||||||
|
module_mapping: Some(module_mapping),
|
||||||
|
filename: self.filename,
|
||||||
|
full_trace: self.full_trace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn filename(self, filename: PathBuf) -> Self {
|
||||||
|
Self {
|
||||||
|
filter: self.filter,
|
||||||
|
module_mapping: self.module_mapping,
|
||||||
|
filename: Some(filename),
|
||||||
|
full_trace: self.full_trace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn full_trace(self, full_trace: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
filter: self.filter,
|
||||||
|
module_mapping: self.module_mapping,
|
||||||
|
filename: self.filename,
|
||||||
|
full_trace: Some(full_trace),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DrCovModule<F> {
|
pub struct DrCovModule<F> {
|
||||||
filter: F,
|
filter: F,
|
||||||
module_mapping: RangeMap<usize, (u16, String)>,
|
module_mapping: Option<RangeMap<usize, (u16, String)>>,
|
||||||
filename: PathBuf,
|
filename: PathBuf,
|
||||||
full_trace: bool,
|
full_trace: bool,
|
||||||
drcov_len: usize,
|
drcov_len: usize,
|
||||||
}
|
}
|
||||||
|
impl DrCovModule<NopAddressFilter> {
|
||||||
|
#[must_use]
|
||||||
|
pub fn builder() -> DrCovModuleBuilder<NopAddressFilter> {
|
||||||
|
DrCovModuleBuilder {
|
||||||
|
filter: Some(NopAddressFilter),
|
||||||
|
module_mapping: None,
|
||||||
|
full_trace: None,
|
||||||
|
filename: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<F> DrCovModule<F>
|
impl<F> DrCovModule<F>
|
||||||
where
|
where
|
||||||
@ -50,7 +126,12 @@ where
|
|||||||
{
|
{
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[allow(clippy::let_underscore_untyped)]
|
#[allow(clippy::let_underscore_untyped)]
|
||||||
pub fn new(filter: F, filename: PathBuf, full_trace: bool) -> Self {
|
pub fn new(
|
||||||
|
filter: F,
|
||||||
|
filename: PathBuf,
|
||||||
|
module_mapping: Option<RangeMap<usize, (u16, String)>>,
|
||||||
|
full_trace: bool,
|
||||||
|
) -> Self {
|
||||||
if full_trace {
|
if full_trace {
|
||||||
let _ = DRCOV_IDS.lock().unwrap().insert(vec![]);
|
let _ = DRCOV_IDS.lock().unwrap().insert(vec![]);
|
||||||
}
|
}
|
||||||
@ -58,7 +139,7 @@ where
|
|||||||
let _ = DRCOV_LENGTHS.lock().unwrap().insert(HashMap::new());
|
let _ = DRCOV_LENGTHS.lock().unwrap().insert(HashMap::new());
|
||||||
Self {
|
Self {
|
||||||
filter,
|
filter,
|
||||||
module_mapping: RangeMap::new(),
|
module_mapping,
|
||||||
filename,
|
filename,
|
||||||
full_trace,
|
full_trace,
|
||||||
drcov_len: 0,
|
drcov_len: 0,
|
||||||
@ -77,6 +158,8 @@ where
|
|||||||
S: Unpin + UsesInput + HasMetadata,
|
S: Unpin + UsesInput + HasMetadata,
|
||||||
{
|
{
|
||||||
type ModuleAddressFilter = F;
|
type ModuleAddressFilter = F;
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
type ModulePageFilter = NopPageFilter;
|
||||||
|
|
||||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||||
where
|
where
|
||||||
@ -89,25 +172,47 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
fn first_exec<ET>(&mut self, emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
fn first_exec<ET>(&mut self, emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
||||||
where
|
where
|
||||||
ET: EmulatorModuleTuple<S>,
|
ET: EmulatorModuleTuple<S>,
|
||||||
{
|
{
|
||||||
let qemu = emulator_modules.qemu();
|
if self.module_mapping.is_none() {
|
||||||
|
log::info!("Auto-filling module mapping for DrCov module from QEMU mapping.");
|
||||||
|
|
||||||
for (i, (r, p)) in qemu
|
let qemu = emulator_modules.qemu();
|
||||||
.mappings()
|
|
||||||
.filter_map(|m| {
|
let mut module_mapping: RangeMap<usize, (u16, String)> = RangeMap::new();
|
||||||
m.path()
|
|
||||||
.map(|p| ((m.start() as usize)..(m.end() as usize), p.to_string()))
|
for (i, (r, p)) in qemu
|
||||||
.filter(|(_, p)| !p.is_empty())
|
.mappings()
|
||||||
})
|
.filter_map(|m| {
|
||||||
.enumerate()
|
m.path()
|
||||||
{
|
.map(|p| ((m.start() as usize)..(m.end() as usize), p.to_string()))
|
||||||
self.module_mapping.insert(r, (i as u16, p));
|
.filter(|(_, p)| !p.is_empty())
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
module_mapping.insert(r, (i as u16, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.module_mapping = Some(module_mapping);
|
||||||
|
} else {
|
||||||
|
log::info!("Using user-provided module mapping for DrCov module.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
fn first_exec<ET>(&mut self, _emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
||||||
|
where
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
{
|
||||||
|
assert!(
|
||||||
|
self.module_mapping.is_some(),
|
||||||
|
"DrCov should have a module mapping already set."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn post_exec<OT, ET>(
|
fn post_exec<OT, ET>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_emulator_modules: &mut EmulatorModules<ET, S>,
|
_emulator_modules: &mut EmulatorModules<ET, S>,
|
||||||
@ -127,13 +232,18 @@ where
|
|||||||
for id in DRCOV_IDS.lock().unwrap().as_ref().unwrap() {
|
for id in DRCOV_IDS.lock().unwrap().as_ref().unwrap() {
|
||||||
'pcs_full: for (pc, idm) in DRCOV_MAP.lock().unwrap().as_ref().unwrap() {
|
'pcs_full: for (pc, idm) in DRCOV_MAP.lock().unwrap().as_ref().unwrap() {
|
||||||
let mut module_found = false;
|
let mut module_found = false;
|
||||||
for module in self.module_mapping.iter() {
|
// # Safety
|
||||||
let (range, (_, _)) = module;
|
//
|
||||||
if *pc >= range.start.try_into().unwrap()
|
// Module mapping is already set. It's checked or filled when the module is first run.
|
||||||
&& *pc <= range.end.try_into().unwrap()
|
unsafe {
|
||||||
{
|
for module in self.module_mapping.as_ref().unwrap_unchecked().iter() {
|
||||||
module_found = true;
|
let (range, (_, _)) = module;
|
||||||
break;
|
if *pc >= range.start.try_into().unwrap()
|
||||||
|
&& *pc <= range.end.try_into().unwrap()
|
||||||
|
{
|
||||||
|
module_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !module_found {
|
if !module_found {
|
||||||
@ -155,9 +265,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrCovWriter::new(&self.module_mapping)
|
// # Safety
|
||||||
.write(&self.filename, &drcov_vec)
|
//
|
||||||
.expect("Failed to write coverage file");
|
// Module mapping is already set. It's checked or filled when the module is first run.
|
||||||
|
unsafe {
|
||||||
|
DrCovWriter::new(self.module_mapping.as_ref().unwrap_unchecked())
|
||||||
|
.write(&self.filename, &drcov_vec)
|
||||||
|
.expect("Failed to write coverage file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.drcov_len = DRCOV_IDS.lock().unwrap().as_ref().unwrap().len();
|
self.drcov_len = DRCOV_IDS.lock().unwrap().as_ref().unwrap().len();
|
||||||
} else {
|
} else {
|
||||||
@ -165,13 +280,18 @@ where
|
|||||||
let mut drcov_vec = Vec::<DrCovBasicBlock>::new();
|
let mut drcov_vec = Vec::<DrCovBasicBlock>::new();
|
||||||
'pcs: for (pc, _) in DRCOV_MAP.lock().unwrap().as_ref().unwrap() {
|
'pcs: for (pc, _) in DRCOV_MAP.lock().unwrap().as_ref().unwrap() {
|
||||||
let mut module_found = false;
|
let mut module_found = false;
|
||||||
for module in self.module_mapping.iter() {
|
// # Safety
|
||||||
let (range, (_, _)) = module;
|
//
|
||||||
if *pc >= range.start.try_into().unwrap()
|
// Module mapping is already set. It's checked or filled when the module is first run.
|
||||||
&& *pc <= range.end.try_into().unwrap()
|
unsafe {
|
||||||
{
|
for module in self.module_mapping.as_ref().unwrap_unchecked().iter() {
|
||||||
module_found = true;
|
let (range, (_, _)) = module;
|
||||||
break;
|
if *pc >= range.start.try_into().unwrap()
|
||||||
|
&& *pc <= range.end.try_into().unwrap()
|
||||||
|
{
|
||||||
|
module_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !module_found {
|
if !module_found {
|
||||||
@ -190,9 +310,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrCovWriter::new(&self.module_mapping)
|
// # Safety
|
||||||
.write(&self.filename, &drcov_vec)
|
//
|
||||||
.expect("Failed to write coverage file");
|
// Module mapping is already set. It's checked or filled when the module is first run.
|
||||||
|
unsafe {
|
||||||
|
DrCovWriter::new(self.module_mapping.as_ref().unwrap_unchecked())
|
||||||
|
.write(&self.filename, &drcov_vec)
|
||||||
|
.expect("Failed to write coverage file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.drcov_len = DRCOV_MAP.lock().unwrap().as_ref().unwrap().len();
|
self.drcov_len = DRCOV_MAP.lock().unwrap().as_ref().unwrap().len();
|
||||||
}
|
}
|
||||||
@ -205,6 +330,16 @@ where
|
|||||||
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter {
|
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter {
|
||||||
&mut self.filter
|
&mut self.filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
fn page_filter(&self) -> &Self::ModulePageFilter {
|
||||||
|
&NopPageFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter {
|
||||||
|
unsafe { addr_of_mut!(NOP_PAGE_FILTER).as_mut().unwrap().get_mut() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_unique_block_ids<ET, F, S>(
|
pub fn gen_unique_block_ids<ET, F, S>(
|
@ -18,7 +18,7 @@ pub mod systemmode;
|
|||||||
pub use systemmode::*;
|
pub use systemmode::*;
|
||||||
|
|
||||||
pub mod edges;
|
pub mod edges;
|
||||||
pub use edges::EdgeCoverageModule;
|
pub use edges::*;
|
||||||
|
|
||||||
#[cfg(not(cpu_target = "hexagon"))]
|
#[cfg(not(cpu_target = "hexagon"))]
|
||||||
pub mod calls;
|
pub mod calls;
|
||||||
@ -30,6 +30,11 @@ pub mod cmplog;
|
|||||||
#[cfg(not(any(cpu_target = "mips", cpu_target = "hexagon")))]
|
#[cfg(not(any(cpu_target = "mips", cpu_target = "hexagon")))]
|
||||||
pub use cmplog::CmpLogModule;
|
pub use cmplog::CmpLogModule;
|
||||||
|
|
||||||
|
#[cfg(not(cpu_target = "hexagon"))]
|
||||||
|
pub mod drcov;
|
||||||
|
#[cfg(not(cpu_target = "hexagon"))]
|
||||||
|
pub use drcov::*;
|
||||||
|
|
||||||
use crate::{emu::EmulatorModules, Qemu};
|
use crate::{emu::EmulatorModules, Qemu};
|
||||||
|
|
||||||
/// A module for `libafl_qemu`.
|
/// A module for `libafl_qemu`.
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
#[cfg(not(cpu_target = "hexagon"))]
|
|
||||||
pub mod drcov;
|
|
||||||
|
|
||||||
#[cfg(not(cpu_target = "hexagon"))]
|
|
||||||
pub use drcov::DrCovModule;
|
|
||||||
|
|
||||||
#[cfg(feature = "injections")]
|
#[cfg(feature = "injections")]
|
||||||
pub mod injections;
|
pub mod injections;
|
||||||
#[cfg(feature = "injections")]
|
#[cfg(feature = "injections")]
|
||||||
@ -12,9 +6,7 @@ pub use injections::InjectionModule;
|
|||||||
#[cfg(not(cpu_target = "hexagon"))]
|
#[cfg(not(cpu_target = "hexagon"))]
|
||||||
pub mod snapshot;
|
pub mod snapshot;
|
||||||
#[cfg(not(cpu_target = "hexagon"))]
|
#[cfg(not(cpu_target = "hexagon"))]
|
||||||
pub use snapshot::IntervalSnapshotFilter;
|
pub use snapshot::{IntervalSnapshotFilter, SnapshotModule};
|
||||||
#[cfg(not(cpu_target = "hexagon"))]
|
|
||||||
pub use snapshot::SnapshotModule;
|
|
||||||
|
|
||||||
#[cfg(not(cpu_target = "hexagon"))]
|
#[cfg(not(cpu_target = "hexagon"))]
|
||||||
pub mod asan;
|
pub mod asan;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user