added AFL_LLVM_SKIPSINGLEBLOCK and changed default behaviour to instrument single block functions

This commit is contained in:
van Hauser
2020-05-07 14:59:12 +02:00
parent 02887dc164
commit ef2ccc8117
7 changed files with 38 additions and 22 deletions

View File

@ -16,6 +16,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- an old, old bug in afl that would show negative stability in rare - an old, old bug in afl that would show negative stability in rare
circumstances is now hopefully fixed circumstances is now hopefully fixed
- llvm_mode: - llvm_mode:
- afl-clang-fast/lto now do not skip single block functions. This
behaviour can be reactivated with AFL_LLVM_SKIPSINGLEBLOCK
- if LLVM 11 is installed the posix shm_open+mmap is used and a fixed - if LLVM 11 is installed the posix shm_open+mmap is used and a fixed
address for the shared memory map is used as this increases the address for the shared memory map is used as this increases the
fuzzing speed fuzzing speed

View File

@ -83,6 +83,10 @@ tools make fairly broad use of environmental variables:
The native instrumentation helpers (llvm_mode and gcc_plugin) accept a subset The native instrumentation helpers (llvm_mode and gcc_plugin) accept a subset
of the settings discussed in section #1, with the exception of: of the settings discussed in section #1, with the exception of:
- Setting AFL_LLVM_SKIPSINGLEBLOCK=1 will skip instrumenting
functions with a single basic block. This is useful for most C and
some C++ targets. This works for all instrumentation modes.
- AFL_AS, since this toolchain does not directly invoke GNU as. - AFL_AS, since this toolchain does not directly invoke GNU as.
- TMPDIR and AFL_KEEP_ASSEMBLY, since no temporary assembly files are - TMPDIR and AFL_KEEP_ASSEMBLY, since no temporary assembly files are
@ -156,10 +160,6 @@ Then there are a few specific features that are only available in llvm_mode:
afl-fuzz will only be able to see the path the loop took, but not how afl-fuzz will only be able to see the path the loop took, but not how
many times it was called (unless it is a complex loop). many times it was called (unless it is a complex loop).
- Setting AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 will skip instrumenting
functions with a single basic block. This is useful for most C and
some C++ targets.
See llvm_mode/README.instrim.md See llvm_mode/README.instrim.md
### NGRAM ### NGRAM

View File

