From 9d03763d942c19ac9c6cbe7d6a3f3cecba65abad Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 1 May 2020 00:57:20 +0200 Subject: at some point we have to do a rewrite of llvm_mode/GNUmakefile --- llvm_mode/GNUmakefile | 95 +++++++++++++++++++++++++++++------------------ llvm_mode/README.md | 21 ++++++++++- llvm_mode/afl-llvm-rt.o.c | 2 +- 3 files changed, 80 insertions(+), 38 deletions(-) (limited to 'llvm_mode') diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 69b0875e..2cbe53cd 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -38,7 +38,7 @@ else LLVM_CONFIG ?= llvm-config endif -LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null ) +LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' ) LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[2-9]' && echo 1 || echo 0 ) LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 ) LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//') @@ -82,30 +82,66 @@ endif # this seems to be busted on some distros, so using the one in $PATH is # probably better. -CC ?= $(LLVM_BINDIR)/clang -CXX ?= $(LLVM_BINDIR)/clang++ +CC = $(LLVM_BINDIR)/clang +CXX = $(LLVM_BINDIR)/clang++ +# llvm-config --bindir may not providing a valid path, so ... ifeq "$(shell test -e $(CC) || echo 1 )" "1" - # llvm-config --bindir may not providing a valid path, so ... - ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1" - # we found one in the local install directory, lets use these - CC = $(BIN_DIR)/clang - CXX = $(BIN_DIR)/clang++ - else - # hope for the best - $(warning we have trouble finding clang/clang++ - llvm-config is not helping us) - CC = clang - CXX = clang++ + # however we must ensure that this is not a "CC=gcc make" + ifeq "$(shell command -v $(CC) 2> /dev/null)" "" + # we do not have a valid CC variable so we try alternatives + ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1" + # we found one in the local install directory, lets use these + CC = $(BIN_DIR)/clang + CXX = $(BIN_DIR)/clang++ + else + # hope for the best + $(warning we have trouble finding clang/clang++ - llvm-config is not helping us) + CC = clang + CXX = clang++ + endif endif endif # sanity check. # Are versions of clang --version and llvm-config --version equal? -CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p') +CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p') -ifneq "$(CLANGVER)" "$(LLVMVER)" - CC = $(shell $(LLVM_CONFIG) --bindir)/clang - CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++ +# I disable this because it does not make sense with what we did before (marc) +# We did exactly set these 26 lines above with these values, and it would break +# "CC=gcc make" etc. usages +ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" + CC_SAVE = $(LLVM_BINDIR)/clang +else + CC_SAVE = $(CC) +endif +ifeq "$(findstring clang, $(shell $(CXX) --version 2>/dev/null))" "" + CXX_SAVE = $(LLVM_BINDIR)/clang++ +else + CXX_SAVE = $(CXX) +endif + +CLANG_BIN = $(CC_SAVE) +CLANGPP_BIN = $(CXX_SAVE) + +ifeq "$(CC_SAVE)" "$(LLVM_BINDIR)/clang" + USE_BINDIR = 1 +else + ifeq "$(CXX_SAVE)" "$(LLVM_BINDIR)/clang++" + USE_BINDIR = 1 + else + USE_BINDIR = 0 + endif +endif + +# On old platform we cannot compile with clang because std++ libraries are too +# old. For these we need to use gcc/g++, so if we find REAL_CC and REAL_CXX +# variable we override the compiler variables here +ifneq "$(REAL_CC)" "" +CC = $(REAL_CC) +endif +ifneq "$(REAL_CXX)" "" +CXX = $(REAL_CXX) endif # After we set CC/CXX we can start makefile magic tests @@ -146,19 +182,6 @@ ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`command -v endif endif -CLANG_BIN = $(basename $(CC)) -CLANGPP_BIN = $(basename $(CXX)) -ifeq "$(shell test -e $(CLANG_BIN) || echo 1 )" "1" - CLANG_BIN = $(CC) - CLANGPP_BIN = $(CXX) -endif - -ifeq "$(CC)" "$(LLVM_BINDIR)/clang" - USE_BINDIR = 1 -else - USE_BINDIR = 0 -endif - CFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2 override CFLAGS += -Wall \ -g -Wno-pointer-sign -I ../include/ \ @@ -166,7 +189,7 @@ override CFLAGS += -Wall \ -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \ -DLLVM_VERSION=\"$(LLVMVER)\" -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \ -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \ - -DCLANG_BIN=\"$(CC)\" -DCLANGPP_BIN=\"$(CXX)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function + -DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function ifdef AFL_TRACE_PC $(info Compile option AFL_TRACE_PC is deprecated, just set AFL_LLVM_INSTRUMENT=PCGUARD to activate when compiling targets ) endif @@ -249,7 +272,7 @@ test_deps: @echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'" ifneq "$(CLANGVER)" "$(LLVMVER)" @echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)" - @echo "[!] Retrying with the clang compiler from llvm: CC=`llvm-config --bindir`/clang" + @echo "[!] Retry with the clang compiler from llvm: CC=`llvm-config --bindir`/clang" else @echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good." endif @@ -290,9 +313,9 @@ endif ../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc afl-llvm-common.o ifeq "$(LLVM_LTO)" "1" $(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o - $(CC) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o - @$(CC) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi - @$(CC) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi + $(CLANG_BIN) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o + @$(CLANG_BIN) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi + @$(CLANG_BIN) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi endif # laf @@ -323,7 +346,7 @@ endif test_build: $(PROGS) @echo "[*] Testing the CC wrapper and instrumentation output..." - unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) + unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr @rm -f test-instr diff --git a/llvm_mode/README.md b/llvm_mode/README.md index 607350fb..0bff1ff1 100644 --- a/llvm_mode/README.md +++ b/llvm_mode/README.md @@ -37,7 +37,26 @@ co-exists with the original code. The idea and much of the implementation comes from Laszlo Szekeres. -## 2) How to use this +## 2a) How to use this - short + +Set the `LLVM_CONFIG` variable to the clang version you want to use, e.g. +``` +LLVM_CONFIG=llvm-config-9 make +``` +In case you have your own compiled llvm version specify the full path: +``` +LLVM_CONFIG=~/llvm-project/build/bin/llvm-config make +``` +If you try to use a new llvm version on an old Linux this can fail because of +old c++ libraries. In this case usually switching to gcc/g++ to compile +llvm_mode will work: +``` +LLVM_CONFIG=llvm-config-7 REAL_CC=gcc REAL_CXX=g++ make +``` +It is highly recommended to use the newest clang version you can put your +hands on :) + +## 2b) How to use this - long In order to leverage this mechanism, you need to have clang installed on your system. You should also make sure that the llvm-config tool is in your path diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 8867ae36..722ca421 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -152,7 +152,7 @@ static void __afl_map_shm(void) { if (getenv("AFL_DEBUG")) fprintf(stderr, - "DEBUG: id_str %s, __afl_map_addr 0x%x, MAP_SIZE %u, " + "DEBUG: id_str %s, __afl_map_addr 0x%lx, MAP_SIZE %u, " "__afl_final_loc %u, max_size_forkserver %u/0x%x\n", id_str == NULL ? "" : id_str, __afl_map_addr, MAP_SIZE, __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE); -- cgit 1.4.1 From 378573ab8b2f9b150429503c649e86e0fed4e946 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 2 May 2020 00:39:13 +0200 Subject: AFL_LLVM_SKIP_NEVERZERO added --- docs/Changelog.md | 3 +++ docs/env_variables.md | 4 ++++ llvm_mode/LLVMInsTrim.so.cc | 5 +++-- llvm_mode/README.neverzero.md | 10 +++++++++- llvm_mode/afl-clang-fast.c | 6 ++++++ llvm_mode/afl-llvm-lto-instrumentation.so.cc | 14 +++++++++++--- llvm_mode/afl-llvm-pass.so.cc | 10 +++++----- src/afl-common.c | 7 ++++--- 8 files changed, 45 insertions(+), 14 deletions(-) (limited to 'llvm_mode') diff --git a/docs/Changelog.md b/docs/Changelog.md index 565bee72..cae99681 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,6 +20,9 @@ sending a mail to . address for the shared memory map is used as this increases the fuzzing speed - fixes to LTO mode if instrumented edges > MAP_SIZE + - added AFL_LLVM_SKIP_NEVERZERO to skip the never zero coverage counter + implmentation. For targets with little or no loops or heavy called + functions. Gives a small performance boost. - qemu_mode: - add information on PIE/PIC load addresses for 32 bit - better dependency checks diff --git a/docs/env_variables.md b/docs/env_variables.md index 41c8f12a..bdbb8520 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -204,6 +204,10 @@ Then there are a few specific features that are only available in llvm_mode: slowdown due a performance issue that is only fixed in llvm 9+. This feature increases path discovery by a little bit. + - Setting AFL_LLVM_SKIP_NEVERZERO=1 will not implement the skip zero + test. If the target performs only few loops then this will give a + small performance boost. + See llvm_mode/README.neverzero.md ### CMPLOG diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index 98263ef1..c78250eb 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -56,6 +56,7 @@ struct InsTrim : public ModulePass { protected: uint32_t function_minimum_size = 1; uint32_t debug = 0; + char * skip_nozero = NULL; private: std::mt19937 generator; @@ -112,6 +113,7 @@ struct InsTrim : public ModulePass { if ((neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO")) != NULL) if (!be_quiet) OKF("LLVM neverZero activated (by hexcoder)\n"); #endif + skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); if (getenv("AFL_LLVM_INSTRIM_LOOPHEAD") != NULL || getenv("LOOPHEAD") != NULL) { @@ -304,8 +306,7 @@ struct InsTrim : public ModulePass { NULL) // with llvm 9 we make this the default as the bug in llvm is // then fixed #else - if (1) // with llvm 9 we make this the default as the bug in llvm is - // then fixed + if (!skip_nozero) #endif { diff --git a/llvm_mode/README.neverzero.md b/llvm_mode/README.neverzero.md index 1e406560..903e5bd3 100644 --- a/llvm_mode/README.neverzero.md +++ b/llvm_mode/README.neverzero.md @@ -20,8 +20,16 @@ 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 +If you want to enable this for llvm versions below 9 then set ``` export AFL_LLVM_NOT_ZERO=1 ``` + +In case you are on llvm 9 or greater and you do not want this behaviour then +you can set: +``` +AFL_LLVM_SKIP_NEVERZERO=1 +``` +If the target does not have extensive loops or functions that are called +a lot then this can give a small performance boost. diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 3de5fd7d..c59b814d 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -562,6 +562,11 @@ int main(int argc, char **argv, char **envp) { instrument_mode = INSTRUMENT_PCGUARD; #endif + if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) + FATAL( + "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " + "together"); + if ((ptr = getenv("AFL_LLVM_INSTRUMENT")) != NULL) { if (strncasecmp(ptr, "default", strlen("default")) == 0 || @@ -726,6 +731,7 @@ int main(int argc, char **argv, char **envp) { "AFL_HARDEN: adds code hardening to catch memory bugs\n" "AFL_INST_RATIO: percentage of branches to instrument\n" "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" + "AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n" "AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to " "cascaded " diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 118ada52..2811d98e 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -78,6 +78,8 @@ class AFLLTOPass : public ModulePass { FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %d\n", ptr, MAP_SIZE - 1); + skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); + } void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -111,6 +113,7 @@ class AFLLTOPass : public ModulePass { int afl_global_id = 1, debug = 0, autodictionary = 0; uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0, total_instr = 0; uint64_t map_addr = 0x10000; + char * skip_nozero = NULL; }; @@ -614,9 +617,14 @@ bool AFLLTOPass::runOnModule(Module &M) { Value *Incr = IRB.CreateAdd(Counter, One); - auto cf = IRB.CreateICmpEQ(Incr, Zero); - auto carry = IRB.CreateZExt(cf, Int8Ty); - Incr = IRB.CreateAdd(Incr, carry); + if (skip_nozero) { + + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); + + } + IRB.CreateStore(Incr, MapPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 9314c3d1..3e9026c8 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -84,7 +84,7 @@ class AFLCoverage : public ModulePass { uint32_t ngram_size = 0; uint32_t debug = 0; uint32_t map_size = MAP_SIZE; - char * ctx_str = NULL; + char * ctx_str = NULL, *skip_nozero = NULL; }; @@ -180,6 +180,7 @@ bool AFLCoverage::runOnModule(Module &M) { #if LLVM_VERSION_MAJOR < 9 char *neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO"); #endif + skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); unsigned PrevLocSize; @@ -467,6 +468,9 @@ bool AFLCoverage::runOnModule(Module &M) { if (neverZero_counters_str != NULL) { // with llvm 9 we make this the default as the bug in llvm is // then fixed +#else + if (!skip_nozero) { + #endif /* hexcoder: Realize a counter that skips zero during overflow. * Once this counter reaches its maximum value, it next increments to 1 @@ -482,12 +486,8 @@ bool AFLCoverage::runOnModule(Module &M) { auto carry = IRB.CreateZExt(cf, Int8Ty); Incr = IRB.CreateAdd(Incr, carry); -#if LLVM_VERSION_MAJOR < 9 - } -#endif - IRB.CreateStore(Incr, MapPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); diff --git a/src/afl-common.c b/src/afl-common.c index 8f21ad94..54b2e790 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,9 +69,10 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", - "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", - "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", - "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", + "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", + "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", + "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "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_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally -- cgit 1.4.1 From 0c5c172a3045d2810d5e55169fbeece29620f7dd Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 2 May 2020 12:57:33 +0200 Subject: makefile fix --- llvm_mode/GNUmakefile | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'llvm_mode') diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 2cbe53cd..93886e47 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -93,11 +93,24 @@ ifeq "$(shell test -e $(CC) || echo 1 )" "1" ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1" # we found one in the local install directory, lets use these CC = $(BIN_DIR)/clang - CXX = $(BIN_DIR)/clang++ else # hope for the best - $(warning we have trouble finding clang/clang++ - llvm-config is not helping us) + $(warning we have trouble finding clang - llvm-config is not helping us) CC = clang + endif + endif +endif +# llvm-config --bindir may not providing a valid path, so ... +ifeq "$(shell test -e $(CXX) || echo 1 )" "1" + # however we must ensure that this is not a "CC=gcc make" + ifeq "$(shell command -v $(CXX) 2> /dev/null)" "" + # we do not have a valid CC variable so we try alternatives + ifeq "$(shell test -e '$(BIN_DIR)/clang++' && echo 1)" "1" + # we found one in the local install directory, lets use these + CXX = $(BIN_DIR)/clang++ + else + # hope for the best + $(warning we have trouble finding clang++ - llvm-config is not helping us) CXX = clang++ endif endif @@ -111,18 +124,18 @@ CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[ # We did exactly set these 26 lines above with these values, and it would break # "CC=gcc make" etc. usages ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" - CC_SAVE = $(LLVM_BINDIR)/clang + CC_SAVE := $(LLVM_BINDIR)/clang else - CC_SAVE = $(CC) + CC_SAVE := $(CC) endif ifeq "$(findstring clang, $(shell $(CXX) --version 2>/dev/null))" "" - CXX_SAVE = $(LLVM_BINDIR)/clang++ + CXX_SAVE := $(LLVM_BINDIR)/clang++ else - CXX_SAVE = $(CXX) + CXX_SAVE := $(CXX) endif -CLANG_BIN = $(CC_SAVE) -CLANGPP_BIN = $(CXX_SAVE) +CLANG_BIN := $(CC_SAVE) +CLANGPP_BIN := $(CXX_SAVE) ifeq "$(CC_SAVE)" "$(LLVM_BINDIR)/clang" USE_BINDIR = 1 @@ -150,13 +163,13 @@ ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .te CFLAGS_OPT = -march=native endif -ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" +ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" AFL_CLANG_FLTO ?= -flto=full else - ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" AFL_CLANG_FLTO ?= -flto=thin else - ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" AFL_CLANG_FLTO ?= -flto endif endif @@ -177,7 +190,7 @@ endif AFL_CLANG_FUSELD= ifneq "$(AFL_CLANG_FLTO)" "" -ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" +ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" AFL_CLANG_FUSELD=1 endif endif @@ -272,7 +285,6 @@ test_deps: @echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'" ifneq "$(CLANGVER)" "$(LLVMVER)" @echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)" - @echo "[!] Retry with the clang compiler from llvm: CC=`llvm-config --bindir`/clang" else @echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good." endif -- cgit 1.4.1 From 16c16b3e6e0cd678f5da76f757761fb821f1011f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 4 May 2020 18:01:47 +0200 Subject: ctx and ngram can be used together now --- docs/Changelog.md | 1 + docs/env_variables.md | 6 +- examples/afl_network_proxy/afl-network-client.c | 26 +-- llvm_mode/afl-clang-fast.c | 202 +++++++++++++++--------- llvm_mode/afl-llvm-pass.so.cc | 15 +- 5 files changed, 150 insertions(+), 100 deletions(-) (limited to 'llvm_mode') diff --git a/docs/Changelog.md b/docs/Changelog.md index cae99681..8c0624b6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,6 +20,7 @@ sending a mail to . address for the shared memory map is used as this increases the fuzzing speed - fixes to LTO mode if instrumented edges > MAP_SIZE + - CTX and NGRAM can now be used together - added AFL_LLVM_SKIP_NEVERZERO to skip the never zero coverage counter implmentation. For targets with little or no loops or heavy called functions. Gives a small performance boost. diff --git a/docs/env_variables.md b/docs/env_variables.md index bdbb8520..ab5808ec 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -97,12 +97,14 @@ Then there are a few specific features that are only available in llvm_mode: - AFL_LLVM_INSTRUMENT - this configures the instrumentation mode. Available options: - DEFAULT - classic AFL (map[cur_loc ^ prev_loc >> 1]++) + CLASSIC - classic AFL (map[cur_loc ^ prev_loc >> 1]++) (default) CFG - InsTrim instrumentation (see below) LTO - LTO instrumentation (see below) CTX - context sensitive instrumentation (see below) NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16) - Only one can be used. + In CLASSIC (default) can can also specify CTX and/nor NGRAM, seperate + the options with a comma "," then, e.g.: + AFL_LLVM_INSTRUMENT=CLASSIC,CTX,NGRAM-4 ### LTO diff --git a/examples/afl_network_proxy/afl-network-client.c b/examples/afl_network_proxy/afl-network-client.c index 781ea328..cf09b2ad 100644 --- a/examples/afl_network_proxy/afl-network-client.c +++ b/examples/afl_network_proxy/afl-network-client.c @@ -321,7 +321,7 @@ int main(int argc, char *argv[]) { // fprintf(stderr, "Sending testcase with len %u\n", *lenptr); #ifdef USE_DEFLATE - #ifdef COMPRESS_TESTCASES +#ifdef COMPRESS_TESTCASES // we only compress the testcase if it does not fit in the TCP packet if (*lenptr > 1500 - 20 - 32 - 4) { @@ -331,25 +331,27 @@ int main(int argc, char *argv[]) { buf2 + 8, buf2_len); if (send(s, buf2, *lenptr2 + 8, 0) != *lenptr2 + 8) PFATAL("sending test data failed"); - //fprintf(stderr, "COMPRESS (%u->%u):\n", *lenptr, *lenptr2); - //for (u32 i = 0; i < *lenptr; i++) + // fprintf(stderr, "COMPRESS (%u->%u):\n", *lenptr, *lenptr2); + // for (u32 i = 0; i < *lenptr; i++) // fprintf(stderr, "%02x", buf[i + 4]); - //fprintf(stderr, "\n"); - //for (u32 i = 0; i < *lenptr2; i++) + // fprintf(stderr, "\n"); + // for (u32 i = 0; i < *lenptr2; i++) // fprintf(stderr, "%02x", buf2[i + 8]); - //fprintf(stderr, "\n"); + // fprintf(stderr, "\n"); } else { - #endif + +#endif #endif if (send(s, buf, *lenptr + 4, 0) != *lenptr + 4) PFATAL("sending test data failed"); #ifdef USE_DEFLATE - #ifdef COMPRESS_TESTCASES +#ifdef COMPRESS_TESTCASES // fprintf(stderr, "unCOMPRESS (%u)\n", *lenptr); } - #endif + +#endif #endif received = 0; @@ -381,9 +383,9 @@ int main(int argc, char *argv[]) { &decompress_len) != LIBDEFLATE_SUCCESS || decompress_len != __afl_map_size) FATAL("decompression failed"); - // fprintf(stderr, "DECOMPRESS (%u->%u): ", compress_len, decompress_len); - // for (u32 i = 0; i < __afl_map_size; i++) fprintf(stderr, "%02x", - // __afl_area_ptr[i]); fprintf(stderr, "\n"); + // fprintf(stderr, "DECOMPRESS (%u->%u): ", compress_len, decompress_len); + // for (u32 i = 0; i < __afl_map_size; i++) fprintf(stderr, "%02x", + // __afl_area_ptr[i]); fprintf(stderr, "\n"); #else while (received < __afl_map_size && (ret = recv(s, __afl_area_ptr + received, __afl_map_size - received, diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index c59b814d..9f85e5c6 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -43,7 +43,7 @@ static u8 * obj_path; /* Path to runtime libraries */ static u8 **cc_params; /* Parameters passed to the real CC */ static u32 cc_par_cnt = 1; /* Param count, including argv0 */ static u8 llvm_fullpath[PATH_MAX]; -static u8 instrument_mode; +static u8 instrument_mode, instrument_opt_mode, ngram_size; static u8 * lto_flag = AFL_CLANG_FLTO; static u8 * march_opt = CFLAGS_OPT; static u8 debug; @@ -60,14 +60,15 @@ enum { INSTRUMENT_INSTRIM = 2, INSTRUMENT_CFG = 2, INSTRUMENT_LTO = 3, - INSTRUMENT_CTX = 4, - INSTRUMENT_NGRAM = 5 // + ngram value of 2-16 = 7 - 21 + INSTRUMENT_OPT_CTX = 4, + INSTRUMENT_OPT_NGRAM = 8 }; -char instrument_mode_string[6][16] = { +char instrument_mode_string[10][16] = { - "DEFAULT", "PCGUARD", "CFG", "LTO", "CTX", + "CLASSIC", "PCGUARD", "CFG", "LTO", "CTX", "", + "", "", "NGRAM", "" }; @@ -562,59 +563,6 @@ int main(int argc, char **argv, char **envp) { instrument_mode = INSTRUMENT_PCGUARD; #endif - if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) - FATAL( - "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " - "together"); - - if ((ptr = getenv("AFL_LLVM_INSTRUMENT")) != NULL) { - - if (strncasecmp(ptr, "default", strlen("default")) == 0 || - strncasecmp(ptr, "afl", strlen("afl")) == 0 || - strncasecmp(ptr, "classic", strlen("classic")) == 0) - instrument_mode = INSTRUMENT_DEFAULT; - if (strncasecmp(ptr, "cfg", strlen("cfg")) == 0 || - strncasecmp(ptr, "instrim", strlen("instrim")) == 0) - instrument_mode = INSTRUMENT_CFG; - else if (strncasecmp(ptr, "pc-guard", strlen("pc-guard")) == 0 || - strncasecmp(ptr, "pcguard", strlen("pcgard")) == 0) - instrument_mode = INSTRUMENT_PCGUARD; - else if (strncasecmp(ptr, "lto", strlen("lto")) == 0) - instrument_mode = INSTRUMENT_LTO; - else if (strncasecmp(ptr, "ctx", strlen("ctx")) == 0) { - - instrument_mode = INSTRUMENT_CTX; - setenv("AFL_LLVM_CTX", "1", 1); - - } else if (strncasecmp(ptr, "ngram", strlen("ngram")) == 0) { - - ptr += strlen("ngram"); - while (*ptr && (*ptr < '0' || *ptr > '9')) - ptr++; - if (!*ptr) - if ((ptr = getenv("AFL_LLVM_NGRAM_SIZE")) != NULL) - FATAL( - "you must set the NGRAM size with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ngram-2"); - instrument_mode = INSTRUMENT_NGRAM + atoi(ptr); - if (instrument_mode < INSTRUMENT_NGRAM + 2 || - instrument_mode > INSTRUMENT_NGRAM + NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " - "(%u)", - NGRAM_SIZE_MAX); - - ptr = alloc_printf("%u", instrument_mode - INSTRUMENT_NGRAM); - setenv("AFL_LLVM_NGRAM_SIZE", ptr, 1); - - } else if (strncasecmp(ptr, "classic", strlen("classic")) != 0 || - - strncasecmp(ptr, "default", strlen("default")) != 0 || - strncasecmp(ptr, "afl", strlen("afl")) != 0) - FATAL("unknown AFL_LLVM_INSTRUMENT value: %s", ptr); - - } - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { @@ -636,39 +584,116 @@ int main(int argc, char **argv, char **envp) { } - if (getenv("AFL_LLVM_CTX")) { + if (getenv("AFL_LLVM_CTX")) instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (instrument_mode == 0) - instrument_mode = INSTRUMENT_CTX; - else if (instrument_mode != INSTRUMENT_CTX) - FATAL("you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_CTX together"); + if (getenv("AFL_LLVM_NGRAM_SIZE")) { + + instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; + ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); + if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) + FATAL( + "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " + "(%u)", + NGRAM_SIZE_MAX); } - if (getenv("AFL_LLVM_NGRAM_SIZE")) { + if (getenv("AFL_LLVM_INSTRUMENT")) { - if (instrument_mode == 0) { + u8 *ptr = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); - instrument_mode = INSTRUMENT_NGRAM + atoi(getenv("AFL_LLVM_NGRAM_SIZE")); - if (instrument_mode < INSTRUMENT_NGRAM + 2 || - instrument_mode > INSTRUMENT_NGRAM + NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " - "(%u)", - NGRAM_SIZE_MAX); + while (ptr) { - } else if (instrument_mode != INSTRUMENT_NGRAM) + if (strncasecmp(ptr, "default", strlen("default")) == 0 || + strncasecmp(ptr, "afl", strlen("afl")) == 0 || + strncasecmp(ptr, "classic", strlen("classic")) == 0) { - FATAL( - "you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_NGRAM_SIZE " - "together"); + if (!instrument_mode || instrument_mode == INSTRUMENT_DEFAULT) + instrument_mode = INSTRUMENT_DEFAULT; + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_string[instrument_mode]); + + } + + if (strncasecmp(ptr, "pc-guard", strlen("pc-guard")) == 0 || + strncasecmp(ptr, "pcguard", strlen("pcgard")) == 0) { + + if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) + instrument_mode = INSTRUMENT_PCGUARD; + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_string[instrument_mode]); + + } + + if (strncasecmp(ptr, "cfg", strlen("cfg")) == 0 || + strncasecmp(ptr, "instrim", strlen("instrim")) == 0) { + + if (!instrument_mode || instrument_mode == INSTRUMENT_CFG) + instrument_mode = INSTRUMENT_CFG; + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_string[instrument_mode]); + + } + + if (strncasecmp(ptr, "lto", strlen("lto")) == 0) { + + if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) + instrument_mode = INSTRUMENT_LTO; + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_string[instrument_mode]); + + } + + if (strncasecmp(ptr, "ctx", strlen("ctx")) == 0) { + + instrument_opt_mode |= INSTRUMENT_OPT_CTX; + setenv("AFL_LLVM_CTX", "1", 1); + + } + + if (strncasecmp(ptr, "ngram", strlen("ngram")) == 0) { + + ptr += strlen("ngram"); + while (*ptr && (*ptr < '0' || *ptr > '9')) + ptr++; + if (!*ptr) + if ((ptr = getenv("AFL_LLVM_NGRAM_SIZE")) != NULL) + FATAL( + "you must set the NGRAM size with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ngram-2"); + ngram_size = atoi(ptr); + if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) + FATAL( + "NGRAM instrumentation option must be between 2 and " + "NGRAM_SIZE_MAX " + "(%u)", + NGRAM_SIZE_MAX); + instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); + ptr = alloc_printf("%u", ngram_size); + setenv("AFL_LLVM_NGRAM_SIZE", ptr, 1); + + } + + ptr = strtok(NULL, ":,;"); + + } } - if (instrument_mode < INSTRUMENT_NGRAM) + if (!instrument_opt_mode) ptr = instrument_mode_string[instrument_mode]; + else if (instrument_opt_mode == INSTRUMENT_OPT_CTX) + ptr = alloc_printf("%s + CTX", instrument_mode_string[instrument_mode]); + else if (instrument_opt_mode == INSTRUMENT_OPT_NGRAM) + ptr = alloc_printf("%s + NGRAM-%u", instrument_mode_string[instrument_mode], + ngram_size); else - ptr = alloc_printf("NGRAM-%u", instrument_mode - INSTRUMENT_NGRAM); + ptr = alloc_printf("%s + CTX + NGRAM-%u", + instrument_mode_string[instrument_mode], ngram_size); if (strstr(argv[0], "afl-clang-lto") != NULL) { @@ -690,9 +715,28 @@ int main(int argc, char **argv, char **envp) { #ifndef AFL_CLANG_FLTO if (instrument_mode == INSTRUMENT_LTO) - FATAL("instrumentation mode LTO specified but LLVM support not available"); + FATAL( + "instrumentation mode LTO specified but LLVM support not available " + "(requires LLVM 11)"); #endif + if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) + /*&& instrument_mode != INSTRUMENT_CFG*/ + FATAL( + "CTX and NGRAM instrumentation options can only be used with the " + "CLASSIC instrumentation mode!"); + + if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) + FATAL( + "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " + "together"); + + if (instrument_mode == INSTRUMENT_CFG && + getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") == NULL && ngram_size) + FATAL( + "NGRAM option together with CFG/INSTRIM instrumentation mode can only " + "be used if AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK is set"); + if (argc < 2 || strcmp(argv[1], "-h") == 0) { if (instrument_mode != INSTRUMENT_LTO) diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 3e9026c8..42a2f3af 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -182,7 +182,7 @@ bool AFLCoverage::runOnModule(Module &M) { #endif skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); - unsigned PrevLocSize; + unsigned PrevLocSize = 0; char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE"); if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE"); @@ -216,9 +216,6 @@ bool AFLCoverage::runOnModule(Module &M) { if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize); #endif - if (ctx_str && ngram_size_str) - FATAL("you must decide between NGRAM and CTX instrumentation"); - /* Get globals for the SHM region and the previous location. Note that __afl_prev_loc is thread-local. */ @@ -437,8 +434,10 @@ bool AFLCoverage::runOnModule(Module &M) { PrevLocTrans = IRB.CreateXorReduce(PrevLoc); else #endif - if (ctx_str) - PrevLocTrans = IRB.CreateZExt(IRB.CreateXor(PrevLoc, PrevCtx), Int32Ty); + PrevLocTrans = PrevLoc; + if (ctx_str) + PrevLocTrans = + IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCtx), Int32Ty); else PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); @@ -452,7 +451,9 @@ bool AFLCoverage::runOnModule(Module &M) { if (ngram_size) MapPtrIdx = IRB.CreateGEP( MapPtr, - IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, CurLoc), Int32Ty)); + IRB.CreateZExt( + IRB.CreateXor(PrevLocTrans, IRB.CreateZExt(CurLoc, Int32Ty)), + Int32Ty)); else #endif MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, CurLoc)); -- cgit 1.4.1 From 95a2d4923244473b59e2b1a6012ad2e186d3b2a4 Mon Sep 17 00:00:00 2001 From: David Mendenhall Date: Mon, 4 May 2020 11:30:06 -0700 Subject: Fix typo in README.lto.md --- llvm_mode/README.lto.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'llvm_mode') diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index bb66b5e7..d8e4766d 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -65,7 +65,7 @@ $ cd build $ cmake -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;compiler-rt;libclc;libcxx;libcxxabi;libunwind;lld' -DCMAKE_BUILD_TYPE=Release -DLLVM_BINUTILS_INCDIR=/usr/include/ ../llvm/ $ make -j $(nproc) $ export PATH=`pwd`/bin:$PATH -$ export LLVM_CONFIG=`pwd`/bin/llcm-config +$ export LLVM_CONFIG=`pwd`/bin/llvm-config $ cd /path/to/AFLplusplus/ $ make $ cd llvm_mode -- cgit 1.4.1 From 6e45e55d82eeed2075579a530f5aeea8d00af55b Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 10:38:44 +0200 Subject: fix crash in AFL_LLVM_LAF_TRANSFORM_COMPARES --- docs/Changelog.md | 1 + llvm_mode/afl-llvm-rt.o.c | 15 ++++++--------- llvm_mode/compare-transform-pass.so.cc | 12 ++++++++---- test/test.sh | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) (limited to 'llvm_mode') diff --git a/docs/Changelog.md b/docs/Changelog.md index 8c0624b6..ac68e8ff 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -21,6 +21,7 @@ sending a mail to . fuzzing speed - fixes to LTO mode if instrumented edges > MAP_SIZE - CTX and NGRAM can now be used together + - AFL_LLVM_LAF_TRANSFORM_COMPARES would sometimes crash, fixed - added AFL_LLVM_SKIP_NEVERZERO to skip the never zero coverage counter implmentation. For targets with little or no loops or heavy called functions. Gives a small performance boost. diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 722ca421..56038f7a 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -67,22 +67,19 @@ u8 __afl_area_initial[MAP_SIZE]; u8 *__afl_area_ptr = __afl_area_initial; u8 *__afl_dictionary; +u32 __afl_final_loc; +u32 __afl_map_size = MAP_SIZE; +u32 __afl_dictionary_len; +u64 __afl_map_addr; + #ifdef __ANDROID__ PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; -u32 __afl_final_loc; u32 __afl_prev_ctx; u32 __afl_cmp_counter; -u32 __afl_dictionary_len; -u32 __afl_map_size = MAP_SIZE; -u64 __afl_map_addr; #else __thread PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; -__thread u32 __afl_final_loc; __thread u32 __afl_prev_ctx; __thread u32 __afl_cmp_counter; -__thread u32 __afl_dictionary_len; -__thread u32 __afl_map_size = MAP_SIZE; -__thread u64 __afl_map_addr; #endif struct cmp_map *__afl_cmp_map; @@ -152,7 +149,7 @@ static void __afl_map_shm(void) { if (getenv("AFL_DEBUG")) fprintf(stderr, - "DEBUG: id_str %s, __afl_map_addr 0x%lx, MAP_SIZE %u, " + "DEBUG: id_str %s, __afl_map_addr 0x%llx, MAP_SIZE %u, " "__afl_final_loc %u, max_size_forkserver %u/0x%x\n", id_str == NULL ? "" : id_str, __afl_map_addr, MAP_SIZE, __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE); diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc index c871c1c4..9cf4169e 100644 --- a/llvm_mode/compare-transform-pass.so.cc +++ b/llvm_mode/compare-transform-pass.so.cc @@ -386,13 +386,13 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, TmpConstStr = Str1.str(); VarStr = Str2P; - constLen = isMemcmp ? sizedLen : GetStringLength(Str1P); + constLen = isMemcmp ? sizedLen : TmpConstStr.length(); } else { TmpConstStr = Str2.str(); VarStr = Str1P; - constLen = isMemcmp ? sizedLen : GetStringLength(Str2P); + constLen = isMemcmp ? sizedLen : TmpConstStr.length(); } @@ -401,8 +401,12 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, * runtime bounds checking, which makes debugging easier) */ TmpConstStr.append("\0", 1); ConstStr = StringRef(TmpConstStr); - - if (isSizedcmp && constLen > sizedLen) { constLen = sizedLen; } + // fprintf(stderr, "issized: %d, const > sized ? %u > %u\n", isSizedcmp, + // constLen, sizedLen); + if (isSizedcmp && constLen > sizedLen && sizedLen) constLen = sizedLen; + if (constLen > TmpConstStr.length()) constLen = TmpConstStr.length(); + if (!constLen) constLen = TmpConstStr.length(); + if (!constLen) continue; if (!be_quiet) errs() << callInst->getCalledFunction()->getName() << ": len " << constLen diff --git a/test/test.sh b/test/test.sh index e950e3de..90633a9f 100755 --- a/test/test.sh +++ b/test/test.sh @@ -81,7 +81,7 @@ test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && { } || { AFL_GCC=afl-gcc } -command -v gcc || AFL_GCC=afl-clang +command -v gcc >/dev/null 2>&1 || AFL_GCC=afl-clang SYS=`uname -m` -- cgit 1.4.1 From 9d384b4e383e2b216847e2ed3aee432a25cd37d8 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 12:46:49 +0200 Subject: ctx and ngram fix --- llvm_mode/afl-llvm-pass.so.cc | 128 +++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 53 deletions(-) (limited to 'llvm_mode') diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 42a2f3af..c0391b04 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -294,70 +294,52 @@ bool AFLCoverage::runOnModule(Module &M) { if (!isInWhitelist(&F)) continue; - if (ctx_str && F.size() > 1) { // Context sensitive coverage - // load the context ID of the previous function and write to to a local - // variable on the stack - auto bb = &F.getEntryBlock(); - BasicBlock::iterator IP = bb->getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); - PrevCtx = IRB.CreateLoad(AFLContext); - PrevCtx->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - - // does the function have calls? and is any of the calls larger than one - // basic block? - has_calls = 0; - for (auto &BB : F) { - - if (has_calls) break; - for (auto &IN : BB) { - - CallInst *callInst = nullptr; - if ((callInst = dyn_cast(&IN))) { - - Function *Callee = callInst->getCalledFunction(); - if (!Callee || Callee->size() < 2) - continue; - else { + for (auto &BB : F) { - has_calls = 1; - break; + BasicBlock::iterator IP = BB.getFirstInsertionPt(); + IRBuilder<> IRB(&(*IP)); - } + // Context sensitive coverage + if (ctx_str && &BB == &F.getEntryBlock() && F.size() > 1) { - } + // load the context ID of the previous function and write to to a local + // variable on the stack + PrevCtx = IRB.CreateLoad(AFLContext); + PrevCtx->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } + // does the function have calls? and is any of the calls larger than one + // basic block? + for (auto &BB : F) { - } + if (has_calls) break; + for (auto &IN : BB) { - // if yes we store a context ID for this function in the global var - if (has_calls) { + CallInst *callInst = nullptr; + if ((callInst = dyn_cast(&IN))) { - ConstantInt *NewCtx = ConstantInt::get(Int32Ty, AFL_R(map_size)); - StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext); - StoreCtx->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(C, None)); + Function *Callee = callInst->getCalledFunction(); + if (!Callee || Callee->size() < 2) + continue; + else { - } + has_calls = 1; + break; - } + } - for (auto &BB : F) { + } - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); + } - // in CTX mode we have to restore the original context for the caller - - // she might be calling other functions which need the correct CTX - if (ctx_str && has_calls) { + } - Instruction *Inst = BB.getTerminator(); - if (isa(Inst) || isa(Inst)) { + // if yes we store a context ID for this function in the global var + if (has_calls) { - IRBuilder<> Post_IRB(Inst); - StoreInst * RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); - RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(C, None)); + ConstantInt *NewCtx = ConstantInt::get(Int32Ty, AFL_R(map_size)); + StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext); + StoreCtx->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); } @@ -407,7 +389,28 @@ bool AFLCoverage::runOnModule(Module &M) { } // fprintf(stderr, " == %d\n", more_than_one); - if (more_than_one != 1) continue; + if (more_than_one != 1) { + + // in CTX mode we have to restore the original context for the caller - + // she might be calling other functions which need the correct CTX + if (ctx_str && has_calls && F.size() > 1) { + + Instruction *Inst = BB.getTerminator(); + if (isa(Inst) || isa(Inst)) { + + IRBuilder<> Post_IRB(Inst); + StoreInst * RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); + RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } + + } + + continue; + + } + #endif ConstantInt *CurLoc; @@ -431,15 +434,17 @@ bool AFLCoverage::runOnModule(Module &M) { prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */ if (ngram_size) - PrevLocTrans = IRB.CreateXorReduce(PrevLoc); + PrevLocTrans = + IRB.CreateZExt(IRB.CreateXorReduce(PrevLoc), IRB.getInt32Ty()); else #endif PrevLocTrans = PrevLoc; + if (ctx_str) PrevLocTrans = IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCtx), Int32Ty); else - PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); + PrevLocTrans = IRB.CreateZExt(PrevLocTrans, IRB.getInt32Ty()); /* Load SHM pointer */ @@ -518,6 +523,23 @@ bool AFLCoverage::runOnModule(Module &M) { } + // in CTX mode we have to restore the original context for the caller - + // she might be calling other functions which need the correct CTX. + // Currently this is only needed for the Ubuntu clang-6.0 bug + if (ctx_str && has_calls && F.size() > 1) { + + Instruction *Inst = BB.getTerminator(); + if (isa(Inst) || isa(Inst)) { + + IRBuilder<> Post_IRB(Inst); + StoreInst * RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); + RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } + + } + inst_blocks++; } -- cgit 1.4.1 From d82ada89fee37068b0ff44f340338af3fc07cc37 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 14:08:24 +0200 Subject: support older llvm versions --- llvm_mode/compare-transform-pass.so.cc | 42 ++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'llvm_mode') diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc index 9cf4169e..10413076 100644 --- a/llvm_mode/compare-transform-pass.so.cc +++ b/llvm_mode/compare-transform-pass.so.cc @@ -211,20 +211,24 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } // not literal? maybe global or local variable - if (!(HasStr1 ^ HasStr2)) { + if (!(HasStr1 || HasStr2)) { auto *Ptr = dyn_cast(Str2P); if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { - if (auto *Array = - dyn_cast(Var->getInitializer())) { + if (Var->hasInitializer()) { - HasStr2 = true; - Str2 = Array->getAsString(); - valueMap[Str2P] = new std::string(Str2.str()); - // fprintf(stderr, "glo2 %s\n", Str2.str().c_str()); + if (auto *Array = + dyn_cast(Var->getInitializer())) { + + HasStr2 = true; + Str2 = Array->getAsString(); + valueMap[Str2P] = new std::string(Str2.str()); + fprintf(stderr, "glo2 %s\n", Str2.str().c_str()); + + } } @@ -239,13 +243,17 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, if (auto *Var = dyn_cast(Ptr->getOperand(0))) { - if (auto *Array = - dyn_cast(Var->getInitializer())) { + if (Var->hasInitializer()) { + + if (auto *Array = dyn_cast( + Var->getInitializer())) { + + HasStr1 = true; + Str1 = Array->getAsString(); + valueMap[Str1P] = new std::string(Str1.str()); + // fprintf(stderr, "glo1 %s\n", Str1.str().c_str()); - HasStr1 = true; - Str1 = Array->getAsString(); - valueMap[Str1P] = new std::string(Str1.str()); - // fprintf(stderr, "glo1 %s\n", Str1.str().c_str()); + } } @@ -260,13 +268,13 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } - if ((HasStr1 ^ HasStr2)) indirect = true; + if ((HasStr1 || HasStr2)) indirect = true; } if (isIntMemcpy) continue; - if (!(HasStr1 ^ HasStr2)) { + if (!(HasStr1 || HasStr2)) { // do we have a saved local variable initialization? std::string *val = valueMap[Str1P]; @@ -294,7 +302,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } /* handle cases of one string is const, one string is variable */ - if (!(HasStr1 ^ HasStr2)) continue; + if (!(HasStr1 || HasStr2)) continue; if (isMemcmp || isStrncmp || isStrncasecmp) { @@ -359,7 +367,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } - if (!(HasStr1 ^ HasStr2)) { + if (!(HasStr1 || HasStr2)) { // do we have a saved local or global variable initialization? std::string *val = valueMap[Str1P]; -- cgit 1.4.1 From d6346561dbe2a00472eda76e8a1276b77e0f67a7 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 15:37:02 +0200 Subject: ctx+ngram for instrim --- docs/Changelog.md | 3 +- llvm_mode/LLVMInsTrim.so.cc | 262 ++++++++++++++++++++++++++++++++++++++------ llvm_mode/afl-clang-fast.c | 14 +-- 3 files changed, 233 insertions(+), 46 deletions(-) (limited to 'llvm_mode') diff --git a/docs/Changelog.md b/docs/Changelog.md index ac68e8ff..e4ac8783 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -21,7 +21,8 @@ sending a mail to . fuzzing speed - fixes to LTO mode if instrumented edges > MAP_SIZE - CTX and NGRAM can now be used together - - AFL_LLVM_LAF_TRANSFORM_COMPARES would sometimes crash, fixed + - CTX and NGRAM are now also supported in CFG/INSTRIM mode + - AFL_LLVM_LAF_TRANSFORM_COMPARES could, fixed - added AFL_LLVM_SKIP_NEVERZERO to skip the never zero coverage counter implmentation. For targets with little or no loops or heavy called functions. Gives a small performance boost. diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index c78250eb..ad046a8b 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -36,11 +36,12 @@ typedef long double max_align_t; #include #include -#include "config.h" -#include "debug.h" - #include "MarkNodes.h" #include "afl-llvm-common.h" +#include "llvm-ngram-coverage.h" + +#include "config.h" +#include "debug.h" using namespace llvm; @@ -94,9 +95,15 @@ struct InsTrim : public ModulePass { } +#if LLVM_VERSION_MAJOR >= 4 || \ + (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) +#define AFL_HAVE_VECTOR_INTRINSICS 1 +#endif + bool runOnModule(Module &M) override { char be_quiet = 0; + int ngram_size = 0; if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) { @@ -108,6 +115,11 @@ struct InsTrim : public ModulePass { if (getenv("AFL_DEBUG") != NULL) debug = 1; + LLVMContext &C = M.getContext(); + + IntegerType *Int8Ty = IntegerType::getInt8Ty(C); + IntegerType *Int32Ty = IntegerType::getInt32Ty(C); + #if LLVM_VERSION_MAJOR < 9 char *neverZero_counters_str; if ((neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO")) != NULL) @@ -125,24 +137,107 @@ struct InsTrim : public ModulePass { if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") != NULL) function_minimum_size = 2; - // this is our default - MarkSetOpt = true; + unsigned PrevLocSize = 0; + char * ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE"); + if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE"); + char *ctx_str = getenv("AFL_LLVM_CTX"); + +#ifdef AFL_HAVE_VECTOR_INTRINSICS + /* Decide previous location vector size (must be a power of two) */ + VectorType *PrevLocTy; + + if (ngram_size_str) + if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 || + ngram_size > NGRAM_SIZE_MAX) + FATAL( + "Bad value of AFL_NGRAM_SIZE (must be between 2 and NGRAM_SIZE_MAX " + "(%u))", + NGRAM_SIZE_MAX); + + if (ngram_size) + PrevLocSize = ngram_size - 1; + else +#else + if (ngram_size_str) + FATAL( + "Sorry, NGRAM branch coverage is not supported with llvm version %s!", + LLVM_VERSION_STRING); +#endif + PrevLocSize = 1; + +#ifdef AFL_HAVE_VECTOR_INTRINSICS + // IntegerType *Int64Ty = IntegerType::getInt64Ty(C); + uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize); + IntegerType *IntLocTy = + IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT); + if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize); +#endif - LLVMContext &C = M.getContext(); - IntegerType *Int8Ty = IntegerType::getInt8Ty(C); - IntegerType *Int32Ty = IntegerType::getInt32Ty(C); + /* Get globals for the SHM region and the previous location. Note that + __afl_prev_loc is thread-local. */ - GlobalVariable *CovMapPtr = new GlobalVariable( - M, PointerType::getUnqual(Int8Ty), false, GlobalValue::ExternalLinkage, - nullptr, "__afl_area_ptr"); + GlobalVariable *AFLMapPtr = + new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, + GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); + GlobalVariable *AFLPrevLoc; + GlobalVariable *AFLContext; + LoadInst * PrevCtx = NULL; // for CTX sensitive coverage - GlobalVariable *OldPrev = new GlobalVariable( + if (ctx_str) +#ifdef __ANDROID__ + AFLContext = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx"); +#else + AFLContext = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx", + 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); +#endif + +#ifdef AFL_HAVE_VECTOR_INTRINSICS + if (ngram_size) +#ifdef __ANDROID__ + AFLPrevLoc = new GlobalVariable( + M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, + /* Initializer */ nullptr, "__afl_prev_loc"); +#else + AFLPrevLoc = new GlobalVariable( + M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, + /* Initializer */ nullptr, "__afl_prev_loc", + /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel, + /* AddressSpace */ 0, /* IsExternallyInitialized */ false); +#endif + else +#endif +#ifdef __ANDROID__ + AFLPrevLoc = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc"); +#else + AFLPrevLoc = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); +#endif + +#ifdef AFL_HAVE_VECTOR_INTRINSICS + /* Create the vector shuffle mask for updating the previous block history. + Note that the first element of the vector will store cur_loc, so just set + it to undef to allow the optimizer to do its thing. */ + + SmallVector PrevLocShuffle = {UndefValue::get(Int32Ty)}; + + for (unsigned I = 0; I < PrevLocSize - 1; ++I) + PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I)); + + for (unsigned I = PrevLocSize; I < PrevLocVecSize; ++I) + PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize)); + + Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle); +#endif + + // this is our default + MarkSetOpt = true; ConstantInt *Zero = ConstantInt::get(Int8Ty, 0); ConstantInt *One = ConstantInt::get(Int8Ty, 1); - ConstantInt *One32 = ConstantInt::get(Int32Ty, 1); u64 total_rs = 0; u64 total_hs = 0; @@ -240,13 +335,30 @@ struct InsTrim : public ModulePass { } - if (function_minimum_size < 2) { + for (BasicBlock &BB : F) { + + if (MS.find(&BB) == MS.end()) { continue; } + IRBuilder<> IRB(&*BB.getFirstInsertionPt()); + + if (ngram_size) { + + LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc); + PrevLoc->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); - for (BasicBlock &BB : F) { + Value *ShuffledPrevLoc = IRB.CreateShuffleVector( + PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask); + Value *UpdatedPrevLoc = IRB.CreateInsertElement( + ShuffledPrevLoc, ConstantInt::get(Int32Ty, genLabel()), + (uint64_t)0); - if (MS.find(&BB) == MS.end()) { continue; } - IRBuilder<> IRB(&*BB.getFirstInsertionPt()); - IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), OldPrev); + IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc) + ->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } else { + + IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), AFLPrevLoc); } @@ -254,18 +366,67 @@ struct InsTrim : public ModulePass { } + int has_calls = 0; for (BasicBlock &BB : F) { - if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; } + auto PI = pred_begin(&BB); + auto PE = pred_end(&BB); + IRBuilder<> IRB(&*BB.getFirstInsertionPt()); + Value * L = NULL; + unsigned int cur_loc; + + // Context sensitive coverage + if (ctx_str && &BB == &F.getEntryBlock()) { + + PrevCtx = IRB.CreateLoad(AFLContext); + PrevCtx->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + // does the function have calls? and is any of the calls larger than + // one basic block? + has_calls = 0; + for (auto &BB : F) { + + if (has_calls) break; + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + if ((callInst = dyn_cast(&IN))) { + + Function *Callee = callInst->getCalledFunction(); + if (!Callee || Callee->size() < 2) + continue; + else { + + has_calls = 1; + break; + + } + + } - auto PI = pred_begin(&BB); - auto PE = pred_end(&BB); - IRBuilder<> IRB(&*BB.getFirstInsertionPt()); - Value * L = NULL; + } + + } + + // if yes we store a context ID for this function in the global var + if (has_calls) { + + ConstantInt *NewCtx = ConstantInt::get(Int32Ty, genLabel()); + StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext); + StoreCtx->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } + + } // END of ctx_str + + if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; } - if (function_minimum_size < 2 && PI == PE) { + if (PI == PE) { - L = ConstantInt::get(Int32Ty, genLabel()); + cur_loc = genLabel(); + L = ConstantInt::get(Int32Ty, cur_loc); } else { @@ -276,6 +437,7 @@ struct InsTrim : public ModulePass { BasicBlock *PBB = *PI; auto It = PredMap.insert({PBB, genLabel()}); unsigned Label = It.first->second; + cur_loc = Label; PN->addIncoming(ConstantInt::get(Int32Ty, Label), PBB); } @@ -285,15 +447,37 @@ struct InsTrim : public ModulePass { } /* Load prev_loc */ - LoadInst *PrevLoc = IRB.CreateLoad(OldPrev); + LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc); PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - Value *PrevLocCasted = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); + Value *PrevLocTrans; + +#ifdef AFL_HAVE_VECTOR_INTRINSICS + /* "For efficiency, we propose to hash the tuple as a key into the + hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where + prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */ + + if (ngram_size) + PrevLocTrans = + IRB.CreateZExt(IRB.CreateXorReduce(PrevLoc), IRB.getInt32Ty()); + else +#endif + PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); + + if (ctx_str) + PrevLocTrans = + IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCtx), Int32Ty); /* Load SHM pointer */ - LoadInst *MapPtr = IRB.CreateLoad(CovMapPtr); + LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - Value *MapPtrIdx = - IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocCasted, L)); + Value *MapPtrIdx; +#ifdef AFL_HAVE_VECTOR_INTRINSICS + if (ngram_size) + MapPtrIdx = IRB.CreateGEP( + MapPtr, IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, L), Int32Ty)); + else +#endif + MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, L)); /* Update bitmap */ LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); @@ -329,12 +513,20 @@ struct InsTrim : public ModulePass { IRB.CreateStore(Incr, MapPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - // save the actually location ID to OldPrev if function_minimum_size > 1 - if (function_minimum_size > 1) { + if (ctx_str && has_calls) { + + // in CTX mode we have to restore the original context for the + // caller - she might be calling other functions which need the + // correct CTX + Instruction *Inst = BB.getTerminator(); + if (isa(Inst) || isa(Inst)) { - Value *Shr = IRB.CreateLShr(L, One32); - IRB.CreateStore(Shr, OldPrev) - ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); + IRBuilder<> Post_IRB(Inst); + StoreInst * RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); + RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } } diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 9f85e5c6..4b9999a6 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -720,23 +720,17 @@ int main(int argc, char **argv, char **envp) { "(requires LLVM 11)"); #endif - if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) - /*&& instrument_mode != INSTRUMENT_CFG*/ + if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC && + instrument_mode != INSTRUMENT_CFG) FATAL( - "CTX and NGRAM instrumentation options can only be used with the " - "CLASSIC instrumentation mode!"); + "CTX and NGRAM instrumentation options can only be used with CFG " + "(recommended) and CLASSIC instrumentation modes!"); if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) FATAL( "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " "together"); - if (instrument_mode == INSTRUMENT_CFG && - getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") == NULL && ngram_size) - FATAL( - "NGRAM option together with CFG/INSTRIM instrumentation mode can only " - "be used if AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK is set"); - if (argc < 2 || strcmp(argv[1], "-h") == 0) { if (instrument_mode != INSTRUMENT_LTO) -- cgit 1.4.1 From a38980c80babbb75038766c49774effc0bfa8222 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 17:57:56 +0200 Subject: unsized string compare fix --- llvm_mode/compare-transform-pass.so.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'llvm_mode') diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc index 10413076..2111b646 100644 --- a/llvm_mode/compare-transform-pass.so.cc +++ b/llvm_mode/compare-transform-pass.so.cc @@ -408,6 +408,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, * the StringRef (in comparison to std::string a StringRef has built-in * runtime bounds checking, which makes debugging easier) */ TmpConstStr.append("\0", 1); + if (!sizedLen) constLen++; ConstStr = StringRef(TmpConstStr); // fprintf(stderr, "issized: %d, const > sized ? %u > %u\n", isSizedcmp, // constLen, sizedLen); -- cgit 1.4.1 From 00683d06c2dc4a021929f25c86b8b426542c4e40 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 20:10:54 +0200 Subject: fix LTO mode --- TODO.md | 3 ++- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 16 ++++++---------- llvm_mode/afl-llvm-pass.so.cc | 3 +-- 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'llvm_mode') diff --git a/TODO.md b/TODO.md index f326b6c7..dd88dcc2 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,8 @@ ## Roadmap 2.65+ - - AFL_MAP_SIZE for afl-llvm-pass, qemu_mode and unicorn_mode + - InsTrim mode for LTO solution + - AFL_MAP_SIZE for qemu_mode and unicorn_mode - random crc32 HASH_CONST per run? because with 65536 paths we have collisions - namespace for targets? e.g. network - libradamsa as a custom module? diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 2811d98e..838e45af 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -690,8 +690,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if (map_addr) { GlobalVariable *AFLMapAddrFixed = new GlobalVariable( - M, Int64Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr", - 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); + M, Int64Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr"); ConstantInt *MapAddr = ConstantInt::get(Int64Ty, map_addr); StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed); StoreMapAddr->setMetadata(M.getMDKindID("nosanitize"), @@ -706,8 +705,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if (afl_global_id % 8) write_loc = (((afl_global_id + 8) >> 3) << 3); GlobalVariable *AFLFinalLoc = new GlobalVariable( - M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc", - 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); + M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc"); ConstantInt *const_loc = ConstantInt::get(Int32Ty, write_loc); StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"), @@ -756,10 +754,9 @@ bool AFLLTOPass::runOnModule(Module &M) { } - GlobalVariable *AFLDictionaryLen = new GlobalVariable( - M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, - "__afl_dictionary_len", 0, GlobalVariable::GeneralDynamicTLSModel, - 0, false); + GlobalVariable *AFLDictionaryLen = + new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, + 0, "__afl_dictionary_len"); ConstantInt *const_len = ConstantInt::get(Int32Ty, offset); StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen); StoreDictLen->setMetadata(M.getMDKindID("nosanitize"), @@ -770,8 +767,7 @@ bool AFLLTOPass::runOnModule(Module &M) { M, ArrayTy, true, GlobalValue::ExternalLinkage, ConstantDataArray::get(C, *(new ArrayRef((char *)ptr, offset))), - "__afl_internal_dictionary", 0, - GlobalVariable::GeneralDynamicTLSModel, 0, false); + "__afl_internal_dictionary"); AFLInternalDictionary->setInitializer(ConstantDataArray::get( C, *(new ArrayRef((char *)ptr, offset)))); AFLInternalDictionary->setConstant(true); diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index c0391b04..0d9e0aba 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -583,8 +583,7 @@ bool AFLCoverage::runOnModule(Module &M) { GlobalVariable *AFLFinalLoc = new GlobalVariable( M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, - "__afl_final_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0, - false); + "__afl_final_loc"); ConstantInt *const_loc = ConstantInt::get(Int32Ty, map_size); StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"), -- cgit 1.4.1 From 128e4d55651731a876cd33bee900021cf61ab39b Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 20:23:16 +0200 Subject: more typos fixed --- examples/afl_untracer/afl-untracer.c | 4 ++-- llvm_mode/afl-clang-fast.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'llvm_mode') diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index f812958c..d319b530 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -65,7 +65,7 @@ #include #include #else -#error "Unsupproted platform" +#error "Unsupported platform" #endif #define MEMORY_MAP_DECREMENT 0x200000000000 @@ -667,7 +667,7 @@ int main(int argc, char *argv[]) { fuzz(); // we can use _exit which is faster because our target library - // was loaded via dlopen and there cannot have deconstructors + // was loaded via dlopen and therefore cannot have deconstructors // registered. _exit(0); diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 4b9999a6..2d1b427c 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -717,7 +717,7 @@ int main(int argc, char **argv, char **envp) { if (instrument_mode == INSTRUMENT_LTO) FATAL( "instrumentation mode LTO specified but LLVM support not available " - "(requires LLVM 11)"); + "(requires LLVM 11 or higher)"); #endif if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC && -- cgit 1.4.1