final touches

This commit is contained in:
van Hauser
2019-07-05 11:28:08 +02:00
parent 9199967022
commit 7f6aaa5314
5 changed files with 71 additions and 55 deletions

View File

@ -17,6 +17,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
Version ++2.52d (tbd): Version ++2.52d (tbd):
----------------------------- -----------------------------
- added never zero counters for afl-gcc and optional (because of an
optimization issue in llvm < 9) for llvm_mode (AFL_LLVM_NEVER_ZERO=1)
- added whitelist support for llvm_mode via AFL_LLVM_WHITELIST to allow - added whitelist support for llvm_mode via AFL_LLVM_WHITELIST to allow
only to instrument what is actually interesting. Gives more speed and less only to instrument what is actually interesting. Gives more speed and less
map pollution (originally by choller@mozilla) map pollution (originally by choller@mozilla)

View File

@ -108,8 +108,11 @@ Then there are a few specific features that are only available in llvm_mode:
OTHER OTHER
===== =====
- Setting AFL_NZERO_COUNTS=1 during compilation will use counters - Setting export AFL_LLVM_NOT_ZERO=1 during compilation will use counters
that skip zero on overflow. that skip zero on overflow. This is the default for llvm >= 9,
however for llvm versions below that this will increase an unnecessary
slowdown due a performance issue that is only fixed in llvm 9+.
This feature increases path discovery by a little bit.
Note that AFL_INST_RATIO will behave a bit differently than for afl-gcc, Note that AFL_INST_RATIO will behave a bit differently than for afl-gcc,
because functions are *not* instrumented unconditionally - so low values because functions are *not* instrumented unconditionally - so low values

View File

@ -25,11 +25,17 @@ VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
LLVM_CONFIG ?= llvm-config LLVM_CONFIG ?= llvm-config
#LLVM_OK = $(shell $(LLVM_CONFIG) --version | egrep -q '^[5-6]' && echo 0 || echo 1 ) #LLVM_OK = $(shell $(LLVM_CONFIG) --version | egrep -q '^[5-6]' && echo 0 || echo 1 )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version | egrep -q '^9|3.0' && echo 1 || echo 0 ) LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version | egrep -q '^9|3.0' && echo 1 || echo 0 )
LLVM_MAJOR = ($shell $(LLVM_CONFIG) --version | sed 's/\..*//')
ifeq "$(LLVM_UNSUPPORTED)" "1" ifeq "$(LLVM_UNSUPPORTED)" "1"
$(warn llvm_mode only supports versions 3.8.0 up to 8.x ) $(warn llvm_mode only supports versions 3.8.0 up to 8.x )
endif endif
# this is not visible yet:
ifeq "$(LLVM_MAJOR)" "9"
$(info llvm_mode deteted llvm 9, enabling neverZero implementation)
endif
CFLAGS ?= -O3 -funroll-loops CFLAGS ?= -O3 -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \

View File

@ -0,0 +1,22 @@
Usage
=====
In larger, complex or reiterative programs the map that collects the edge pairs
can easily fill up and wrap.
This is not that much of an issue - unless by chance it wraps just to a 0
when the program execution ends.
In this case afl-fuzz is not able to see that the pair has been accessed and
will ignore it.
NeverZero prevents this behaviour. If a counter wraps, it jumps over the 0
directly to a 1. This improves path discovery (by a very little amount)
at a very little cost (one instruction per edge).
This is implemented in afl-gcc, however for llvm_mode this is optional if
the llvm version is below 9 - as there is a perfomance bug that is only fixed
in version 9 and onwards.
If you want to enable this for llvm < 9 then set
export AFL_LLVM_NOT_ZERO=1

View File