@ -134,7 +134,8 @@ struct InsTrim : public ModulePass {
} }
if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") != NULL) if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
function_minimum_size = 2; function_minimum_size = 2;
unsigned PrevLocSize = 0; unsigned PrevLocSize = 0;
@ -394,7 +395,7 @@ struct InsTrim : public ModulePass {
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction(); Function *Callee = callInst->getCalledFunction();
if (!Callee || Callee->size() < 2) if (!Callee || Callee->size() < function_minimum_size)
continue; continue;
else { else {

View File

@ -172,7 +172,8 @@ struct InsTrimLTO : public ModulePass {
} }
if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") != NULL) if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
function_minimum_size = 2; function_minimum_size = 2;
// this is our default // this is our default

View File

@ -87,6 +87,7 @@ class AFLLTOPass : public ModulePass {
protected: protected:
int afl_global_id = 1, debug = 0, autodictionary = 0; int afl_global_id = 1, debug = 0, autodictionary = 0;
uint32_t function_minimum_size = 1;
uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0, total_instr = 0; uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0, total_instr = 0;
uint64_t map_addr = 0x10000; uint64_t map_addr = 0x10000;
char * skip_nozero = NULL; char * skip_nozero = NULL;
@ -124,6 +125,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0; if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
function_minimum_size = 2;
if ((ptr = getenv("AFL_LLVM_MAP_ADDR"))) { if ((ptr = getenv("AFL_LLVM_MAP_ADDR"))) {
uint64_t val; uint64_t val;
@ -189,7 +194,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
// fprintf(stderr, "DEBUG: Function %s\n", F.getName().str().c_str()); // fprintf(stderr, "DEBUG: Function %s\n", F.getName().str().c_str());
if (F.size() < 2) continue; if (F.size() < function_minimum_size) continue;
if (isBlacklisted(&F)) continue; if (isBlacklisted(&F)) continue;
std::vector<BasicBlock *> InsBlocks; std::vector<BasicBlock *> InsBlocks;

View File

@ -84,6 +84,7 @@ class AFLCoverage : public ModulePass {
uint32_t ngram_size = 0; uint32_t ngram_size = 0;
uint32_t debug = 0; uint32_t debug = 0;
uint32_t map_size = MAP_SIZE; uint32_t map_size = MAP_SIZE;
uint32_t function_minimum_size = 1;
char * ctx_str = NULL, *skip_nozero = NULL; char * ctx_str = NULL, *skip_nozero = NULL;
}; };
@ -182,6 +183,10 @@ bool AFLCoverage::runOnModule(Module &M) {
#endif #endif
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
function_minimum_size = 2;
unsigned PrevLocSize = 0; unsigned PrevLocSize = 0;
char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE"); char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
@ -294,13 +299,15 @@ bool AFLCoverage::runOnModule(Module &M) {
if (!isInWhitelist(&F)) continue; if (!isInWhitelist(&F)) continue;
if (F.size() < function_minimum_size) continue;
for (auto &BB : F) { for (auto &BB : F) {
BasicBlock::iterator IP = BB.getFirstInsertionPt(); BasicBlock::iterator IP = BB.getFirstInsertionPt();
IRBuilder<> IRB(&(*IP)); IRBuilder<> IRB(&(*IP));
// Context sensitive coverage // Context sensitive coverage
if (ctx_str && &BB == &F.getEntryBlock() && F.size() > 1) { if (ctx_str && &BB == &F.getEntryBlock()) {
// load the context ID of the previous function and write to to a local // load the context ID of the previous function and write to to a local
// variable on the stack // variable on the stack
@ -318,7 +325,7 @@ bool AFLCoverage::runOnModule(Module &M) {
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction(); Function *Callee = callInst->getCalledFunction();
if (!Callee || Callee->size() < 2) if (!Callee || Callee->size() < function_minimum_size)
continue; continue;
else { else {
@ -389,11 +396,11 @@ bool AFLCoverage::runOnModule(Module &M) {
} }
// fprintf(stderr, " == %d\n", more_than_one); // fprintf(stderr, " == %d\n", more_than_one);
if (more_than_one != 1) { if (F.size() > 1 && more_than_one != 1) {
// in CTX mode we have to restore the original context for the caller - // in CTX mode we have to restore the original context for the caller -
// she might be calling other functions which need the correct CTX // she might be calling other functions which need the correct CTX
if (ctx_str && has_calls && F.size() > 1) { if (ctx_str && has_calls) {
Instruction *Inst = BB.getTerminator(); Instruction *Inst = BB.getTerminator();
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) { if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
@ -526,7 +533,7 @@ bool AFLCoverage::runOnModule(Module &M) {
// in CTX mode we have to restore the original context for the caller - // in CTX mode we have to restore the original context for the caller -
// she might be calling other functions which need the correct CTX. // she might be calling other functions which need the correct CTX.
// Currently this is only needed for the Ubuntu clang-6.0 bug // Currently this is only needed for the Ubuntu clang-6.0 bug
if (ctx_str && has_calls && F.size() > 1) { if (ctx_str && has_calls) {
Instruction *Inst = BB.getTerminator(); Instruction *Inst = BB.getTerminator();
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) { if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {

View File

@ -64,15 +64,15 @@ char *afl_environment_variables[] = {
"AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM",
"AFL_LLVM_CTX", "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_CTX", "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD",
"AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY", "AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY",
"AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_SKIPSINGLEBLOCK", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK",
"AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW",
"AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES",
"AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR",
"AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
"AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO",
"AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID",
"AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV",
"AFL_UNTRACER_FILE", "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE",
"AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE",
//"AFL_PERSISTENT", // not implemented anymore, so warn additionally //"AFL_PERSISTENT", // not implemented anymore, so warn additionally