Cmplog routines mutator (#204)

* save

* routines in meta

* execute passes

* fix cmplog rtn pass

* clippy
This commit is contained in:
Andrea Fioraldi 2021-07-05 09:54:44 +02:00 committed by GitHub
parent 84a9e36acf
commit 5b76c22ea7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 51 deletions

View File

@ -443,9 +443,25 @@ where
} }
} }
} }
CmpValues::Bytes(_v) => { CmpValues::Bytes(v) => {
// TODO 'outer: for i in off..len {
// buffer_copy(input.bytes_mut(), token, 0, off, len); let mut size = core::cmp::min(v.0.len(), len - i);
while size != 0 {
if v.0[0..size] == input.bytes()[i..i + size] {
buffer_copy(input.bytes_mut(), &v.1, 0, i, size);
break 'outer;
}
size -= 1;
}
size = core::cmp::min(v.1.len(), len - i);
while size != 0 {
if v.1[0..size] == input.bytes()[i..i + size] {
buffer_copy(input.bytes_mut(), &v.0, 0, i, size);
break 'outer;
}
size -= 1;
}
}
} }
} }

View File

@ -188,6 +188,9 @@ impl CompilerWrapper for ClangWrapper {
args.push(self.wrapped_cc.clone()); args.push(self.wrapped_cc.clone());
} }
args.extend_from_slice(self.base_args.as_slice()); args.extend_from_slice(self.base_args.as_slice());
if !self.passes.is_empty() {
args.push("-fno-experimental-new-pass-manager".into());
}
for pass in &self.passes { for pass in &self.passes {
args.push("-Xclang".into()); args.push("-Xclang".into());
args.push("-load".into()); args.push("-load".into());

View File

@ -247,7 +247,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
/* iterate over all functions, bbs and instruction and add suitable calls */ /* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) { for (auto &F : M) {
if (!isIgnoreFunction(&F)) continue; if (isIgnoreFunction(&F)) continue;
for (auto &BB : F) { for (auto &BB : F) {

View File

@ -205,3 +205,4 @@ void __cmplog_rtn_llvm_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstri
get_llvm_stdstring(stdstring2)); get_llvm_stdstring(stdstring2));
} }

View File

@ -12,7 +12,7 @@
#define CMPLOG_RTN_LEN 32 #define CMPLOG_RTN_LEN 32
#define CMPLOG_MAP_RTN_H ((CMPLOG_MAP_H * sizeof(CmpLogOperands)) / sizeof(CmpLogRoutine)) #define CMPLOG_MAP_RTN_H ((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine))
#define CMPLOG_KIND_INS 0 #define CMPLOG_KIND_INS 0
#define CMPLOG_KIND_RTN 1 #define CMPLOG_KIND_RTN 1
@ -23,10 +23,10 @@ typedef struct CmpLogHeader {
uint8_t kind; uint8_t kind;
} CmpLogHeader; } CmpLogHeader;
typedef struct CmpLogOperands { typedef struct CmpLogInstruction {
uint64_t v0; uint64_t v0;
uint64_t v1; uint64_t v1;
} CmpLogOperands; } CmpLogInstruction;
typedef struct CmpLogRoutine { typedef struct CmpLogRoutine {
uint8_t v0[CMPLOG_RTN_LEN]; uint8_t v0[CMPLOG_RTN_LEN];
@ -36,7 +36,7 @@ typedef struct CmpLogRoutine {
typedef struct CmpLogMap { typedef struct CmpLogMap {
CmpLogHeader headers[CMPLOG_MAP_W]; CmpLogHeader headers[CMPLOG_MAP_W];
union { union {
CmpLogOperands operands[CMPLOG_MAP_W][CMPLOG_MAP_H]; CmpLogInstruction operands[CMPLOG_MAP_W][CMPLOG_MAP_H];
CmpLogRoutine routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_H]; CmpLogRoutine routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_H];
} vals; } vals;
} CmpLogMap; } CmpLogMap;

View File

@ -13,6 +13,12 @@ use crate::{CMPLOG_MAP_H, CMPLOG_MAP_W};
/// The `CmpLog` map size /// The `CmpLog` map size
pub const CMPLOG_MAP_SIZE: usize = CMPLOG_MAP_W * CMPLOG_MAP_H; pub const CMPLOG_MAP_SIZE: usize = CMPLOG_MAP_W * CMPLOG_MAP_H;
/// The size of a logged routine argument in bytes
pub const CMPLOG_RTN_LEN: usize = 32;
pub const CMPLOG_MAP_RTN_H: usize = (CMPLOG_MAP_H * core::mem::size_of::<CmpLogInstruction>())
/ core::mem::size_of::<CmpLogRoutine>();
/// `CmpLog` instruction kind /// `CmpLog` instruction kind
pub const CMPLOG_KIND_INS: u8 = 0; pub const CMPLOG_KIND_INS: u8 = 0;
/// `CmpLog` return kind /// `CmpLog` return kind
@ -30,26 +36,31 @@ pub struct CmpLogHeader {
/// The operands logged during `CmpLog`. /// The operands logged during `CmpLog`.
#[repr(C)] #[repr(C)]
#[derive(Default, Debug, Clone, Copy)] #[derive(Default, Debug, Clone, Copy)]
pub struct CmpLogOperands(u64, u64); pub struct CmpLogInstruction(u64, u64);
/// The routine arguments logged during `CmpLog`.
#[repr(C)]
#[derive(Default, Debug, Clone, Copy)]
pub struct CmpLogRoutine([u8; CMPLOG_RTN_LEN], [u8; CMPLOG_RTN_LEN]);
#[repr(C)]
#[derive(Clone, Copy)]
pub union CmpLogVals {
operands: [[CmpLogInstruction; CMPLOG_MAP_H]; CMPLOG_MAP_W],
routines: [[CmpLogRoutine; CMPLOG_MAP_RTN_H]; CMPLOG_MAP_W],
}
/// A struct containing the `CmpLog` metadata for a `LibAFL` run. /// A struct containing the `CmpLog` metadata for a `LibAFL` run.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone, Copy)] #[derive(Clone, Copy)]
pub struct CmpLogMap { pub struct CmpLogMap {
headers: [CmpLogHeader; CMPLOG_MAP_W], headers: [CmpLogHeader; CMPLOG_MAP_W],
operands: [[CmpLogOperands; CMPLOG_MAP_H]; CMPLOG_MAP_W], vals: CmpLogVals,
} }
impl Default for CmpLogMap { impl Default for CmpLogMap {
fn default() -> Self { fn default() -> Self {
Self { unsafe { core::mem::zeroed() }
headers: [CmpLogHeader {
hits: 0,
shape: 0,
kind: 0,
}; CMPLOG_MAP_W],
operands: [[CmpLogOperands(0, 0); CMPLOG_MAP_H]; CMPLOG_MAP_W],
}
} }
} }
@ -63,50 +74,56 @@ impl CmpMap for CmpLogMap {
} }
fn usable_executions_for(&self, idx: usize) -> usize { fn usable_executions_for(&self, idx: usize) -> usize {
if self.headers[idx].kind == CMPLOG_KIND_INS {
if self.executions_for(idx) < CMPLOG_MAP_H { if self.executions_for(idx) < CMPLOG_MAP_H {
self.executions_for(idx) self.executions_for(idx)
} else { } else {
CMPLOG_MAP_H CMPLOG_MAP_H
} }
} else if self.executions_for(idx) < CMPLOG_MAP_RTN_H {
self.executions_for(idx)
} else {
CMPLOG_MAP_RTN_H
}
} }
fn values_of(&self, idx: usize, execution: usize) -> CmpValues { fn values_of(&self, idx: usize, execution: usize) -> CmpValues {
if self.headers[idx].kind == CMPLOG_KIND_INS { if self.headers[idx].kind == CMPLOG_KIND_INS {
unsafe {
match self.headers[idx].shape { match self.headers[idx].shape {
1 => { 1 => CmpValues::U8((
return CmpValues::U8(( self.vals.operands[idx][execution].0 as u8,
self.operands[idx][execution].0 as u8, self.vals.operands[idx][execution].1 as u8,
self.operands[idx][execution].1 as u8, )),
2 => CmpValues::U16((
self.vals.operands[idx][execution].0 as u16,
self.vals.operands[idx][execution].1 as u16,
)),
4 => CmpValues::U32((
self.vals.operands[idx][execution].0 as u32,
self.vals.operands[idx][execution].1 as u32,
)),
8 => CmpValues::U64((
self.vals.operands[idx][execution].0 as u64,
self.vals.operands[idx][execution].1 as u64,
)),
other => panic!("Invalid CmpLog shape {}", other),
}
}
} else {
unsafe {
CmpValues::Bytes((
self.vals.routines[idx][execution].0.to_vec(),
self.vals.routines[idx][execution].1.to_vec(),
)) ))
} }
2 => {
return CmpValues::U16((
self.operands[idx][execution].0 as u16,
self.operands[idx][execution].1 as u16,
))
} }
4 => {
return CmpValues::U32((
self.operands[idx][execution].0 as u32,
self.operands[idx][execution].1 as u32,
))
}
8 => {
return CmpValues::U64((
self.operands[idx][execution].0 as u64,
self.operands[idx][execution].1 as u64,
))
}
_ => {}
};
}
// TODO bytes
CmpValues::Bytes((vec![], vec![]))
} }
fn reset(&mut self) -> Result<(), Error> { fn reset(&mut self) -> Result<(), Error> {
// For performance, we reset just the headers
self.headers = unsafe { core::mem::zeroed() }; self.headers = unsafe { core::mem::zeroed() };
// self.operands = unsafe { core::mem::zeroed() }; // self.vals.operands = unsafe { core::mem::zeroed() };
Ok(()) Ok(())
} }
} }
@ -119,7 +136,9 @@ pub static mut libafl_cmplog_map: CmpLogMap = CmpLogMap {
shape: 0, shape: 0,
kind: 0, kind: 0,
}; CMPLOG_MAP_W], }; CMPLOG_MAP_W],
operands: [[CmpLogOperands(0, 0); CMPLOG_MAP_H]; CMPLOG_MAP_W], vals: CmpLogVals {
operands: [[CmpLogInstruction(0, 0); CMPLOG_MAP_H]; CMPLOG_MAP_W],
},
}; };
pub use libafl_cmplog_map as CMPLOG_MAP; pub use libafl_cmplog_map as CMPLOG_MAP;