@ -118,7 +118,9 @@ bool AFLCoverage::runOnModule(Module &M) {
} }
char* neverZero_counters_str = getenv("AFL_NZERO_COUNTS"); #if LLVM_VERSION_MAJOR < 9
char* neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO");
#endif
/* Get globals for the SHM region and the previous location. Note that /* Get globals for the SHM region and the previous location. Note that
__afl_prev_loc is thread-local. */ __afl_prev_loc is thread-local. */
@ -236,75 +238,56 @@ bool AFLCoverage::runOnModule(Module &M) {
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
Value *Incr; Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
// if (neverZero_counters_str == NULL || neverZero_counters_str[0] != '4')
Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
if (neverZero_counters_str != NULL) { #if LLVM_VERSION_MAJOR < 9
/* hexcoder: Realize a counter that skips zero during overflow. if (neverZero_counters_str != NULL) { // with llvm 9 we make this the default as the bug in llvm is then fixed
* Once this counter reaches its maximum value, it next increments to 1 #endif
* /* hexcoder: Realize a counter that skips zero during overflow.
* Instead of * Once this counter reaches its maximum value, it next increments to 1
* Counter + 1 -> Counter *
* we inject now this * Instead of
* Counter + 1 -> {Counter, OverflowFlag} * Counter + 1 -> Counter
* Counter + OverflowFlag -> Counter * we inject now this
*/ * Counter + 1 -> {Counter, OverflowFlag}
* Counter + OverflowFlag -> Counter
// Solution #1 - creates */
//mov ecx,edx /* // we keep the old solutions just in case
//add cl,0x1 // Solution #1
//adc dl,0x1 if (neverZero_counters_str[0] == '1') {
/* CallInst *AddOv = IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow, Counter, ConstantInt::get(Int8Ty, 1));
if (neverZero_counters_str[0] == '1') { AddOv->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
CallInst *AddOv = IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow, Counter, ConstantInt::get(Int8Ty, 1)); Value *SumWithOverflowBit = AddOv;
AddOv->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Incr = IRB.CreateAdd(IRB.CreateExtractValue(SumWithOverflowBit, 0), // sum
Value *SumWithOverflowBit = AddOv; IRB.CreateZExt( // convert from one bit type to 8 bits type
Incr = IRB.CreateAdd(IRB.CreateExtractValue(SumWithOverflowBit, 0), // sum IRB.CreateExtractValue(SumWithOverflowBit, 1), // overflow
IRB.CreateZExt( // convert from one bit type to 8 bits type Int8Ty));
IRB.CreateExtractValue(SumWithOverflowBit, 1), // overflow // Solution #2
Int8Ty));
// Solution #2 - creates the same code as #1
} else if (neverZero_counters_str[0] == '2') { } else if (neverZero_counters_str[0] == '2') {
auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1));
Incr = IRB.CreateAdd(Incr, cf);
// Solution #3 - creates
//add cl,0x1
//cmp cl,0x1
//adc cl,0x0
} else if (neverZero_counters_str[0] == '3') {
auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
Incr = IRB.CreateAdd(Incr, cf);
// Solution #4 - creates
// cmp dl, $0xff
// sete cl
// add dl,cl
// add dl,0x01
} else if (neverZero_counters_str[0] == '4') {
auto cf = IRB.CreateICmpEQ(Counter, ConstantInt::get(Int8Ty, 255)); auto cf = IRB.CreateICmpEQ(Counter, ConstantInt::get(Int8Ty, 255));
Value *HowMuch = IRB.CreateAdd(ConstantInt::get(Int8Ty, 1), cf); Value *HowMuch = IRB.CreateAdd(ConstantInt::get(Int8Ty, 1), cf);
Incr = IRB.CreateAdd(Counter, HowMuch); Incr = IRB.CreateAdd(Counter, HowMuch);
// Solution #3
} else if (neverZero_counters_str[0] == '5') { } else if (neverZero_counters_str[0] == '3') {
*/ */
// this is the solution we choose because llvm9 should do the right thing here
auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0)); auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
auto carry = IRB.CreateZExt(cf, Int8Ty); auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry); Incr = IRB.CreateAdd(Incr, carry);
/* /*
} else if (neverZero_counters_str[0] == '6') { // Solution #4
} else if (neverZero_counters_str[0] == '4') {
auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1)); auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1));
auto carry = IRB.CreateZExt(cf, Int8Ty); auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry); Incr = IRB.CreateAdd(Incr, carry);
} else {
// no other implementations yet
} else {
fprintf(stderr, "Error: unknown value for AFL_NZERO_COUNTS: %s (valid is 1-4)\n", neverZero_counters_str); fprintf(stderr, "Error: unknown value for AFL_NZERO_COUNTS: %s (valid is 1-4)\n", neverZero_counters_str);
exit(-1); exit(-1);
} }
*/ */
#if LLVM_VERSION_MAJOR < 9
} }
#endif
IRB.CreateStore(Incr, MapPtrIdx)->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); IRB.CreateStore(Incr, MapPtrIdx)->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));