mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-13 02:28:09 +00:00
@ -15,6 +15,10 @@
|
|||||||
(thanks to @kcwu for raising the issues and providing support!)
|
(thanks to @kcwu for raising the issues and providing support!)
|
||||||
- more 64 bit archicture support by @maribu
|
- more 64 bit archicture support by @maribu
|
||||||
- afl-cc:
|
- afl-cc:
|
||||||
|
- Added instrumenting hidden edges (approx 5% edges were not instrumented,
|
||||||
|
LLVM sancov overall misses 8% of edges compared to our implementation)
|
||||||
|
Note that is is currently only implemented for our PCGUARD plugin, not
|
||||||
|
LTO, CLASSIC, etc.!
|
||||||
- Fix to make AFL_SAN_NO_INST work with gcc_plugin
|
- Fix to make AFL_SAN_NO_INST work with gcc_plugin
|
||||||
- MacOS aflpp driver compilation fix (-fsanitize=fuzzer implementation)
|
- MacOS aflpp driver compilation fix (-fsanitize=fuzzer implementation)
|
||||||
- Make AFL_DUMP_MAP_SIZE work even if the target has sanitizer issues
|
- Make AFL_DUMP_MAP_SIZE work even if the target has sanitizer issues
|
||||||
|
@ -869,10 +869,11 @@ Here are some of the most important caveats for AFL++:
|
|||||||
|
|
||||||
- There is no direct support for fuzzing network services, background daemons,
|
- There is no direct support for fuzzing network services, background daemons,
|
||||||
or interactive apps that require UI interaction to work. You may need to make
|
or interactive apps that require UI interaction to work. You may need to make
|
||||||
simple code changes to make them behave in a more traditional way. Preeny or
|
simple code changes to make them behave in a more traditional way. Preeny,
|
||||||
libdesock may offer a relatively simple option, too - see:
|
libdesock or desockmulti may offer a relatively simple option, too - see:
|
||||||
[https://github.com/zardus/preeny](https://github.com/zardus/preeny) or
|
[https://github.com/zardus/preeny](https://github.com/zardus/preeny) or
|
||||||
[https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock)
|
[https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock)
|
||||||
|
[https://github.com/zyingp/desockmulti](https://github.com/zyingp/desockmulti)
|
||||||
|
|
||||||
Some useful tips for modifying network-based services can be also found at:
|
Some useful tips for modifying network-based services can be also found at:
|
||||||
[https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)
|
[https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)
|
||||||
|
@ -1216,7 +1216,6 @@ u8 *describe_op(afl_state_t *, u8, size_t);
|
|||||||
#endif
|
#endif
|
||||||
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
||||||
u8 has_new_bits(afl_state_t *, u8 *);
|
u8 has_new_bits(afl_state_t *, u8 *);
|
||||||
u8 has_new_bits_unclassified(afl_state_t *, u8 *);
|
|
||||||
#ifndef AFL_SHOWMAP
|
#ifndef AFL_SHOWMAP
|
||||||
void classify_counts(afl_forkserver_t *);
|
void classify_counts(afl_forkserver_t *);
|
||||||
#endif
|
#endif
|
||||||
|
@ -242,6 +242,7 @@ typedef enum fsrv_run_result {
|
|||||||
|
|
||||||
void afl_fsrv_init(afl_forkserver_t *fsrv);
|
void afl_fsrv_init(afl_forkserver_t *fsrv);
|
||||||
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
|
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
|
||||||
|
void afl_fsrv_setup_preload(afl_forkserver_t *fsrv, char *argv0);
|
||||||
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||||
volatile u8 *stop_soon_p, u8 debug_child_output);
|
volatile u8 *stop_soon_p, u8 debug_child_output);
|
||||||
u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
|
u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
|
||||||
|
@ -333,7 +333,7 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); }
|
if (getenv("AFL_DEBUG")) { DEBUGF("Instrumentation disabled\n"); }
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -396,7 +396,7 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (debug) { DEBUGF("Instrument disabled\n"); }
|
if (debug) { DEBUGF("Instrumentation disabled\n"); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
|
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
// #include "llvm/IR/Verifier.h"
|
||||||
#if LLVM_VERSION_MAJOR >= 15
|
#if LLVM_VERSION_MAJOR >= 15
|
||||||
#if LLVM_VERSION_MAJOR < 17
|
#if LLVM_VERSION_MAJOR < 17
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
@ -76,9 +77,9 @@
|
|||||||
#else
|
#else
|
||||||
#include "llvm/Transforms/Utils/Instrumentation.h"
|
#include "llvm/Transforms/Utils/Instrumentation.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -206,7 +207,8 @@ class ModuleSanitizerCoverageAFL
|
|||||||
|
|
||||||
SanitizerCoverageOptions Options;
|
SanitizerCoverageOptions Options;
|
||||||
|
|
||||||
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0;
|
uint32_t instr = 0, selects = 0, hidden = 0, unhandled = 0, skippedbb = 0,
|
||||||
|
dump_cc = 0;
|
||||||
GlobalVariable *AFLMapPtr = NULL;
|
GlobalVariable *AFLMapPtr = NULL;
|
||||||
ConstantInt *One = NULL;
|
ConstantInt *One = NULL;
|
||||||
ConstantInt *Zero = NULL;
|
ConstantInt *Zero = NULL;
|
||||||
@ -279,7 +281,7 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); }
|
if (getenv("AFL_DEBUG")) { DEBUGF("Instrumentation disabled\n"); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,9 +507,16 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
|||||||
getenv("AFL_USE_TSAN") ? ", TSAN" : "",
|
getenv("AFL_USE_TSAN") ? ", TSAN" : "",
|
||||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||||
|
char buf[32] = "";
|
||||||
|
if (skippedbb) {
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), " %u instrumentations saved.", skippedbb);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
OKF("Instrumented %u locations with no collisions (%s mode) of which are "
|
OKF("Instrumented %u locations with no collisions (%s mode) of which are "
|
||||||
"%u handled and %u unhandled selects.",
|
"%u handled and %u unhandled special instructions.%s",
|
||||||
instr, modeline, selects, unhandled);
|
instr, modeline, selects + hidden, unhandled, buf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -781,11 +790,14 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
|
|
||||||
if (AllBlocks.empty()) return false;
|
if (AllBlocks.empty()) return false;
|
||||||
|
|
||||||
uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0;
|
uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0, cnt_hidden_sel = 0,
|
||||||
|
cnt_hidden_sel_inc = 0, skip_blocks = 0;
|
||||||
static uint32_t first = 1;
|
static uint32_t first = 1;
|
||||||
|
|
||||||
for (auto &BB : F) {
|
for (auto &BB : F) {
|
||||||
|
|
||||||
|
bool block_is_instrumented = false;
|
||||||
|
|
||||||
for (auto &IN : BB) {
|
for (auto &IN : BB) {
|
||||||
|
|
||||||
CallInst *callInst = nullptr;
|
CallInst *callInst = nullptr;
|
||||||
@ -799,11 +811,11 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
if (!FuncName.compare(StringRef("dlopen")) ||
|
if (!FuncName.compare(StringRef("dlopen")) ||
|
||||||
!FuncName.compare(StringRef("_dlopen"))) {
|
!FuncName.compare(StringRef("_dlopen"))) {
|
||||||
|
|
||||||
fprintf(stderr,
|
WARNF(
|
||||||
"WARNING: dlopen() detected. To have coverage for a library "
|
"dlopen() detected. To have coverage for a library that your "
|
||||||
"that your target dlopen()'s this must either happen before "
|
"target dlopen()'s this must either happen before __AFL_INIT() "
|
||||||
"__AFL_INIT() or you must use AFL_PRELOAD to preload all "
|
"or you must use AFL_PRELOAD to preload all dlopen()'ed "
|
||||||
"dlopen()'ed libraries!\n");
|
"libraries!\n");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -811,53 +823,183 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
if (!FuncName.compare(StringRef("__afl_coverage_interesting"))) {
|
if (!FuncName.compare(StringRef("__afl_coverage_interesting"))) {
|
||||||
|
|
||||||
cnt_cov++;
|
cnt_cov++;
|
||||||
|
block_is_instrumented = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectInst *selectInst = nullptr;
|
bool instrumentInst = false;
|
||||||
|
ICmpInst *icmp;
|
||||||
|
FCmpInst *fcmp;
|
||||||
|
|
||||||
if ((selectInst = dyn_cast<SelectInst>(&IN))) {
|
if ((icmp = dyn_cast<ICmpInst>(&IN)) ||
|
||||||
|
(fcmp = dyn_cast<FCmpInst>(&IN)) || isa<SelectInst>(&IN)) {
|
||||||
|
|
||||||
Value *c = selectInst->getCondition();
|
// || isa<PHINode>(&IN)
|
||||||
auto t = c->getType();
|
|
||||||
if (t->getTypeID() == llvm::Type::IntegerTyID) {
|
|
||||||
|
|
||||||
cnt_sel++;
|
bool usedInBranch = false, usedInSelectDecision = false;
|
||||||
cnt_sel_inc += 2;
|
|
||||||
|
|
||||||
}
|
for (auto *U : IN.users()) {
|
||||||
|
|
||||||
else if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
if (isa<BranchInst>(U)) {
|
||||||
|
|
||||||
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
|
usedInBranch = true;
|
||||||
if (tt) {
|
break;
|
||||||
|
|
||||||
cnt_sel++;
|
}
|
||||||
cnt_sel_inc += (tt->getElementCount().getKnownMinValue() * 2);
|
|
||||||
|
if (auto *sel = dyn_cast<SelectInst>(U)) {
|
||||||
|
|
||||||
|
if (icmp && sel->getCondition() == icmp) {
|
||||||
|
|
||||||
|
usedInSelectDecision = true;
|
||||||
|
|
||||||
|
} else if (fcmp && sel->getCondition() == fcmp) {
|
||||||
|
|
||||||
|
usedInSelectDecision = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!usedInBranch && !usedInSelectDecision) {
|
||||||
|
|
||||||
|
// errs() << "Instrument! " << *(&IN) << "\n";
|
||||||
|
instrumentInst = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instrumentInst) {
|
||||||
|
|
||||||
|
block_is_instrumented = true;
|
||||||
|
SelectInst *selectInst;
|
||||||
|
ICmpInst *icmp;
|
||||||
|
FCmpInst *fcmp;
|
||||||
|
// PHINode *phiInst;
|
||||||
|
// errs() << "IN: " << *(&IN) << "\n";
|
||||||
|
|
||||||
|
/* if ((phiInst = dyn_cast<PHINode>(&IN))) {
|
||||||
|
|
||||||
|
cnt_hidden_sel++;
|
||||||
|
cnt_hidden_sel_inc += phiInst->getNumIncomingValues();
|
||||||
|
|
||||||
|
} else*/
|
||||||
|
|
||||||
|
if ((icmp = dyn_cast<ICmpInst>(&IN))) {
|
||||||
|
|
||||||
|
if (icmp->getType()->isIntegerTy(1)) {
|
||||||
|
|
||||||
|
cnt_sel++;
|
||||||
|
cnt_sel_inc += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
unhandled++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ((fcmp = dyn_cast<FCmpInst>(&IN))) {
|
||||||
|
|
||||||
|
if (fcmp->getType()->isIntegerTy(1)) {
|
||||||
|
|
||||||
|
cnt_sel++;
|
||||||
|
cnt_sel_inc += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
unhandled++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ((selectInst = dyn_cast<SelectInst>(&IN))) {
|
||||||
|
|
||||||
|
Value *c = selectInst->getCondition();
|
||||||
|
auto t = c->getType();
|
||||||
|
if (t->getTypeID() == llvm::Type::IntegerTyID) {
|
||||||
|
|
||||||
|
cnt_sel++;
|
||||||
|
cnt_sel_inc += 2;
|
||||||
|
|
||||||
|
} else if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
||||||
|
|
||||||
|
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
|
||||||
|
if (tt) {
|
||||||
|
|
||||||
|
cnt_sel++;
|
||||||
|
cnt_sel_inc += (tt->getElementCount().getKnownMinValue() * 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!be_quiet) {
|
||||||
|
|
||||||
|
WARNF("unknown select ID type: %u\n", t->getTypeID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} /*else {
|
||||||
|
|
||||||
|
cnt_hidden_sel++;
|
||||||
|
cnt_hidden_sel_inc += 2;
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block_is_instrumented && &BB != &BB.getParent()->getEntryBlock() &&
|
||||||
|
llvm::is_contained(AllBlocks, &BB)) {
|
||||||
|
|
||||||
|
Instruction *instr = &*BB.begin();
|
||||||
|
LLVMContext &Ctx = BB.getContext();
|
||||||
|
MDNode *md = MDNode::get(Ctx, MDString::get(Ctx, "skipinstrument"));
|
||||||
|
instr->setMetadata("tag", md);
|
||||||
|
skip_blocks++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateFunctionLocalArrays(F, AllBlocks, first + cnt_cov + cnt_sel_inc);
|
uint32_t xtra = 0;
|
||||||
|
if (skip_blocks < first + cnt_cov + cnt_sel_inc + cnt_hidden_sel_inc) {
|
||||||
|
|
||||||
|
xtra = first + cnt_cov + cnt_sel_inc + cnt_hidden_sel_inc - skip_blocks;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateFunctionLocalArrays(F, AllBlocks, xtra);
|
||||||
|
|
||||||
|
if (!FunctionGuardArray) {
|
||||||
|
|
||||||
|
WARNF(
|
||||||
|
"SANCOV: FunctionGuardArray is NULL, failed to emit instrumentation.");
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (first) { first = 0; }
|
if (first) { first = 0; }
|
||||||
selects += cnt_sel;
|
selects += cnt_sel;
|
||||||
|
hidden += cnt_hidden_sel;
|
||||||
|
|
||||||
uint32_t special = 0, local_selects = 0, skip_next = 0;
|
uint32_t special = 0, local_selects = 0, skip_select = 0, skip_icmp = 0;
|
||||||
|
// uint32_t skip_phi = 0;
|
||||||
|
|
||||||
for (auto &BB : F) {
|
for (auto &BB : F) {
|
||||||
|
|
||||||
|
// errs() << *(&BB) << "\n";
|
||||||
|
|
||||||
for (auto &IN : BB) {
|
for (auto &IN : BB) {
|
||||||
|
|
||||||
|
// errs() << *(&IN) << "\n";
|
||||||
CallInst *callInst = nullptr;
|
CallInst *callInst = nullptr;
|
||||||
|
|
||||||
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||||
@ -875,15 +1017,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
IRBuilder<> IRB(callInst);
|
IRBuilder<> IRB(callInst);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!FunctionGuardArray) {
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"SANCOV: FunctionGuardArray is NULL, failed to emit "
|
|
||||||
"instrumentation.");
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Value *GuardPtr = IRB.CreateIntToPtr(
|
Value *GuardPtr = IRB.CreateIntToPtr(
|
||||||
IRB.CreateAdd(
|
IRB.CreateAdd(
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
@ -897,132 +1030,324 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectInst *selectInst = nullptr;
|
bool instrumentInst = false;
|
||||||
|
ICmpInst *icmp;
|
||||||
|
FCmpInst *fcmp;
|
||||||
|
|
||||||
if (!skip_next && (selectInst = dyn_cast<SelectInst>(&IN))) {
|
if ((icmp = dyn_cast<ICmpInst>(&IN)) ||
|
||||||
|
(fcmp = dyn_cast<FCmpInst>(&IN)) || isa<SelectInst>(&IN)) {
|
||||||
|
|
||||||
uint32_t vector_cnt = 0;
|
// || isa<PHINode>(&IN)
|
||||||
Value *condition = selectInst->getCondition();
|
|
||||||
Value *result;
|
|
||||||
auto t = condition->getType();
|
|
||||||
IRBuilder<> IRB(selectInst->getNextNode());
|
|
||||||
|
|
||||||
if (t->getTypeID() == llvm::Type::IntegerTyID) {
|
bool usedInBranch = false, usedInSelectDecision = false;
|
||||||
|
|
||||||
if (!FunctionGuardArray) {
|
for (auto *U : IN.users()) {
|
||||||
|
|
||||||
fprintf(stderr,
|
if (isa<BranchInst>(U)) {
|
||||||
"SANCOV: FunctionGuardArray is NULL, failed to emit "
|
|
||||||
"instrumentation.");
|
usedInBranch = true;
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GuardPtr1 = IRB.CreateIntToPtr(
|
if (auto *sel = dyn_cast<SelectInst>(U)) {
|
||||||
IRB.CreateAdd(
|
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
|
||||||
ConstantInt::get(
|
|
||||||
IntptrTy,
|
|
||||||
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
|
|
||||||
Int32PtrTy);
|
|
||||||
|
|
||||||
auto GuardPtr2 = IRB.CreateIntToPtr(
|
if (icmp && sel->getCondition() == icmp) {
|
||||||
IRB.CreateAdd(
|
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
|
||||||
ConstantInt::get(
|
|
||||||
IntptrTy,
|
|
||||||
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
|
|
||||||
Int32PtrTy);
|
|
||||||
|
|
||||||
result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2);
|
usedInSelectDecision = true;
|
||||||
|
break;
|
||||||
|
|
||||||
} else
|
} else if (fcmp && sel->getCondition() == fcmp) {
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 14
|
usedInSelectDecision = true;
|
||||||
if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
break;
|
||||||
|
|
||||||
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
|
|
||||||
if (tt) {
|
|
||||||
|
|
||||||
uint32_t elements = tt->getElementCount().getFixedValue();
|
|
||||||
vector_cnt = elements;
|
|
||||||
if (elements) {
|
|
||||||
|
|
||||||
FixedVectorType *GuardPtr1 =
|
|
||||||
FixedVectorType::get(Int32PtrTy, elements);
|
|
||||||
FixedVectorType *GuardPtr2 =
|
|
||||||
FixedVectorType::get(Int32PtrTy, elements);
|
|
||||||
Value *x, *y;
|
|
||||||
|
|
||||||
if (!FunctionGuardArray) {
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"SANCOV: FunctionGuardArray is NULL, failed to emit "
|
|
||||||
"instrumentation.");
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Value *val1 = IRB.CreateIntToPtr(
|
|
||||||
IRB.CreateAdd(
|
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
|
||||||
ConstantInt::get(
|
|
||||||
IntptrTy,
|
|
||||||
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
|
|
||||||
Int32PtrTy);
|
|
||||||
x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0);
|
|
||||||
|
|
||||||
Value *val2 = IRB.CreateIntToPtr(
|
|
||||||
IRB.CreateAdd(
|
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
|
||||||
ConstantInt::get(
|
|
||||||
IntptrTy,
|
|
||||||
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
|
|
||||||
Int32PtrTy);
|
|
||||||
y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0);
|
|
||||||
|
|
||||||
for (uint64_t i = 1; i < elements; i++) {
|
|
||||||
|
|
||||||
val1 = IRB.CreateIntToPtr(
|
|
||||||
IRB.CreateAdd(
|
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
|
||||||
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
|
|
||||||
AllBlocks.size()) *
|
|
||||||
4)),
|
|
||||||
Int32PtrTy);
|
|
||||||
x = IRB.CreateInsertElement(x, val1, i);
|
|
||||||
|
|
||||||
val2 = IRB.CreateIntToPtr(
|
|
||||||
IRB.CreateAdd(
|
|
||||||
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
|
||||||
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
|
|
||||||
AllBlocks.size()) *
|
|
||||||
4)),
|
|
||||||
Int32PtrTy);
|
|
||||||
y = IRB.CreateInsertElement(y, val2, i);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
result = IRB.CreateSelect(condition, x, y);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
}
|
||||||
|
|
||||||
|
if (!usedInBranch && !usedInSelectDecision) {
|
||||||
|
|
||||||
|
// errs() << "Instrument! " << *(&IN) << "\n";
|
||||||
|
instrumentInst = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instrumentInst) {
|
||||||
|
|
||||||
|
Value *result = nullptr;
|
||||||
|
uint32_t vector_cnt = 0;
|
||||||
|
SelectInst *selectInst;
|
||||||
|
// PHINode *phi = nullptr, *newPhi = nullptr;
|
||||||
|
IRBuilder<> IRB(IN.getNextNode());
|
||||||
|
|
||||||
|
if ((icmp = dyn_cast<ICmpInst>(&IN))) {
|
||||||
|
|
||||||
|
if (!icmp->getType()->isIntegerTy(1)) { continue; }
|
||||||
|
|
||||||
|
if (skip_icmp) {
|
||||||
|
|
||||||
|
skip_icmp--;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
|
||||||
|
if (DILocation *Loc = IN.getDebugLoc()) {
|
||||||
|
|
||||||
|
llvm::errs() << "DEBUG " << Loc->getFilename() << ":"
|
||||||
|
<< Loc->getLine() << ":";
|
||||||
|
std::string path =
|
||||||
|
Loc->getDirectory().str() + "/" + Loc->getFilename().str();
|
||||||
|
std::ifstream sourceFile(path);
|
||||||
|
std::string lineContent;
|
||||||
|
for (unsigned line = 1; line <= Loc->getLine(); ++line)
|
||||||
|
std::getline(sourceFile, lineContent);
|
||||||
|
llvm::errs() << lineContent << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
errs() << *(&IN) << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = icmp;
|
||||||
|
auto GuardPtr1 = IRB.CreateInBoundsGEP(
|
||||||
|
FunctionGuardArray->getValueType(), FunctionGuardArray,
|
||||||
|
{IRB.getInt64(0),
|
||||||
|
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
|
||||||
|
|
||||||
|
auto GuardPtr2 = IRB.CreateInBoundsGEP(
|
||||||
|
FunctionGuardArray->getValueType(), FunctionGuardArray,
|
||||||
|
{IRB.getInt64(0),
|
||||||
|
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
|
||||||
|
|
||||||
|
result = IRB.CreateSelect(res, GuardPtr1, GuardPtr2);
|
||||||
|
skip_select = 1;
|
||||||
|
// fprintf(stderr, "Icmp!\n");
|
||||||
|
|
||||||
|
} else if ((fcmp = dyn_cast<FCmpInst>(&IN))) {
|
||||||
|
|
||||||
|
if (!fcmp->getType()->isIntegerTy(1)) { continue; }
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
|
||||||
|
if (DILocation *Loc = IN.getDebugLoc()) {
|
||||||
|
|
||||||
|
llvm::errs() << "DEBUG " << Loc->getFilename() << ":"
|
||||||
|
<< Loc->getLine() << ":";
|
||||||
|
std::string path =
|
||||||
|
Loc->getDirectory().str() + "/" + Loc->getFilename().str();
|
||||||
|
std::ifstream sourceFile(path);
|
||||||
|
std::string lineContent;
|
||||||
|
for (unsigned line = 1; line <= Loc->getLine(); ++line)
|
||||||
|
std::getline(sourceFile, lineContent);
|
||||||
|
llvm::errs() << lineContent << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
errs() << *(&IN) << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = fcmp;
|
||||||
|
auto GuardPtr1 = IRB.CreateInBoundsGEP(
|
||||||
|
FunctionGuardArray->getValueType(), FunctionGuardArray,
|
||||||
|
{IRB.getInt64(0),
|
||||||
|
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
|
||||||
|
|
||||||
|
auto GuardPtr2 = IRB.CreateInBoundsGEP(
|
||||||
|
FunctionGuardArray->getValueType(), FunctionGuardArray,
|
||||||
|
{IRB.getInt64(0),
|
||||||
|
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
|
||||||
|
|
||||||
|
result = IRB.CreateSelect(res, GuardPtr1, GuardPtr2);
|
||||||
|
skip_select = 1;
|
||||||
|
// fprintf(stderr, "Fcmp!\n");
|
||||||
|
|
||||||
|
/*} else if ((phi = dyn_cast<PHINode>(&IN))) {
|
||||||
|
|
||||||
|
if (skip_phi) {
|
||||||
|
|
||||||
|
skip_phi = 0;
|
||||||
|
// errs() << "SKIP: " << *(&IN) << "\n";
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// errs() << "-->PHI: " << *(&IN) << "\n";
|
||||||
|
// continue;
|
||||||
|
Instruction *insertBefore =
|
||||||
|
&*phi->getParent()->getFirstInsertionPt(); newPhi =
|
||||||
|
PHINode::Create(Int32PtrTy, 0, "", insertBefore); BasicBlock
|
||||||
|
*phiBlock = phi->getParent();
|
||||||
|
|
||||||
|
for (BasicBlock *pred : predecessors(phiBlock)) {
|
||||||
|
|
||||||
|
IRBuilder<> predBuilder(pred->getTerminator());
|
||||||
|
|
||||||
|
Value *ptr = predBuilder.CreateInBoundsGEP(
|
||||||
|
FunctionGuardArray->getValueType(), FunctionGuardArray,
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy, (cnt_cov + local_selects++ +
|
||||||
|
AllBlocks.size()))); newPhi->addIncoming(ptr, pred);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result = newPhi;
|
||||||
|
skip_phi = 1;
|
||||||
|
// fprintf(stderr, "Phi!\n");
|
||||||
|
*/
|
||||||
|
|
||||||
|
} else if ((selectInst = dyn_cast<SelectInst>(&IN))) {
|
||||||
|
|
||||||
|
if (skip_select) {
|
||||||
|
|
||||||
|
skip_select = 0;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// fprintf(stderr, "Select!\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *condition = selectInst->getCondition();
|
||||||
|
auto t = condition->getType();
|
||||||
|
|
||||||
|
if (t->getTypeID() == llvm::Type::IntegerTyID) {
|
||||||
|
|
||||||
|
auto GuardPtr1 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy,
|
||||||
|
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
|
||||||
|
auto GuardPtr2 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy,
|
||||||
|
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
|
||||||
|
result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2);
|
||||||
|
skip_select = 1;
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR >= 14
|
||||||
|
if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
||||||
|
|
||||||
|
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
|
||||||
|
|
||||||
|
if (tt) {
|
||||||
|
|
||||||
|
uint32_t elements = tt->getElementCount().getFixedValue();
|
||||||
|
vector_cnt = elements;
|
||||||
|
if (elements) {
|
||||||
|
|
||||||
|
FixedVectorType *GuardPtr1 =
|
||||||
|
FixedVectorType::get(Int32PtrTy, elements);
|
||||||
|
FixedVectorType *GuardPtr2 =
|
||||||
|
FixedVectorType::get(Int32PtrTy, elements);
|
||||||
|
Value *x, *y;
|
||||||
|
|
||||||
|
Value *val1 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
|
||||||
|
AllBlocks.size()) *
|
||||||
|
4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0);
|
||||||
|
|
||||||
|
Value *val2 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
|
||||||
|
AllBlocks.size()) *
|
||||||
|
4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0);
|
||||||
|
|
||||||
|
for (uint64_t i = 1; i < elements; i++) {
|
||||||
|
|
||||||
|
val1 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy,
|
||||||
|
(cnt_cov + local_selects++ + AllBlocks.size()) *
|
||||||
|
4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
x = IRB.CreateInsertElement(x, val1, i);
|
||||||
|
|
||||||
|
val2 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy,
|
||||||
|
(cnt_cov + local_selects++ + AllBlocks.size()) *
|
||||||
|
4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
y = IRB.CreateInsertElement(y, val2, i);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result = IRB.CreateSelect(condition, x, y);
|
||||||
|
skip_select = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
||||||
// fprintf(stderr, "UNHANDLED: %u\n", t->getTypeID());
|
if (!be_quiet) {
|
||||||
unhandled++;
|
|
||||||
continue;
|
WARNF("Warning: Unhandled ID type: %u\n", t->getTypeID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unhandled++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t vector_cur = 0;
|
uint32_t vector_cur = 0;
|
||||||
|
|
||||||
/* Load SHM pointer */
|
/* Load SHM pointer */
|
||||||
|
/*
|
||||||
|
if (newPhi) {
|
||||||
|
|
||||||
|
auto *inst = dyn_cast<Instruction>(result);
|
||||||
|
PHINode *nphi;
|
||||||
|
|
||||||
|
while ((nphi = dyn_cast<PHINode>(inst))) {
|
||||||
|
|
||||||
|
// fprintf(stderr, "NEXT!\n");
|
||||||
|
inst = inst->getNextNode();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IRB.SetInsertPoint(inst);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
LoadInst *MapPtr =
|
LoadInst *MapPtr =
|
||||||
IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
|
IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
|
||||||
@ -1073,6 +1398,7 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||||
Incr = IRB.CreateAdd(Incr, carry);
|
Incr = IRB.CreateAdd(Incr, carry);
|
||||||
|
skip_icmp++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,13 +1420,8 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_next = 1;
|
|
||||||
instr += vector_cnt;
|
instr += vector_cnt;
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
skip_next = 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1109,9 +1430,40 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
|||||||
|
|
||||||
if (AllBlocks.empty() && !special && !local_selects) return false;
|
if (AllBlocks.empty() && !special && !local_selects) return false;
|
||||||
|
|
||||||
if (!AllBlocks.empty())
|
uint32_t skipped = 0;
|
||||||
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
|
|
||||||
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
|
if (!AllBlocks.empty()) {
|
||||||
|
|
||||||
|
for (size_t i = 0, N = AllBlocks.size(); i < N; i++) {
|
||||||
|
|
||||||
|
auto instr = AllBlocks[i]->begin();
|
||||||
|
if (instr->getMetadata("skipinstrument")) {
|
||||||
|
|
||||||
|
skipped++;
|
||||||
|
// fprintf(stderr, "Skipped!\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
InjectCoverageAtBlock(F, *AllBlocks[i], i - skipped, IsLeafFunc);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
skippedbb += skipped;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (verifyFunction(F, &errs())) {
|
||||||
|
|
||||||
|
errs() << "Broken function after instrumentation\n";
|
||||||
|
F.print(errs(), nullptr);
|
||||||
|
report_fatal_error("Invalid IR");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
|||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||||
if (getenv("AFL_LLVM_ONLY_FSRV")) {
|
if (getenv("AFL_LLVM_ONLY_FSRV")) {
|
||||||
|
|
||||||
if (debug) { fprintf(stderr, "Instrument disabled\n"); }
|
if (debug) { fprintf(stderr, "Instrumentation disabled\n"); }
|
||||||
return PreservedAnalyses::all();
|
return PreservedAnalyses::all();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
|||||||
#else
|
#else
|
||||||
if (getenv("AFL_LLVM_ONLY_FSRV")) {
|
if (getenv("AFL_LLVM_ONLY_FSRV")) {
|
||||||
|
|
||||||
if (debug) { fprintf(stderr, "Instrument disabled\n"); }
|
if (debug) { fprintf(stderr, "Instrumentation disabled\n"); }
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ using namespace llvm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
|
||||||
|
|
||||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||||
class CmpLogInstructions : public PassInfoMixin<CmpLogInstructions> {
|
class CmpLogInstructions : public PassInfoMixin<CmpLogInstructions> {
|
||||||
|
|
||||||
@ -92,6 +94,8 @@ class CmpLogInstructions : public ModulePass {
|
|||||||
#else
|
#else
|
||||||
bool runOnModule(Module &M) override;
|
bool runOnModule(Module &M) override;
|
||||||
|
|
||||||
|
bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT);
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 4
|
#if LLVM_VERSION_MAJOR >= 4
|
||||||
StringRef getPassName() const override {
|
StringRef getPassName() const override {
|
||||||
|
|
||||||
@ -106,7 +110,7 @@ class CmpLogInstructions : public ModulePass {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool hookInstrs(Module &M);
|
bool hookInstrs(Module &M, DomTreeCallback DTCallback);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,7 +162,16 @@ Iterator Unique(Iterator first, Iterator last) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CmpLogInstructions::hookInstrs(Module &M) {
|
bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) {
|
||||||
|
|
||||||
|
if (DT->dominates(To, From)) return true;
|
||||||
|
if (auto Next = To->getUniqueSuccessor())
|
||||||
|
if (DT->dominates(Next, From)) return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CmpLogInstructions::hookInstrs(Module &M, DomTreeCallback DTCallback) {
|
||||||
|
|
||||||
std::vector<Instruction *> icomps;
|
std::vector<Instruction *> icomps;
|
||||||
LLVMContext &C = M.getContext();
|
LLVMContext &C = M.getContext();
|
||||||
@ -296,6 +309,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
for (auto &F : M) {
|
for (auto &F : M) {
|
||||||
|
|
||||||
if (!isInInstrumentList(&F, MNAME)) continue;
|
if (!isInInstrumentList(&F, MNAME)) continue;
|
||||||
|
const DominatorTree *DT = DTCallback(F);
|
||||||
|
|
||||||
for (auto &BB : F) {
|
for (auto &BB : F) {
|
||||||
|
|
||||||
@ -304,6 +318,12 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
CmpInst *selectcmpInst = nullptr;
|
CmpInst *selectcmpInst = nullptr;
|
||||||
if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
|
if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
|
||||||
|
|
||||||
|
// skip loop comparisons
|
||||||
|
if (selectcmpInst->hasOneUse())
|
||||||
|
if (auto BR = dyn_cast<BranchInst>(selectcmpInst->user_back()))
|
||||||
|
for (BasicBlock *B : BR->successors())
|
||||||
|
if (IsBackEdge(BR->getParent(), B, DT)) continue;
|
||||||
|
|
||||||
icomps.push_back(selectcmpInst);
|
icomps.push_back(selectcmpInst);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -681,11 +701,19 @@ bool CmpLogInstructions::runOnModule(Module &M) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||||
|
auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{
|
||||||
|
|
||||||
|
return &FAM.getResult<DominatorTreeAnalysis>(F);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
if (getenv("AFL_QUIET") == NULL)
|
if (getenv("AFL_QUIET") == NULL)
|
||||||
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
||||||
else
|
else
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
bool ret = hookInstrs(M);
|
|
||||||
|
bool ret = hookInstrs(M, DTCallback);
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||||
|
@ -75,7 +75,6 @@ static bool edges_only, /* Ignore hit counts? */
|
|||||||
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
||||||
|
|
||||||
static u8 *target_path;
|
static u8 *target_path;
|
||||||
static u8 frida_mode;
|
|
||||||
static u8 qemu_mode;
|
static u8 qemu_mode;
|
||||||
static u8 cs_mode;
|
static u8 cs_mode;
|
||||||
static u32 map_size = MAP_SIZE;
|
static u32 map_size = MAP_SIZE;
|
||||||
@ -628,9 +627,7 @@ static void handle_stop_sig(int sig) {
|
|||||||
|
|
||||||
static void set_up_environment(char **argv) {
|
static void set_up_environment(char **argv) {
|
||||||
|
|
||||||
u8 *x;
|
u8 *x;
|
||||||
char *afl_preload;
|
|
||||||
char *frida_afl_preload = NULL;
|
|
||||||
|
|
||||||
fsrv.dev_null_fd = open("/dev/null", O_RDWR);
|
fsrv.dev_null_fd = open("/dev/null", O_RDWR);
|
||||||
if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||||
@ -672,57 +669,7 @@ static void set_up_environment(char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_sanitizer_defaults();
|
set_sanitizer_defaults();
|
||||||
|
afl_fsrv_setup_preload(&fsrv, argv[0]);
|
||||||
if (get_afl_env("AFL_PRELOAD")) {
|
|
||||||
|
|
||||||
if (qemu_mode) {
|
|
||||||
|
|
||||||
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
|
|
||||||
|
|
||||||
} else if (frida_mode) {
|
|
||||||
|
|
||||||
afl_preload = getenv("AFL_PRELOAD");
|
|
||||||
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
|
|
||||||
if (afl_preload) {
|
|
||||||
|
|
||||||
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
frida_afl_preload = alloc_printf("%s", frida_binary);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(frida_binary);
|
|
||||||
|
|
||||||
setenv("LD_PRELOAD", frida_afl_preload, 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* CoreSight mode uses the default behavior. */
|
|
||||||
|
|
||||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (frida_mode) {
|
|
||||||
|
|
||||||
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
|
|
||||||
setenv("LD_PRELOAD", frida_binary, 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
|
|
||||||
#endif
|
|
||||||
ck_free(frida_binary);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frida_afl_preload) { ck_free(frida_afl_preload); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -936,10 +883,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
case 'O': /* FRIDA mode */
|
case 'O': /* FRIDA mode */
|
||||||
|
|
||||||
if (frida_mode) { FATAL("Multiple -O options not supported"); }
|
if (fsrv.frida_mode) { FATAL("Multiple -O options not supported"); }
|
||||||
|
|
||||||
frida_mode = 1;
|
fsrv.frida_mode = true;
|
||||||
fsrv.frida_mode = frida_mode;
|
|
||||||
setenv("AFL_FRIDA_INST_SEED", "1", 1);
|
setenv("AFL_FRIDA_INST_SEED", "1", 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -320,6 +320,38 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void afl_fsrv_setup_preload(afl_forkserver_t *fsrv, char *argv0) {
|
||||||
|
|
||||||
|
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
|
||||||
|
if (fsrv->qemu_mode) return;
|
||||||
|
|
||||||
|
u8 *afl_preload = getenv("AFL_PRELOAD");
|
||||||
|
u8 *preload_path = NULL;
|
||||||
|
u8 *frida_binary = NULL;
|
||||||
|
if (fsrv->frida_mode)
|
||||||
|
frida_binary = find_afl_binary(argv0, "afl-frida-trace.so");
|
||||||
|
|
||||||
|
if (afl_preload && frida_binary)
|
||||||
|
preload_path = alloc_printf("%s:%s", afl_preload, frida_binary);
|
||||||
|
else if (afl_preload)
|
||||||
|
preload_path = ck_strdup(afl_preload);
|
||||||
|
else if (frida_binary)
|
||||||
|
preload_path = ck_strdup(frida_binary);
|
||||||
|
|
||||||
|
ck_free(frida_binary);
|
||||||
|
|
||||||
|
if (preload_path) {
|
||||||
|
|
||||||
|
setenv("LD_PRELOAD", preload_path, 1);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
setenv("DYLD_INSERT_LIBRARIES", preload_path, 1);
|
||||||
|
#endif
|
||||||
|
ck_free(preload_path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Wrapper for select() and read(), reading a 32 bit var.
|
/* Wrapper for select() and read(), reading a 32 bit var.
|
||||||
Returns the time passed to read.
|
Returns the time passed to read.
|
||||||
If the wait times out, returns timeout_ms + 1;
|
If the wait times out, returns timeout_ms + 1;
|
||||||
|
@ -255,7 +255,8 @@ inline u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
|
|||||||
* on rare cases it fall backs to the slow path: classify_counts() first, then
|
* on rare cases it fall backs to the slow path: classify_counts() first, then
|
||||||
* return has_new_bits(). */
|
* return has_new_bits(). */
|
||||||
|
|
||||||
inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map) {
|
static inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map,
|
||||||
|
bool *classified) {
|
||||||
|
|
||||||
/* Handle the hot path first: no new coverage */
|
/* Handle the hot path first: no new coverage */
|
||||||
u8 *end = afl->fsrv.trace_bits + afl->fsrv.map_size;
|
u8 *end = afl->fsrv.trace_bits + afl->fsrv.map_size;
|
||||||
@ -272,6 +273,7 @@ inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map) {
|
|||||||
|
|
||||||
#endif /* ^WORD_SIZE_64 */
|
#endif /* ^WORD_SIZE_64 */
|
||||||
classify_counts(&afl->fsrv);
|
classify_counts(&afl->fsrv);
|
||||||
|
*classified = true;
|
||||||
return has_new_bits(afl, virgin_map);
|
return has_new_bits(afl, virgin_map);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -470,6 +472,46 @@ void write_crash_readme(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void classify_if_necessary(afl_state_t *afl, bool *classified) {
|
||||||
|
|
||||||
|
if (*classified) return;
|
||||||
|
classify_counts(&afl->fsrv);
|
||||||
|
*classified = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void calculate_cksum_if_necessary(afl_state_t *afl, u64 *cksum,
|
||||||
|
bool *cksumed,
|
||||||
|
bool *classified) {
|
||||||
|
|
||||||
|
if (*cksumed) return;
|
||||||
|
classify_if_necessary(afl, classified);
|
||||||
|
*cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||||
|
*cksumed = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void calculate_new_bits_if_necessary(afl_state_t *afl,
|
||||||
|
u8 *new_bits,
|
||||||
|
bool *bits_counted,
|
||||||
|
bool *classified) {
|
||||||
|
|
||||||
|
if (*bits_counted) return;
|
||||||
|
|
||||||
|
if (*classified) {
|
||||||
|
|
||||||
|
*new_bits = has_new_bits(afl, afl->virgin_bits);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
*new_bits = has_new_bits_unclassified(afl, afl->virgin_bits, classified);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*bits_counted = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the result of an execve() during routine fuzzing is interesting,
|
/* Check if the result of an execve() during routine fuzzing is interesting,
|
||||||
save or queue the input test case for further analysis if so. Returns 1 if
|
save or queue the input test case for further analysis if so. Returns 1 if
|
||||||
entry is saved, 0 otherwise. */
|
entry is saved, 0 otherwise. */
|
||||||
@ -498,13 +540,15 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
|
|
||||||
u8 fn[PATH_MAX];
|
u8 fn[PATH_MAX];
|
||||||
u8 *queue_fn = "";
|
u8 *queue_fn = "";
|
||||||
u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1;
|
u8 keeping = 0, res, is_timeout = 0;
|
||||||
u8 classified = 0;
|
|
||||||
u8 san_fault = 0, san_idx = 0, feed_san = 0;
|
u8 san_fault = 0, san_idx = 0, feed_san = 0;
|
||||||
s32 fd;
|
s32 fd;
|
||||||
u64 cksum = 0;
|
|
||||||
u32 cksum_simplified = 0, cksum_unique = 0;
|
u32 cksum_simplified = 0, cksum_unique = 0;
|
||||||
|
|
||||||
|
bool classified = false, bits_counted = false, cksumed = false;
|
||||||
|
u8 new_bits = 0; /* valid if bits_counted is true */
|
||||||
|
u64 cksum = 0; /* valid if cksumed is true */
|
||||||
|
|
||||||
afl->san_case_status = 0;
|
afl->san_case_status = 0;
|
||||||
|
|
||||||
/* Update path frequency. */
|
/* Update path frequency. */
|
||||||
@ -513,11 +557,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
only be used for special schedules */
|
only be used for special schedules */
|
||||||
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||||
|
|
||||||
classify_counts(&afl->fsrv);
|
calculate_cksum_if_necessary(afl, &cksum, &cksumed, &classified);
|
||||||
classified = 1;
|
|
||||||
need_hash = 0;
|
|
||||||
|
|
||||||
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
|
||||||
|
|
||||||
/* Saturated increment */
|
/* Saturated increment */
|
||||||
if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
|
if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
|
||||||
@ -551,17 +591,9 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
if (unlikely(afl->san_binary_length) &&
|
if (unlikely(afl->san_binary_length) &&
|
||||||
unlikely(afl->san_abstraction == COVERAGE_INCREASE)) {
|
unlikely(afl->san_abstraction == COVERAGE_INCREASE)) {
|
||||||
|
|
||||||
if (classified) {
|
/* Check if the input increase the coverage */
|
||||||
|
calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted,
|
||||||
/* We could have classified the bits in SAND with COVERAGE_INCREASE */
|
&classified);
|
||||||
new_bits = has_new_bits(afl, afl->virgin_bits);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
|
|
||||||
classified = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(new_bits)) { feed_san = 1; }
|
if (unlikely(new_bits)) { feed_san = 1; }
|
||||||
|
|
||||||
@ -570,15 +602,9 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
if (unlikely(afl->san_binary_length) &&
|
if (unlikely(afl->san_binary_length) &&
|
||||||
likely(afl->san_abstraction == UNIQUE_TRACE)) {
|
likely(afl->san_abstraction == UNIQUE_TRACE)) {
|
||||||
|
|
||||||
// If schedule is not FAST..RARE, we need to classify counts here
|
|
||||||
// Note: SAND was evaluated under FAST schedule but should also work
|
// Note: SAND was evaluated under FAST schedule but should also work
|
||||||
// with other scedules.
|
// with other scedules.
|
||||||
if (!classified) {
|
classify_if_necessary(afl, &classified);
|
||||||
|
|
||||||
classify_counts(&afl->fsrv);
|
|
||||||
classified = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cksum_unique =
|
cksum_unique =
|
||||||
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||||
@ -638,23 +664,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
|
|
||||||
/* Keep only if there are new bits in the map, add to queue for
|
/* Keep only if there are new bits in the map, add to queue for
|
||||||
future fuzzing, etc. */
|
future fuzzing, etc. */
|
||||||
if (!unlikely(afl->san_abstraction == COVERAGE_INCREASE && feed_san)) {
|
calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, &classified);
|
||||||
|
|
||||||
/* If we are in coverage increasing abstraction and have fed input to
|
|
||||||
sanitizers, we are sure it has new bits.*/
|
|
||||||
if (classified) {
|
|
||||||
|
|
||||||
/* We could have classified the bits in SAND with UNIQUE_TRACE */
|
|
||||||
new_bits = has_new_bits(afl, afl->virgin_bits);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
|
|
||||||
classified = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (likely(!new_bits)) {
|
if (likely(!new_bits)) {
|
||||||
|
|
||||||
@ -677,6 +687,11 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
|
|
||||||
save_to_queue:
|
save_to_queue:
|
||||||
|
|
||||||
|
/* these calculations are necessary because some code flow may jump here via
|
||||||
|
goto */
|
||||||
|
calculate_cksum_if_necessary(afl, &cksum, &cksumed, &classified);
|
||||||
|
calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, &classified);
|
||||||
|
|
||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
if (!afl->afl_env.afl_sha1_filenames) {
|
if (!afl->afl_env.afl_sha1_filenames) {
|
||||||
@ -758,6 +773,8 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
afl->queue_top->exec_cksum = cksum;
|
||||||
|
|
||||||
if (new_bits == 2) {
|
if (new_bits == 2) {
|
||||||
|
|
||||||
afl->queue_top->has_new_cov = 1;
|
afl->queue_top->has_new_cov = 1;
|
||||||
@ -765,17 +782,8 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(need_hash && new_bits)) {
|
|
||||||
|
|
||||||
/* due to classify counts we have to recalculate the checksum */
|
|
||||||
afl->queue_top->exec_cksum =
|
|
||||||
hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
|
||||||
need_hash = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For AFLFast schedules we update the new queue entry */
|
/* For AFLFast schedules we update the new queue entry */
|
||||||
if (likely(cksum)) {
|
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||||
|
|
||||||
afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
|
afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
|
||||||
afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
|
afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
|
||||||
@ -874,12 +882,9 @@ may_save_fault:
|
|||||||
}
|
}
|
||||||
|
|
||||||
new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout);
|
new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout);
|
||||||
if (!classified) {
|
classified = false;
|
||||||
|
bits_counted = false;
|
||||||
classify_counts(&afl->fsrv);
|
cksumed = false;
|
||||||
classified = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A corner case that one user reported bumping into: increasing the
|
/* A corner case that one user reported bumping into: increasing the
|
||||||
timeout actually uncovers a crash. Make sure we don't discard it if
|
timeout actually uncovers a crash. Make sure we don't discard it if
|
||||||
|
@ -495,36 +495,41 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
afl->afl_env.afl_post_process_keep_original = 1;
|
afl->afl_env.afl_post_process_keep_original = 1;
|
||||||
|
|
||||||
/* we need a dummy run if this is LTO + cmplog */
|
/* we need a dummy run if this is LTO + cmplog */
|
||||||
if (unlikely(afl->shm.cmplog_mode)) {
|
/*
|
||||||
|
if (unlikely(afl->shm.cmplog_mode)) {
|
||||||
|
|
||||||
(void)write_to_testcase(afl, (void **)&use_mem, q->len, 1);
|
(void)write_to_testcase(afl, (void **)&use_mem, q->len, 1);
|
||||||
|
|
||||||
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
|
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
|
||||||
|
|
||||||
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
|
// afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
|
||||||
we want to bail out quickly. */
|
// we want to bail out quickly.
|
||||||
|
|
||||||
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
|
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration;
|
||||||
|
|
||||||
if (!afl->non_instrumented_mode && !afl->stage_cur &&
|
}
|
||||||
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
|
||||||
|
|
||||||
fault = FSRV_RUN_NOINST;
|
if (!afl->non_instrumented_mode &&
|
||||||
goto abort_calibration;
|
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
||||||
|
|
||||||
|
fault = FSRV_RUN_NOINST;
|
||||||
|
goto abort_calibration;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef INTROSPECTION
|
||||||
|
if (unlikely(!q->bitsmap_size)) { q->bitsmap_size = afl->bitsmap_size; }
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef INTROSPECTION
|
*/
|
||||||
if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (q->exec_cksum) {
|
if (q->exec_cksum) {
|
||||||
|
|
||||||
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
|
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
|
||||||
hnb = has_new_bits(afl, afl->virgin_bits);
|
hnb = has_new_bits(afl, afl->virgin_bits);
|
||||||
if (hnb > new_bits) { new_bits = hnb; }
|
if (unlikely(hnb > new_bits)) { new_bits = hnb; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,7 +558,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
|
|
||||||
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
|
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
|
||||||
|
|
||||||
if (!afl->non_instrumented_mode && !afl->stage_cur &&
|
if (!afl->non_instrumented_mode &&
|
||||||
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
||||||
|
|
||||||
fault = FSRV_RUN_NOINST;
|
fault = FSRV_RUN_NOINST;
|
||||||
@ -562,17 +567,19 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef INTROSPECTION
|
#ifdef INTROSPECTION
|
||||||
if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
|
if (unlikely(!q->bitsmap_size)) { q->bitsmap_size = afl->bitsmap_size; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
classify_counts(&afl->fsrv);
|
classify_counts(&afl->fsrv);
|
||||||
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||||
if (q->exec_cksum != cksum) {
|
|
||||||
|
if (unlikely(q->exec_cksum != cksum)) {
|
||||||
|
|
||||||
hnb = has_new_bits(afl, afl->virgin_bits);
|
hnb = has_new_bits(afl, afl->virgin_bits);
|
||||||
if (hnb > new_bits) { new_bits = hnb; }
|
|
||||||
|
|
||||||
if (q->exec_cksum) {
|
if (unlikely(hnb > new_bits)) { new_bits = hnb; }
|
||||||
|
|
||||||
|
if (likely(q->exec_cksum)) {
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
|
@ -714,61 +714,8 @@ static void handle_stop_sig(int sig) {
|
|||||||
|
|
||||||
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
|
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
|
||||||
|
|
||||||
char *afl_preload;
|
|
||||||
char *frida_afl_preload = NULL;
|
|
||||||
|
|
||||||
set_sanitizer_defaults();
|
set_sanitizer_defaults();
|
||||||
|
afl_fsrv_setup_preload(fsrv, argv[0]);
|
||||||
if (get_afl_env("AFL_PRELOAD")) {
|
|
||||||
|
|
||||||
if (fsrv->qemu_mode) {
|
|
||||||
|
|
||||||
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
|
|
||||||
|
|
||||||
} else if (fsrv->frida_mode) {
|
|
||||||
|
|
||||||
afl_preload = getenv("AFL_PRELOAD");
|
|
||||||
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
|
|
||||||
if (afl_preload) {
|
|
||||||
|
|
||||||
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
frida_afl_preload = alloc_printf("%s", frida_binary);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(frida_binary);
|
|
||||||
|
|
||||||
setenv("LD_PRELOAD", frida_afl_preload, 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* CoreSight mode uses the default behavior. */
|
|
||||||
|
|
||||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (fsrv->frida_mode) {
|
|
||||||
|
|
||||||
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
|
|
||||||
setenv("LD_PRELOAD", frida_binary, 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
|
|
||||||
#endif
|
|
||||||
ck_free(frida_binary);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frida_afl_preload) { ck_free(frida_afl_preload); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,9 +899,7 @@ static void handle_stop_sig(int sig) {
|
|||||||
|
|
||||||
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
|
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
|
||||||
|
|
||||||
u8 *x;
|
u8 *x;
|
||||||
char *afl_preload;
|
|
||||||
char *frida_afl_preload = NULL;
|
|
||||||
|
|
||||||
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
||||||
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||||
@ -945,57 +943,7 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_sanitizer_defaults();
|
set_sanitizer_defaults();
|
||||||
|
afl_fsrv_setup_preload(fsrv, argv[0]);
|
||||||
if (get_afl_env("AFL_PRELOAD")) {
|
|
||||||
|
|
||||||
if (fsrv->qemu_mode) {
|
|
||||||
|
|
||||||
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
|
|
||||||
|
|
||||||
} else if (fsrv->frida_mode) {
|
|
||||||
|
|
||||||
afl_preload = getenv("AFL_PRELOAD");
|
|
||||||
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
|
|
||||||
if (afl_preload) {
|
|
||||||
|
|
||||||
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
frida_afl_preload = alloc_printf("%s", frida_binary);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(frida_binary);
|
|
||||||
|
|
||||||
setenv("LD_PRELOAD", frida_afl_preload, 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* CoreSight mode uses the default behavior. */
|
|
||||||
|
|
||||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (fsrv->frida_mode) {
|
|
||||||
|
|
||||||
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
|
|
||||||
setenv("LD_PRELOAD", frida_binary, 1);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
|
|
||||||
#endif
|
|
||||||
ck_free(frida_binary);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frida_afl_preload) { ck_free(frida_afl_preload); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user