mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-13 18:48:08 +00:00
first batch of changes
This commit is contained in:
@ -26,10 +26,10 @@ BIN_PATH ?= $(PREFIX)/bin
|
|||||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||||
MAN_PATH ?= $(PREFIX)/share/man/man8
|
MAN_PATH ?= $(PREFIX)/share/man/man8
|
||||||
|
|
||||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
|
||||||
|
|
||||||
CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
||||||
CFLAGS_SAFE := -Wall -I../include -Wno-pointer-sign \
|
CFLAGS_SAFE := -Wall -Iinclude -Wno-pointer-sign \
|
||||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||||
-DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
|
-DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
|
||||||
-Wno-unused-function
|
-Wno-unused-function
|
||||||
@ -80,25 +80,22 @@ ifeq "$(shell uname -s)" "SunOS"
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
PROGS = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
|
PROGS = ./afl-gcc-pass.so
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: test_shm test_deps $(PROGS) test_build all_done
|
||||||
|
|
||||||
all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
|
.PHONY: test_shm
|
||||||
|
|
||||||
ifeq "$(SHMAT_OK)" "1"
|
ifeq "$(SHMAT_OK)" "1"
|
||||||
|
|
||||||
test_shm:
|
test_shm:
|
||||||
@echo "[+] shmat seems to be working."
|
@echo "[+] shmat seems to be working."
|
||||||
@rm -f .test2
|
@rm -f .test2
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
test_shm:
|
test_shm:
|
||||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
.PHONY: test_deps
|
||||||
test_deps:
|
test_deps:
|
||||||
@echo "[*] Checking for working '$(CC)'..."
|
@echo "[*] Checking for working '$(CC)'..."
|
||||||
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||||
@ -106,65 +103,65 @@ test_deps:
|
|||||||
# @$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
|
# @$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
|
||||||
@echo "[*] Checking for gcc plugin development header files..."
|
@echo "[*] Checking for gcc plugin development header files..."
|
||||||
@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
|
@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
|
||||||
@echo "[*] Checking for '../afl-showmap'..."
|
@echo "[*] Checking for './afl-showmap'..."
|
||||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
@test -f ./afl-showmap || ( echo "[-] Oops, can't find './afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||||
@echo "[+] All set and ready to build."
|
@echo "[+] All set and ready to build."
|
||||||
|
|
||||||
afl-common.o: ../src/afl-common.c
|
afl-common.o: ./src/afl-common.c
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
../afl-gcc-fast: afl-gcc-fast.c afl-common.o | test_deps
|
./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps
|
||||||
$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $(CPPFLAGS) $< afl-common.o -o $@ $(LDFLAGS)
|
|
||||||
ln -sf afl-gcc-fast ../afl-g++-fast
|
|
||||||
|
|
||||||
../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps
|
|
||||||
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
|
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
|
||||||
|
ln -sf afl-cc afl-gcc-fast
|
||||||
|
ln -sf afl-cc afl-g++-fast
|
||||||
|
ln -sf afl-cc.8 afl-gcc-fast.8
|
||||||
|
ln -sf afl-cc.8 afl-g++-fast.8
|
||||||
|
|
||||||
../afl-gcc-rt.o: afl-gcc-rt.o.c | test_deps
|
.PHONY: test_build
|
||||||
$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -fPIC -c $< -o $@
|
|
||||||
|
|
||||||
test_build: $(PROGS)
|
test_build: $(PROGS)
|
||||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||||
unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
|
unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||||
# unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-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
|
||||||
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
|
||||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr
|
|
||||||
@rm -f test-instr
|
@rm -f test-instr
|
||||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||||
@echo "[+] All right, the instrumentation seems to be working!"
|
@echo "[+] All right, the instrumentation seems to be working!"
|
||||||
|
|
||||||
|
.PHONY: all_done
|
||||||
all_done: test_build
|
all_done: test_build
|
||||||
@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
|
@echo "[+] All done! You can now use './afl-gcc-fast' to compile programs."
|
||||||
|
|
||||||
.NOTPARALLEL: clean
|
.NOTPARALLEL: clean
|
||||||
|
|
||||||
vpath % ..
|
vpath % ..
|
||||||
%.8: %
|
%.8: %
|
||||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
|
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ./$@
|
||||||
@echo .SH NAME >> ../$@
|
@echo .SH NAME >> ./$@
|
||||||
@echo .B $* >> ../$@
|
@echo .B $* >> ./$@
|
||||||
@echo >> ../$@
|
@echo >> ./$@
|
||||||
@echo .SH SYNOPSIS >> ../$@
|
@echo .SH SYNOPSIS >> ./$@
|
||||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ./$@
|
||||||
@echo >> ../$@
|
@echo >> ./$@
|
||||||
@echo .SH OPTIONS >> ../$@
|
@echo .SH OPTIONS >> ./$@
|
||||||
@echo .nf >> ../$@
|
@echo .nf >> ./$@
|
||||||
@../$* -h 2>&1 | tail -n +4 >> ../$@
|
@./$* -h 2>&1 | tail -n +4 >> ./$@
|
||||||
@echo >> ../$@
|
@echo >> ./$@
|
||||||
@echo .SH AUTHOR >> ../$@
|
@echo .SH AUTHOR >> ./$@
|
||||||
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
|
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ./$@
|
||||||
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
|
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
|
||||||
@echo >> ../$@
|
@echo >> ./$@
|
||||||
@echo .SH LICENSE >> ../$@
|
@echo .SH LICENSE >> ./$@
|
||||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
@echo Apache License Version 2.0, January 2004 >> ./$@
|
||||||
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
|
ln -sf afl-cc.8 ./afl-g++-fast.8
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
install: all
|
install: all
|
||||||
install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
|
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc-fast
|
||||||
install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
|
ln -sf afl-c++ $${DESTDIR}$(BIN_PATH)/afl-g++-fast
|
||||||
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
install -m 755 ./afl-gcc-pass.so $${DESTDIR}$(HELPER_PATH)
|
||||||
install -m 644 -T README.instrument_list.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md
|
install -m 644 -T instrumentation/README.gcc_plugin.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
||||||
rm -f $(PROGS) afl-common.o ../afl-g++-fast ../afl-g*-fast.8
|
rm -f $(PROGS) afl-common.o ./afl-g++-fast ./afl-g*-fast.8 instrumentation/*.o
|
@ -26,10 +26,10 @@ DOC_PATH ?= $(PREFIX)/share/doc/afl
|
|||||||
MISC_PATH ?= $(PREFIX)/share/afl
|
MISC_PATH ?= $(PREFIX)/share/afl
|
||||||
MAN_PATH ?= $(PREFIX)/share/man/man8
|
MAN_PATH ?= $(PREFIX)/share/man/man8
|
||||||
|
|
||||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
|
||||||
|
|
||||||
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
|
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
|
||||||
|
|
||||||
|
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
|
||||||
|
|
||||||
ifeq "$(shell uname)" "OpenBSD"
|
ifeq "$(shell uname)" "OpenBSD"
|
||||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||||
@ -41,6 +41,7 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' )
|
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' )
|
||||||
|
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
||||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^19' && echo 1 || echo 0 )
|
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^19' && echo 1 || echo 0 )
|
||||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-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_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]' && echo 1 || echo 0 )
|
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]' && echo 1 || echo 0 )
|
||||||
@ -78,13 +79,13 @@ ifeq "$(LLVM_TOO_OLD)" "1"
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(LLVM_HAVE_LTO)" "1"
|
ifeq "$(LLVM_HAVE_LTO)" "1"
|
||||||
$(info [+] llvm_mode detected llvm 11+, enabling afl-clang-lto LTO implementation)
|
$(info [+] llvm_mode detected llvm 11+, enabling afl-lto LTO implementation)
|
||||||
LLVM_LTO = 1
|
LLVM_LTO = 1
|
||||||
#TEST_MMAP = 1
|
#TEST_MMAP = 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(LLVM_LTO)" "0"
|
ifeq "$(LLVM_LTO)" "0"
|
||||||
$(info [+] llvm_mode detected llvm < 11, afl-clang-lto LTO will not be build.)
|
$(info [+] llvm_mode detected llvm < 11, afl-lto LTO will not be build.)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||||
@ -224,7 +225,7 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
|
CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
|
||||||
CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \
|
CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ./include/ -I ./instrumentation/ \
|
||||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||||
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
|
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
|
||||||
-DLLVM_LIBDIR=\"$(LLVM_LIBDIR)\" -DLLVM_VERSION=\"$(LLVMVER)\" \
|
-DLLVM_LIBDIR=\"$(LLVM_LIBDIR)\" -DLLVM_VERSION=\"$(LLVMVER)\" \
|
||||||
@ -241,7 +242,7 @@ ifdef AFL_TRACE_PC
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CXXFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
|
CXXFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
|
||||||
override CXXFLAGS += -Wall -g -I ../include/ \
|
override CXXFLAGS += -Wall -g -I ./include/ \
|
||||||
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros
|
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros
|
||||||
|
|
||||||
ifneq "$(shell $(LLVM_CONFIG) --includedir) 2> /dev/null" ""
|
ifneq "$(shell $(LLVM_CONFIG) --includedir) 2> /dev/null" ""
|
||||||
@ -283,7 +284,8 @@ ifeq "$(TEST_MMAP)" "1"
|
|||||||
LDFLAGS += -Wno-deprecated-declarations
|
LDFLAGS += -Wno-deprecated-declarations
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-ld-lto ../afl-llvm-lto-instrumentlist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so ../SanitizerCoverageLTO.so
|
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
|
||||||
|
PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./libLLVMInsTrim.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so
|
||||||
|
|
||||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||||
ifeq "$(LLVMVER)" ""
|
ifeq "$(LLVMVER)" ""
|
||||||
@ -295,31 +297,31 @@ ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE_XCODE)" "00"
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(NO_BUILD)" "1"
|
ifeq "$(NO_BUILD)" "1"
|
||||||
TARGETS = no_build
|
TARGETS = test_shm $(PROGS_ALWAYS) afl-cc.8
|
||||||
else
|
else
|
||||||
TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
|
TARGETS = test_shm test_deps $(PROGS) afl-cc.8 test_build all_done
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LLVM_MIN_4_0_1 = $(shell awk 'function tonum(ver, a) {split(ver,a,"."); return a[1]*1000000+a[2]*1000+a[3]} BEGIN { exit tonum(ARGV[1]) >= tonum(ARGV[2]) }' $(LLVMVER) 4.0.1; echo $$?)
|
LLVM_MIN_4_0_1 = $(shell awk 'function tonum(ver, a) {split(ver,a,"."); return a[1]*1000000+a[2]*1000+a[3]} BEGIN { exit tonum(ARGV[1]) >= tonum(ARGV[2]) }' $(LLVMVER) 4.0.1; echo $$?)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
.PHONY: test_shm
|
||||||
ifeq "$(SHMAT_OK)" "1"
|
ifeq "$(SHMAT_OK)" "1"
|
||||||
|
|
||||||
test_shm:
|
test_shm:
|
||||||
@echo "[+] shmat seems to be working."
|
@echo "[+] shmat seems to be working."
|
||||||
@rm -f .test2
|
@rm -f .test2
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
test_shm:
|
test_shm:
|
||||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
.PHONY: no_build
|
||||||
no_build:
|
no_build:
|
||||||
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
|
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
|
||||||
|
|
||||||
|
.PHONY: test_deps
|
||||||
test_deps:
|
test_deps:
|
||||||
@echo "[*] Checking for working 'llvm-config'..."
|
@echo "[*] Checking for working 'llvm-config'..."
|
||||||
ifneq "$(LLVM_APPLE_XCODE)" "1"
|
ifneq "$(LLVM_APPLE_XCODE)" "1"
|
||||||
@ -333,148 +335,165 @@ ifneq "$(CLANGVER)" "$(LLVMVER)"
|
|||||||
else
|
else
|
||||||
@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
|
@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
|
||||||
endif
|
endif
|
||||||
@echo "[*] Checking for '../afl-showmap'..."
|
@echo "[*] Checking for './afl-showmap'..."
|
||||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
@test -f ./afl-showmap || ( echo "[-] Oops, can't find './afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||||
@echo "[+] All set and ready to build."
|
@echo "[+] All set and ready to build."
|
||||||
|
|
||||||
afl-common.o: ../src/afl-common.c
|
instrumentation/afl-common.o: ./src/afl-common.c
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps
|
./afl-cc: src/afl-cc.c instrumentation/afl-common.o | test_deps
|
||||||
$(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
|
$(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< instrumentation/afl-common.o -o $@ -DLLVM_MAJOR=$(LLVM_MAJOR) $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
|
||||||
ln -sf afl-clang-fast ../afl-clang-fast++
|
@ln -sf afl-cc ./afl-c++
|
||||||
|
@ln -sf afl-cc ./afl-gcc
|
||||||
|
@ln -sf afl-cc ./afl-g++
|
||||||
|
@ln -sf afl-cc ./afl-clang-fast
|
||||||
|
@ln -sf afl-cc ./afl-clang-fast++
|
||||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
ifeq "$(LLVM_LTO)" "1"
|
||||||
ln -sf afl-clang-fast ../afl-clang-lto
|
@ln -sf afl-cc ./afl-clang-lto
|
||||||
ln -sf afl-clang-fast ../afl-clang-lto++
|
@ln -sf afl-cc ./afl-clang-lto++
|
||||||
|
@ln -sf afl-cc ./afl-lto
|
||||||
|
@ln -sf afl-cc ./afl-lto++
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
afl-llvm-common.o: afl-llvm-common.cc afl-llvm-common.h
|
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
|
||||||
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
||||||
|
|
||||||
../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc afl-llvm-common.o | test_deps
|
./libLLVMInsTrim.so: instrumentation/LLVMInsTrim.so.cc instrumentation/MarkNodes.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
-$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) afl-llvm-common.o
|
-$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< instrumentation/MarkNodes.cc -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
|
|
||||||
../afl-llvm-pass.so: afl-llvm-pass.so.cc afl-llvm-common.o | test_deps
|
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
ifeq "$(LLVM_MIN_4_0_1)" "0"
|
ifeq "$(LLVM_MIN_4_0_1)" "0"
|
||||||
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
|
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
|
||||||
endif
|
endif
|
||||||
$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
|
|
||||||
../afl-llvm-lto-instrumentlist.so: afl-llvm-lto-instrumentlist.so.cc afl-llvm-common.o
|
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
ifeq "$(LLVM_LTO)" "1"
|
||||||
$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
../afl-ld-lto: afl-ld-lto.c
|
./afl-ld-lto: src/afl-ld-lto.c
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
ifeq "$(LLVM_LTO)" "1"
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
../SanitizerCoverageLTO.so: SanitizerCoverageLTO.so.cc
|
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
ifeq "$(LLVM_LTO)" "1"
|
||||||
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc afl-llvm-common.o
|
./afl-llvm-lto-instrumentation.so: instrumentation/afl-llvm-lto-instrumentation.so.cc instrumentation/afl-llvm-common.o
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
ifeq "$(LLVM_LTO)" "1"
|
||||||
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o
|
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto.o
|
||||||
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -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_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
|
||||||
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -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_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# laf
|
# laf
|
||||||
../split-switches-pass.so: split-switches-pass.so.cc afl-llvm-common.o | test_deps
|
./split-switches-pass.so: instrumentation/split-switches-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
../compare-transform-pass.so: compare-transform-pass.so.cc afl-llvm-common.o | test_deps
|
./compare-transform-pass.so: instrumentation/compare-transform-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
../split-compares-pass.so: split-compares-pass.so.cc afl-llvm-common.o | test_deps
|
./split-compares-pass.so: instrumentation/split-compares-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
# /laf
|
# /laf
|
||||||
|
|
||||||
../cmplog-routines-pass.so: cmplog-routines-pass.cc afl-llvm-common.o | test_deps
|
./cmplog-routines-pass.so: instrumentation/cmplog-routines-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
|
|
||||||
../cmplog-instructions-pass.so: cmplog-instructions-pass.cc afl-llvm-common.o | test_deps
|
./cmplog-instructions-pass.so: instrumentation/cmplog-instructions-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
|
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
|
|
||||||
|
afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
|
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||||
|
|
||||||
|
.PHONY: document
|
||||||
document:
|
document:
|
||||||
$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o
|
$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt.o
|
||||||
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||||
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||||
|
|
||||||
../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
|
./afl-compiler-rt.o: instrumentation/afl-compiler-rt.o.c | test_deps
|
||||||
$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
|
$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
|
||||||
|
ln -sf ./afl-compiler-rt.o ./afl-llvm-rt.o
|
||||||
|
|
||||||
../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
|
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c | test_deps
|
||||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
||||||
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||||
|
@test -e ./afl-compiler-rt-32.o && ln -sf ./afl-compiler-rt-32.o ./afl-llvm-rt-32.o
|
||||||
|
|
||||||
../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps
|
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c | test_deps
|
||||||
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
||||||
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||||
|
@test -e ./afl-compiler-rt-64.o && ln -sf ./afl-compiler-rt-64.o ./afl-llvm-rt-64.o
|
||||||
|
|
||||||
|
.PHONY: test_build
|
||||||
test_build: $(PROGS)
|
test_build: $(PROGS)
|
||||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||||
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)
|
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||||
ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
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
|
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||||
@rm -f test-instr
|
@rm -f test-instr
|
||||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||||
@echo "[+] All right, the instrumentation seems to be working!"
|
@echo "[+] All right, the instrumentation seems to be working!"
|
||||||
|
|
||||||
|
.PHONY: all_done
|
||||||
all_done: test_build
|
all_done: test_build
|
||||||
@echo "[+] All done! You can now use '../afl-clang-fast' to compile programs."
|
@echo "[+] All done! You can now use './afl-cc' to compile programs."
|
||||||
|
|
||||||
.NOTPARALLEL: clean
|
.NOTPARALLEL: clean
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
install: all
|
install: all
|
||||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||||
if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi
|
||||||
if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-rt-lto*.o ../afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||||
if [ -f ../afl-ld-lto ]; then set -e; install -m 755 ../afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
|
@if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-lto-instrumentation.so ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
|
||||||
if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
|
||||||
if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o; fi
|
||||||
if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o; fi
|
||||||
if [ -f ../split-compares-pass.so ]; then set -e; install -m 755 ../split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi
|
||||||
if [ -f ../split-switches-pass.so ]; then set -e; install -m 755 ../split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi
|
||||||
if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi
|
||||||
if [ -f ../SanitizerCoverageLTO.so ]; then set -e; install -m 755 ../SanitizerCoverageLTO.so $${DESTDIR}$(HELPER_PATH); fi
|
set -e; install -m 644 ./dynamic_list.txt $${DESTDIR}$(HELPER_PATH)
|
||||||
set -e; install -m 644 ../dynamic_list.txt $${DESTDIR}$(HELPER_PATH)
|
install -m 644 instrumentation/README.*.md $${DESTDIR}$(DOC_PATH)/
|
||||||
set -e; if [ -f ../afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
|
|
||||||
install -m 644 README.*.md $${DESTDIR}$(DOC_PATH)/
|
|
||||||
install -m 644 README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md
|
|
||||||
|
|
||||||
vpath % ..
|
vpath % ..
|
||||||
%.8: %
|
%.8: %
|
||||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > ../$@
|
@echo .TH $* 8 $(BUILD_DATE) "afl++" > ./$@
|
||||||
@echo .SH NAME >> ../$@
|
@echo .SH NAME >> ./$@
|
||||||
@echo -n ".B $* \- " >> ../$@
|
@printf ".B $* \- " >> ../$@
|
||||||
@../$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ../$@
|
@./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ../$@
|
||||||
@echo >> ../$@
|
@echo .B $* >> ./$@
|
||||||
@echo .SH SYNOPSIS >> ../$@
|
@echo >> ./$@
|
||||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
@echo .SH SYNOPSIS >> ./$@
|
||||||
@echo >> ../$@
|
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ./$@
|
||||||
@echo .SH OPTIONS >> ../$@
|
@echo >> ./$@
|
||||||
@echo .nf >> ../$@
|
@echo .SH OPTIONS >> ./$@
|
||||||
@../$* -h 2>&1 | tail -n +4 >> ../$@
|
@echo .nf >> ./$@
|
||||||
@echo >> ../$@
|
@./$* -h 2>&1 | tail -n +4 >> ./$@
|
||||||
@echo .SH AUTHOR >> ../$@
|
@echo >> ./$@
|
||||||
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
|
@echo .SH AUTHOR >> ./$@
|
||||||
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
|
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ./$@
|
||||||
@echo >> ../$@
|
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
|
||||||
@echo .SH LICENSE >> ../$@
|
@echo >> ./$@
|
||||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
@echo .SH LICENSE >> ./$@
|
||||||
ln -sf afl-clang-fast.8 ../afl-clang-fast++.8
|
@echo Apache License Version 2.0, January 2004 >> ./$@
|
||||||
|
@ln -sf afl-cc.8 ./afl-c++.8
|
||||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
ifeq "$(LLVM_LTO)" "1"
|
||||||
ln -sf afl-clang-fast.8 ../afl-clang-lto.8
|
@ln -sf afl-cc.8 ./afl-clang-lto.8
|
||||||
ln -sf afl-clang-fast.8 ../afl-clang-lto++.8
|
@ln -sf afl-cc.8 ./afl-clang-lto++.8
|
||||||
|
@ln -sf afl-cc.8 ./afl-lto.8
|
||||||
|
@ln -sf afl-cc.8 ./afl-lto++.8
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
|
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
|
||||||
rm -f $(PROGS) afl-common.o ../afl-clang-fast++ ../afl-clang-lto ../afl-clang-lto++ ../afl-clang*.8 ../ld ../afl-ld ../afl-llvm-rt*.o
|
rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-llvm-rt*.o instrumentation/*.o
|
@ -1,159 +0,0 @@
|
|||||||
#
|
|
||||||
# american fuzzy lop++ - GCC plugin instrumentation
|
|
||||||
# -----------------------------------------------
|
|
||||||
#
|
|
||||||
# Written by Austin Seipp <aseipp@pobox.com> and
|
|
||||||
# Laszlo Szekeres <lszekeres@google.com> and
|
|
||||||
# Michal Zalewski and
|
|
||||||
# Heiko Eißfeldt <heiko@hexco.de>
|
|
||||||
#
|
|
||||||
# GCC integration design is based on the LLVM design, which comes
|
|
||||||
# from Laszlo Szekeres.
|
|
||||||
#
|
|
||||||
# Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at:
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
HELPER_PATH ?= $(PREFIX)/lib/afl
|
|
||||||
BIN_PATH ?= $(PREFIX)/bin
|
|
||||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
|
||||||
MAN_PATH ?= $(PREFIX)/share/man/man8
|
|
||||||
|
|
||||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
|
||||||
VERSION:sh= grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2
|
|
||||||
|
|
||||||
CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
|
||||||
CFLAGS = -Wall -I../include -Wno-pointer-sign \
|
|
||||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
|
||||||
-DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
|
|
||||||
-Wno-unused-function
|
|
||||||
|
|
||||||
CXXFLAGS = -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
|
||||||
CXXEFLAGS = $(CXXFLAGS) -Wall
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
CXX = g++
|
|
||||||
|
|
||||||
MYCC=$(CC:clang=gcc)
|
|
||||||
MYCXX=$(CXX:clang++=g++)
|
|
||||||
|
|
||||||
PLUGIN_PATH = $(shell $(MYCC) -print-file-name=plugin)
|
|
||||||
PLUGIN_PATH:sh= $(MYCC) -print-file-name=plugin
|
|
||||||
PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(PLUGIN_PATH)/include"
|
|
||||||
HASH=\#
|
|
||||||
|
|
||||||
GCCVER = $(shell $(MYCC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
|
|
||||||
GCCVER:sh= gcc --version 2>/dev/null | awk 'NR == 1 {print $$NF}'
|
|
||||||
GCCBINDIR = $(shell dirname `command -v $(MYCC)` 2>/dev/null )
|
|
||||||
GCCBINDIR:sh= dirname `command -v $(MYCC)` 2>/dev/null
|
|
||||||
|
|
||||||
_SHMAT_OK= $(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(MYCC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )
|
|
||||||
_SHMAT_OK:sh= echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(MYCC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2
|
|
||||||
|
|
||||||
IGNORE_MMAP=$(TEST_MMAP:1=0)
|
|
||||||
__SHMAT_OK=$(_SHMAT_OK)$(IGNORE_MMAP)
|
|
||||||
___SHMAT_OK=$(__SHMAT_OK:10=0)
|
|
||||||
SHMAT_OK=$(___SHMAT_OK:1=1)
|
|
||||||
_CFLAGS_ADD=$(SHMAT_OK:1=)
|
|
||||||
CFLAGS_ADD=$(_CFLAGS_ADD:0=-DUSEMMAP=1)
|
|
||||||
|
|
||||||
_LDFLAGS_ADD=$(SHMAT_OK:1=)
|
|
||||||
LDFLAGS_ADD=$(_LDFLAGS_ADD:0=-lrt)
|
|
||||||
|
|
||||||
CFLAGS += $(CFLAGS_ADD)
|
|
||||||
LDFLAGS += $(LDFLAGS_ADD)
|
|
||||||
|
|
||||||
PROGS = ../afl-gcc-pass.so ../afl-gcc-fast ../afl-gcc-rt.o
|
|
||||||
|
|
||||||
all: test_shm test_deps $(PROGS) ../afl-gcc-fast.8 test_build all_done
|
|
||||||
|
|
||||||
debug:
|
|
||||||
@echo _SHMAT_OK = $(_SHMAT_OK)
|
|
||||||
@echo IGNORE_MMAP = $(IGNORE_MMAP)
|
|
||||||
@echo __SHMAT_OK = $(__SHMAT_OK)
|
|
||||||
@echo ___SHMAT_OK = $(___SHMAT_OK)
|
|
||||||
@echo SHMAT_OK = $(SHMAT_OK)
|
|
||||||
|
|
||||||
test_shm:
|
|
||||||
@if [ "$(SHMAT_OK)" == "1" ]; then \
|
|
||||||
echo "[+] shmat seems to be working."; \
|
|
||||||
rm -f .test2; \
|
|
||||||
else \
|
|
||||||
echo "[-] shmat seems not to be working, switching to mmap implementation"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
test_deps:
|
|
||||||
@echo "[*] Checking for working '$(MYCC)'..."
|
|
||||||
@type $(MYCC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(MYCC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
|
||||||
# @echo "[*] Checking for gcc for plugin support..."
|
|
||||||
# @$(MYCC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
|
|
||||||
@echo "[*] Checking for gcc plugin development header files..."
|
|
||||||
@test -d `$(MYCC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
|
|
||||||
@echo "[*] Checking for '../afl-showmap'..."
|
|
||||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
|
||||||
@echo "[+] All set and ready to build."
|
|
||||||
|
|
||||||
afl-common.o: ../src/afl-common.c
|
|
||||||
$(MYCC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
|
|
||||||
|
|
||||||
../afl-gcc-fast: afl-gcc-fast.c afl-common.o
|
|
||||||
$(MYCC) -DAFL_GCC_CC=\"$(MYCC)\" -DAFL_GCC_CXX=\"$(MYCXX)\" $(CFLAGS) afl-gcc-fast.c afl-common.o -o $@ $(LDFLAGS)
|
|
||||||
ln -sf afl-gcc-fast ../afl-g++-fast
|
|
||||||
|
|
||||||
../afl-gcc-pass.so: afl-gcc-pass.so.cc
|
|
||||||
$(MYCXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared afl-gcc-pass.so.cc -o $@
|
|
||||||
|
|
||||||
../afl-gcc-rt.o: afl-gcc-rt.o.c
|
|
||||||
$(MYCC) $(CFLAGS) -fPIC -c afl-gcc-rt.o.c -o $@
|
|
||||||
|
|
||||||
test_build: $(PROGS)
|
|
||||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
|
||||||
@unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
|
|
||||||
# unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-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
|
|
||||||
@ASAN_OPTIONS=detect_leaks=0 echo 1 | ../afl-showmap -m none -q -o .test-instr1 ./test-instr
|
|
||||||
@rm -f test-instr
|
|
||||||
@trap 'rm .test-instr0 .test-instr1' 0;if cmp -s .test-instr0 .test-instr1; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
|
||||||
@echo "[+] All right, the instrumentation seems to be working!"
|
|
||||||
|
|
||||||
all_done: test_build
|
|
||||||
@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
|
|
||||||
|
|
||||||
.NOTPARALLEL: clean
|
|
||||||
|
|
||||||
../afl-gcc-fast.8: ../afl-gcc-fast
|
|
||||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
|
|
||||||
@echo .SH NAME >> ../$@
|
|
||||||
@echo .B $* >> ../$@
|
|
||||||
@echo >> ../$@
|
|
||||||
@echo .SH SYNOPSIS >> ../$@
|
|
||||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
|
||||||
@echo >> ../$@
|
|
||||||
@echo .SH OPTIONS >> ../$@
|
|
||||||
@echo .nf >> ../$@
|
|
||||||
@../$* -h 2>&1 | tail -n +4 >> ../$@
|
|
||||||
@echo >> ../$@
|
|
||||||
@echo .SH AUTHOR >> ../$@
|
|
||||||
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
|
|
||||||
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
|
|
||||||
@echo >> ../$@
|
|
||||||
@echo .SH LICENSE >> ../$@
|
|
||||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
|
||||||
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
|
|
||||||
|
|
||||||
install: all
|
|
||||||
install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
|
|
||||||
install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
|
|
||||||
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
|
||||||
install -m 644 -T README.instrument_list.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
|
||||||
rm -f $(PROGS) afl-common.o ../afl-g++-fast ../afl-g*-fast.8
|
|
@ -1,73 +0,0 @@
|
|||||||
========================================
|
|
||||||
Using afl++ with partial instrumentation
|
|
||||||
========================================
|
|
||||||
|
|
||||||
This file describes how you can selectively instrument only the source files
|
|
||||||
that are interesting to you using the gcc instrumentation provided by
|
|
||||||
afl++.
|
|
||||||
|
|
||||||
Plugin by hexcoder-.
|
|
||||||
|
|
||||||
|
|
||||||
## 1) Description and purpose
|
|
||||||
|
|
||||||
When building and testing complex programs where only a part of the program is
|
|
||||||
the fuzzing target, it often helps to only instrument the necessary parts of
|
|
||||||
the program, leaving the rest uninstrumented. This helps to focus the fuzzer
|
|
||||||
on the important parts of the program, avoiding undesired noise and
|
|
||||||
disturbance by uninteresting code being exercised.
|
|
||||||
|
|
||||||
For this purpose, I have added a "partial instrumentation" support to the gcc
|
|
||||||
plugin of AFLFuzz that allows you to specify on a source file level which files
|
|
||||||
should be compiled with or without instrumentation.
|
|
||||||
|
|
||||||
|
|
||||||
## 2) Building the gcc plugin
|
|
||||||
|
|
||||||
The new code is part of the existing afl++ gcc plugin in the gcc_plugin/
|
|
||||||
subdirectory. There is nothing specifically to do :)
|
|
||||||
|
|
||||||
|
|
||||||
## 3) How to use the partial instrumentation mode
|
|
||||||
|
|
||||||
In order to build with partial instrumentation, you need to build with
|
|
||||||
afl-gcc-fast and afl-g++-fast respectively. The only required change is
|
|
||||||
that you need to set the environment variable AFL_GCC_INSTRUMENT_FILE when calling
|
|
||||||
the compiler.
|
|
||||||
|
|
||||||
The environment variable must point to a file containing all the filenames
|
|
||||||
that should be instrumented. For matching, the filename that is being compiled
|
|
||||||
must end in the filename entry contained in this instrument list (to avoid breaking
|
|
||||||
the matching when absolute paths are used during compilation).
|
|
||||||
|
|
||||||
For example if your source tree looks like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
project/
|
|
||||||
project/feature_a/a1.cpp
|
|
||||||
project/feature_a/a2.cpp
|
|
||||||
project/feature_b/b1.cpp
|
|
||||||
project/feature_b/b2.cpp
|
|
||||||
```
|
|
||||||
|
|
||||||
and you only want to test feature_a, then create a instrument list file containing:
|
|
||||||
|
|
||||||
```
|
|
||||||
feature_a/a1.cpp
|
|
||||||
feature_a/a2.cpp
|
|
||||||
```
|
|
||||||
|
|
||||||
However if the instrument list file contains only this, it works as well:
|
|
||||||
|
|
||||||
```
|
|
||||||
a1.cpp
|
|
||||||
a2.cpp
|
|
||||||
```
|
|
||||||
|
|
||||||
but it might lead to files being unwantedly instrumented if the same filename
|
|
||||||
exists somewhere else in the project directories.
|
|
||||||
|
|
||||||
The created instrument list file is then set to AFL_GCC_INSTRUMENT_FILE when you compile
|
|
||||||
your program. For each file that didn't match the instrument list, the compiler will
|
|
||||||
issue a warning at the end stating that no blocks were instrumented. If you
|
|
||||||
didn't intend to instrument that file, then you can safely ignore that warning.
|
|
@ -1,406 +0,0 @@
|
|||||||
/*
|
|
||||||
american fuzzy lop++ - GCC wrapper for GCC plugin
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
Written by Austin Seipp <aseipp@pobox.com> and
|
|
||||||
Laszlo Szekeres <lszekeres@google.com> and
|
|
||||||
Michal Zalewski
|
|
||||||
|
|
||||||
GCC integration design is based on the LLVM design, which comes
|
|
||||||
from Laszlo Szekeres.
|
|
||||||
|
|
||||||
Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at:
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
This program is a drop-in replacement for gcc, similar in most
|
|
||||||
respects to ../afl-gcc, but with compiler instrumentation through a
|
|
||||||
plugin. It tries to figure out compilation mode, adds a bunch of
|
|
||||||
flags, and then calls the real compiler.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define AFL_MAIN
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "alloc-inl.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
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 */
|
|
||||||
u8 use_stdin = 0; /* dummy */
|
|
||||||
|
|
||||||
/* Try to find the runtime libraries. If that fails, abort. */
|
|
||||||
|
|
||||||
static void find_obj(u8 *argv0) {
|
|
||||||
|
|
||||||
u8 *afl_path = getenv("AFL_PATH");
|
|
||||||
u8 *slash, *tmp;
|
|
||||||
|
|
||||||
if (afl_path) {
|
|
||||||
|
|
||||||
tmp = alloc_printf("%s/afl-gcc-rt.o", afl_path);
|
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) {
|
|
||||||
|
|
||||||
obj_path = afl_path;
|
|
||||||
ck_free(tmp);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
slash = strrchr(argv0, '/');
|
|
||||||
|
|
||||||
if (slash) {
|
|
||||||
|
|
||||||
u8 *dir;
|
|
||||||
|
|
||||||
*slash = 0;
|
|
||||||
dir = ck_strdup(argv0);
|
|
||||||
*slash = '/';
|
|
||||||
|
|
||||||
tmp = alloc_printf("%s/afl-gcc-rt.o", dir);
|
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) {
|
|
||||||
|
|
||||||
obj_path = dir;
|
|
||||||
ck_free(tmp);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
ck_free(dir);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!access(AFL_PATH "/afl-gcc-rt.o", R_OK)) {
|
|
||||||
|
|
||||||
obj_path = AFL_PATH;
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
FATAL(
|
|
||||||
"Unable to find 'afl-gcc-rt.o' or 'afl-gcc-pass.so'. Please set "
|
|
||||||
"AFL_PATH");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy argv to cc_params, making the necessary edits. */
|
|
||||||
|
|
||||||
static void edit_params(u32 argc, char **argv) {
|
|
||||||
|
|
||||||
u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1;
|
|
||||||
u8 *name;
|
|
||||||
|
|
||||||
cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
|
|
||||||
|
|
||||||
name = strrchr(argv[0], '/');
|
|
||||||
if (!name)
|
|
||||||
name = argv[0];
|
|
||||||
else
|
|
||||||
++name;
|
|
||||||
|
|
||||||
if (!strcmp(name, "afl-g++-fast")) {
|
|
||||||
|
|
||||||
u8 *alt_cxx = getenv("AFL_CXX");
|
|
||||||
cc_params[0] = alt_cxx && *alt_cxx ? alt_cxx : (u8 *)AFL_GCC_CXX;
|
|
||||||
|
|
||||||
} else if (!strcmp(name, "afl-gcc-fast")) {
|
|
||||||
|
|
||||||
u8 *alt_cc = getenv("AFL_CC");
|
|
||||||
cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)AFL_GCC_CC;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
fprintf(stderr, "Name of the binary: %s\n", argv[0]);
|
|
||||||
FATAL(
|
|
||||||
"Name of the binary is not a known name, expected afl-(gcc|g++)-fast");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
|
|
||||||
cc_params[cc_par_cnt++] = fplugin_arg;
|
|
||||||
|
|
||||||
/* Detect stray -v calls from ./configure scripts. */
|
|
||||||
|
|
||||||
if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0;
|
|
||||||
|
|
||||||
while (--argc) {
|
|
||||||
|
|
||||||
u8 *cur = *(++argv);
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
if (!strcmp(cur, "-m32")) FATAL("-m32 is not supported");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-x")) x_set = 1;
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E") ||
|
|
||||||
!strcmp(cur, "-v"))
|
|
||||||
maybe_linking = 0;
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
|
|
||||||
asan_set = 1;
|
|
||||||
|
|
||||||
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-shared")) maybe_linking = 0;
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = cur;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_HARDEN")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fstack-protector-all";
|
|
||||||
|
|
||||||
if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!asan_set) {
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_ASAN")) {
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive");
|
|
||||||
|
|
||||||
if (getenv("AFL_HARDEN"))
|
|
||||||
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize=address";
|
|
||||||
|
|
||||||
} else if (getenv("AFL_USE_MSAN")) {
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive");
|
|
||||||
|
|
||||||
if (getenv("AFL_HARDEN"))
|
|
||||||
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize=memory";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_UBSAN")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize=undefined";
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getenv("AFL_DONT_OPTIMIZE")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-g";
|
|
||||||
cc_params[cc_par_cnt++] = "-O3";
|
|
||||||
cc_params[cc_par_cnt++] = "-funroll-loops";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_NO_BUILTIN")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(USEMMAP) && !defined(__HAIKU__)
|
|
||||||
cc_params[cc_par_cnt++] = "-lrt";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
|
|
||||||
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
|
|
||||||
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
|
|
||||||
|
|
||||||
/* When the user tries to use persistent or deferred forkserver modes by
|
|
||||||
appending a single line to the program, we want to reliably inject a
|
|
||||||
signature into the binary (to be picked up by afl-fuzz) and we want
|
|
||||||
to call a function from the runtime .o file. This is unnecessarily
|
|
||||||
painful for three reasons:
|
|
||||||
|
|
||||||
1) We need to convince the compiler not to optimize out the signature.
|
|
||||||
This is done with __attribute__((used)).
|
|
||||||
|
|
||||||
2) We need to convince the linker, when called with -Wl,--gc-sections,
|
|
||||||
not to do the same. This is done by forcing an assignment to a
|
|
||||||
'volatile' pointer.
|
|
||||||
|
|
||||||
3) We need to declare __afl_persistent_loop() in the global namespace,
|
|
||||||
but doing this within a method in a class is hard - :: and extern "C"
|
|
||||||
are forbidden and __attribute__((alias(...))) doesn't work. Hence the
|
|
||||||
__asm__ aliasing trick.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] =
|
|
||||||
"-D__AFL_LOOP(_A)="
|
|
||||||
"({ static volatile char *_B __attribute__((used)); "
|
|
||||||
" _B = (char*)\"" PERSIST_SIG
|
|
||||||
"\"; "
|
|
||||||
#ifdef __APPLE__
|
|
||||||
"int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
|
|
||||||
#else
|
|
||||||
"int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
|
|
||||||
#endif /* ^__APPLE__ */
|
|
||||||
"_L(_A); })";
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] =
|
|
||||||
"-D__AFL_INIT()="
|
|
||||||
"do { static volatile char *_A __attribute__((used)); "
|
|
||||||
" _A = (char*)\"" DEFER_SIG
|
|
||||||
"\"; "
|
|
||||||
#ifdef __APPLE__
|
|
||||||
"void _I(void) __asm__(\"___afl_manual_init\"); "
|
|
||||||
#else
|
|
||||||
"void _I(void) __asm__(\"__afl_manual_init\"); "
|
|
||||||
#endif /* ^__APPLE__ */
|
|
||||||
"_I(); } while (0)";
|
|
||||||
|
|
||||||
if (maybe_linking) {
|
|
||||||
|
|
||||||
if (x_set) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-x";
|
|
||||||
cc_params[cc_par_cnt++] = "none";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-gcc-rt.o", obj_path);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt] = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main entry point */
|
|
||||||
|
|
||||||
int main(int argc, char **argv, char **envp) {
|
|
||||||
|
|
||||||
if (argc < 2 || strcmp(argv[1], "-h") == 0) {
|
|
||||||
|
|
||||||
printf(cCYA
|
|
||||||
"afl-gcc-fast" VERSION cRST
|
|
||||||
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n"
|
|
||||||
"\n"
|
|
||||||
"afl-gcc-fast [options]\n"
|
|
||||||
"\n"
|
|
||||||
"This is a helper application for afl-fuzz. It serves as a drop-in "
|
|
||||||
"replacement\n"
|
|
||||||
"for gcc, letting you recompile third-party code with the required "
|
|
||||||
"runtime\n"
|
|
||||||
"instrumentation. A common use pattern would be one of the "
|
|
||||||
"following:\n\n"
|
|
||||||
|
|
||||||
" CC=%s/afl-gcc-fast ./configure\n"
|
|
||||||
" CXX=%s/afl-g++-fast ./configure\n\n"
|
|
||||||
|
|
||||||
"In contrast to the traditional afl-gcc tool, this version is "
|
|
||||||
"implemented as\n"
|
|
||||||
"a GCC plugin and tends to offer improved performance with slow "
|
|
||||||
"programs\n"
|
|
||||||
"(similarly to the LLVM plugin used by afl-clang-fast).\n\n"
|
|
||||||
|
|
||||||
"Environment variables used:\n"
|
|
||||||
"AFL_CC: path to the C compiler to use\n"
|
|
||||||
"AFL_CXX: path to the C++ compiler to use\n"
|
|
||||||
"AFL_PATH: path to instrumenting pass and runtime (afl-gcc-rt.*o)\n"
|
|
||||||
"AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
|
|
||||||
"AFL_NO_BUILTIN: compile for use with libtokencap.so\n"
|
|
||||||
"AFL_INST_RATIO: percentage of branches to instrument\n"
|
|
||||||
"AFL_QUIET: suppress verbose output\n"
|
|
||||||
"AFL_DEBUG: enable developer debugging output\n"
|
|
||||||
"AFL_HARDEN: adds code hardening to catch memory bugs\n"
|
|
||||||
"AFL_USE_ASAN: activate address sanitizer\n"
|
|
||||||
"AFL_USE_MSAN: activate memory sanitizer\n"
|
|
||||||
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
|
|
||||||
"AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
|
|
||||||
"filename\n"
|
|
||||||
|
|
||||||
"\nafl-gcc-fast was built for gcc %s with the gcc binary path of "
|
|
||||||
"\"%s\".\n\n",
|
|
||||||
BIN_PATH, BIN_PATH, GCC_VERSION, GCC_BINDIR);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
} else if ((isatty(2) && !getenv("AFL_QUIET")) ||
|
|
||||||
|
|
||||||
getenv("AFL_DEBUG") != NULL) {
|
|
||||||
|
|
||||||
SAYF(cCYA "afl-gcc-fast" VERSION cRST
|
|
||||||
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n");
|
|
||||||
|
|
||||||
if (getenv("AFL_GCC_INSTRUMENT_FILE") == NULL &&
|
|
||||||
getenv("AFL_GCC_WHITELIST") == NULL) {
|
|
||||||
|
|
||||||
SAYF(
|
|
||||||
cYEL
|
|
||||||
"Warning:" cRST
|
|
||||||
" using afl-gcc-fast without using AFL_GCC_INSTRUMENT_FILE currently "
|
|
||||||
"produces worse results than afl-gcc. Even better, use "
|
|
||||||
"llvm_mode for now.\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
|
|
||||||
be_quiet = 1;
|
|
||||||
|
|
||||||
u8 *ptr;
|
|
||||||
if (!be_quiet &&
|
|
||||||
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
|
|
||||||
|
|
||||||
u32 map_size = atoi(ptr);
|
|
||||||
if (map_size != MAP_SIZE)
|
|
||||||
WARNF("AFL_MAP_SIZE is not supported by afl-gcc-fast");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
check_environment_vars(envp);
|
|
||||||
|
|
||||||
find_obj(argv[0]);
|
|
||||||
|
|
||||||
edit_params(argc, argv);
|
|
||||||
/*if (isatty(2) && !getenv("AFL_QUIET")) {
|
|
||||||
|
|
||||||
printf("Calling \"%s\" with:\n", cc_params[0]);
|
|
||||||
for(int i=1; i<cc_par_cnt; i++) printf("%s\n", cc_params[i]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
execvp(cc_params[0], (char **)cc_params);
|
|
||||||
|
|
||||||
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,315 +0,0 @@
|
|||||||
/*
|
|
||||||
american fuzzy lop++ - GCC plugin instrumentation bootstrap
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
Written by Austin Seipp <aseipp@pobox.com> and
|
|
||||||
Laszlo Szekeres <lszekeres@google.com> and
|
|
||||||
Michal Zalewski
|
|
||||||
|
|
||||||
GCC integration design is based on the LLVM design, which comes
|
|
||||||
from Laszlo Szekeres.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at:
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
This code is the rewrite of afl-as.h's main_payload.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
#include "android-ashmem.h"
|
|
||||||
#endif
|
|
||||||
#include "../config.h"
|
|
||||||
#include "../types.h"
|
|
||||||
|
|
||||||
#ifdef USEMMAP
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#ifndef USEMMAP
|
|
||||||
#include <sys/shm.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
/* Globals needed by the injected instrumentation. The __afl_area_initial region
|
|
||||||
is used for instrumentation output before __afl_map_shm() has a chance to
|
|
||||||
run. It will end up as .comm, so it shouldn't be too wasteful. */
|
|
||||||
|
|
||||||
u8 __afl_area_initial[MAP_SIZE];
|
|
||||||
u8 *__afl_area_ptr = __afl_area_initial;
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
u32 __afl_prev_loc;
|
|
||||||
u32 __afl_final_loc;
|
|
||||||
#else
|
|
||||||
__thread u32 __afl_prev_loc;
|
|
||||||
__thread u32 __afl_final_loc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Trace a basic block with some ID */
|
|
||||||
void __afl_trace(const u32 x) {
|
|
||||||
|
|
||||||
#if 1 /* enable for neverZero feature. */
|
|
||||||
__afl_area_ptr[__afl_prev_loc ^ x] +=
|
|
||||||
1 + ((u8)(1 + __afl_area_ptr[__afl_prev_loc ^ x]) == 0);
|
|
||||||
#else
|
|
||||||
++__afl_area_ptr[__afl_prev_loc ^ x];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__afl_prev_loc = (x >> 1);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Running in persistent mode? */
|
|
||||||
|
|
||||||
static u8 is_persistent;
|
|
||||||
|
|
||||||
/* SHM setup. */
|
|
||||||
|
|
||||||
static void __afl_map_shm(void) {
|
|
||||||
|
|
||||||
u8 *id_str = getenv(SHM_ENV_VAR);
|
|
||||||
|
|
||||||
/* If we're running under AFL, attach to the appropriate region, replacing the
|
|
||||||
early-stage __afl_area_initial region that is needed to allow some really
|
|
||||||
hacky .init code to work correctly in projects such as OpenSSL. */
|
|
||||||
|
|
||||||
if (id_str) {
|
|
||||||
|
|
||||||
#ifdef USEMMAP
|
|
||||||
const char * shm_file_path = id_str;
|
|
||||||
int shm_fd = -1;
|
|
||||||
unsigned char *shm_base = NULL;
|
|
||||||
|
|
||||||
/* create the shared memory segment as if it was a file */
|
|
||||||
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
|
|
||||||
if (shm_fd == -1) {
|
|
||||||
|
|
||||||
fprintf(stderr, "shm_open() failed\n");
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* map the shared memory segment to the address space of the process */
|
|
||||||
shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
|
|
||||||
if (shm_base == MAP_FAILED) {
|
|
||||||
|
|
||||||
close(shm_fd);
|
|
||||||
shm_fd = -1;
|
|
||||||
|
|
||||||
fprintf(stderr, "mmap() failed\n");
|
|
||||||
exit(2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__afl_area_ptr = shm_base;
|
|
||||||
#else
|
|
||||||
u32 shm_id = atoi(id_str);
|
|
||||||
|
|
||||||
__afl_area_ptr = shmat(shm_id, NULL, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Whooooops. */
|
|
||||||
|
|
||||||
if (__afl_area_ptr == (void *)-1) exit(1);
|
|
||||||
|
|
||||||
/* Write something into the bitmap so that even with low AFL_INST_RATIO,
|
|
||||||
our parent doesn't give up on us. */
|
|
||||||
|
|
||||||
__afl_area_ptr[0] = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fork server logic. */
|
|
||||||
|
|
||||||
static void __afl_start_forkserver(void) {
|
|
||||||
|
|
||||||
u8 tmp[4] = {0, 0, 0, 0};
|
|
||||||
u32 map_size = MAP_SIZE;
|
|
||||||
s32 child_pid;
|
|
||||||
|
|
||||||
u8 child_stopped = 0;
|
|
||||||
|
|
||||||
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
|
||||||
|
|
||||||
/* Phone home and tell the parent that we're OK. If parent isn't there,
|
|
||||||
assume we're not running in forkserver mode and just execute program. */
|
|
||||||
|
|
||||||
if (MAP_SIZE <= 0x800000) {
|
|
||||||
|
|
||||||
map_size = (FS_OPT_ENABLED | FS_OPT_MAPSIZE | FS_OPT_SET_MAPSIZE(MAP_SIZE));
|
|
||||||
memcpy(tmp, &map_size, 4);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
u32 was_killed;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
/* Wait for parent by reading from the pipe. Abort if read fails. */
|
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(1);
|
|
||||||
|
|
||||||
/* If we stopped the child in persistent mode, but there was a race
|
|
||||||
condition and afl-fuzz already issued SIGKILL, write off the old
|
|
||||||
process. */
|
|
||||||
|
|
||||||
if (child_stopped && was_killed) {
|
|
||||||
|
|
||||||
child_stopped = 0;
|
|
||||||
if (waitpid(child_pid, &status, 0) < 0) exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!child_stopped) {
|
|
||||||
|
|
||||||
/* Once woken up, create a clone of our process. */
|
|
||||||
|
|
||||||
child_pid = fork();
|
|
||||||
if (child_pid < 0) exit(1);
|
|
||||||
|
|
||||||
/* In child process: close fds, resume execution. */
|
|
||||||
|
|
||||||
if (!child_pid) {
|
|
||||||
|
|
||||||
signal(SIGCHLD, old_sigchld_handler);
|
|
||||||
|
|
||||||
close(FORKSRV_FD);
|
|
||||||
close(FORKSRV_FD + 1);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Special handling for persistent mode: if the child is alive but
|
|
||||||
currently stopped, simply restart it with SIGCONT. */
|
|
||||||
|
|
||||||
kill(child_pid, SIGCONT);
|
|
||||||
child_stopped = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In parent process: write PID to pipe, then wait for child. */
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(1);
|
|
||||||
|
|
||||||
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) exit(1);
|
|
||||||
|
|
||||||
/* In persistent mode, the child stops itself with SIGSTOP to indicate
|
|
||||||
a successful run. In this case, we want to wake it up without forking
|
|
||||||
again. */
|
|
||||||
|
|
||||||
if (WIFSTOPPED(status)) child_stopped = 1;
|
|
||||||
|
|
||||||
/* Relay wait status to pipe, then loop back. */
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A simplified persistent mode handler, used as explained in README.md. */
|
|
||||||
|
|
||||||
int __afl_persistent_loop(unsigned int max_cnt) {
|
|
||||||
|
|
||||||
static u8 first_pass = 1;
|
|
||||||
static u32 cycle_cnt;
|
|
||||||
|
|
||||||
if (first_pass) {
|
|
||||||
|
|
||||||
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
|
|
||||||
On subsequent calls, the parent will take care of that, but on the first
|
|
||||||
iteration, it's our job to erase any trace of whatever happened
|
|
||||||
before the loop. */
|
|
||||||
|
|
||||||
if (is_persistent) {
|
|
||||||
|
|
||||||
memset(__afl_area_ptr, 0, MAP_SIZE);
|
|
||||||
__afl_area_ptr[0] = 1;
|
|
||||||
__afl_prev_loc = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cycle_cnt = max_cnt;
|
|
||||||
first_pass = 0;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_persistent) {
|
|
||||||
|
|
||||||
if (--cycle_cnt) {
|
|
||||||
|
|
||||||
raise(SIGSTOP);
|
|
||||||
|
|
||||||
__afl_area_ptr[0] = 1;
|
|
||||||
__afl_prev_loc = 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* When exiting __AFL_LOOP(), make sure that the subsequent code that
|
|
||||||
follows the loop is not traced. We do that by pivoting back to the
|
|
||||||
dummy output region. */
|
|
||||||
|
|
||||||
__afl_area_ptr = __afl_area_initial;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This one can be called from user code when deferred forkserver mode
|
|
||||||
is enabled. */
|
|
||||||
|
|
||||||
void __afl_manual_init(void) {
|
|
||||||
|
|
||||||
static u8 init_done;
|
|
||||||
|
|
||||||
if (!init_done) {
|
|
||||||
|
|
||||||
__afl_map_shm();
|
|
||||||
__afl_start_forkserver();
|
|
||||||
init_done = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Proper initialization routine. */
|
|
||||||
|
|
||||||
__attribute__((constructor(101))) void __afl_auto_init(void) {
|
|
||||||
|
|
||||||
is_persistent = !!getenv(PERSIST_ENV_VAR);
|
|
||||||
|
|
||||||
if (getenv(DEFER_ENV_VAR)) return;
|
|
||||||
|
|
||||||
__afl_manual_init();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -30,7 +30,7 @@ cp ./program ./program.cmplog
|
|||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
AFL++ has the new -c option that can be used to specify a CmpLog binary (the second
|
AFL++ has the new -c option that needs to be used to specify the CmpLog binary (the second
|
||||||
build).
|
build).
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
@ -39,4 +39,4 @@ For example:
|
|||||||
afl-fuzz -i input -o output -c ./program.cmplog -m none -- ./program.afl @@
|
afl-fuzz -i input -o output -c ./program.cmplog -m none -- ./program.afl @@
|
||||||
```
|
```
|
||||||
|
|
||||||
Be careful to use -m none because CmpLog maps a lot of pages.
|
Be sure to use `-m none` because CmpLog can map a lot of pages.
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
This is an LLVM-based implementation of the context sensitive branch coverage.
|
This is an LLVM-based implementation of the context sensitive branch coverage.
|
||||||
|
|
||||||
Basically every function gets it's own ID and that ID is combined with the
|
Basically every function gets its own ID and that ID is combined with the
|
||||||
edges of the called functions.
|
edges of the called functions.
|
||||||
|
|
||||||
So if both function A and function B call a function C, the coverage
|
So if both function A and function B call a function C, the coverage
|
@ -1,7 +1,7 @@
|
|||||||
# GCC-based instrumentation for afl-fuzz
|
# GCC-based instrumentation for afl-fuzz
|
||||||
|
|
||||||
(See [../README.md](../README.md) for the general instruction manual.)
|
(See [../README.md](../README.md) for the general instruction manual.)
|
||||||
(See [../llvm_mode/README.md](../llvm_mode/README.md) for the LLVM-based instrumentation.)
|
(See [README.llvm.md](README.llvm.md) for the LLVM-based instrumentation.)
|
||||||
|
|
||||||
!!! TODO items are:
|
!!! TODO items are:
|
||||||
!!! => inline instrumentation has to work!
|
!!! => inline instrumentation has to work!
|
30
instrumentation/README.instrim.md
Normal file
30
instrumentation/README.instrim.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# InsTrim
|
||||||
|
|
||||||
|
InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
InsTrim is the work of Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao and Shih-Kun Huang.
|
||||||
|
|
||||||
|
It uses a CFG (call flow graph) and markers to instrument just what
|
||||||
|
is necessary in the binary (ie less than llvm_mode). As a result the binary is
|
||||||
|
about 10-15% faster compared to normal llvm_mode however with some coverage loss.
|
||||||
|
It requires at least llvm version 3.8.0 to build.
|
||||||
|
If you have LLVM 7+ we recommend PCGUARD instead.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Set the environment variable `AFL_LLVM_INSTRUMENT=CFG` or `AFL_LLVM_INSTRIM=1`
|
||||||
|
during compilation of the target.
|
||||||
|
|
||||||
|
There is also special mode which instruments loops in a way so that
|
||||||
|
afl-fuzz can see which loop path has been selected but not being able to
|
||||||
|
see how often the loop has been rerun.
|
||||||
|
This again is a tradeoff for speed for less path information.
|
||||||
|
To enable this mode set `AFL_LLVM_INSTRIM_LOOPHEAD=1`.
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
The paper from Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao and Shih-Kun Huang:
|
||||||
|
[InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing]
|
||||||
|
(https://www.ndss-symposium.org/wp-content/uploads/2018/07/bar2018_14_Hsu_paper.pdf)
|
@ -1,8 +1,8 @@
|
|||||||
# Using afl++ with partial instrumentation
|
# Using afl++ with partial instrumentation
|
||||||
|
|
||||||
This file describes how you can selectively instrument only the source files
|
This file describes how to selectively instrument only source files
|
||||||
or functions that are interesting to you using the LLVM instrumentation
|
or functions that are of interest to you using the LLVM instrumentation
|
||||||
provided by afl++
|
provided by afl++.
|
||||||
|
|
||||||
## 1) Description and purpose
|
## 1) Description and purpose
|
||||||
|
|
||||||
@ -13,10 +13,10 @@ on the important parts of the program, avoiding undesired noise and
|
|||||||
disturbance by uninteresting code being exercised.
|
disturbance by uninteresting code being exercised.
|
||||||
|
|
||||||
For this purpose, a "partial instrumentation" support en par with llvm sancov
|
For this purpose, a "partial instrumentation" support en par with llvm sancov
|
||||||
is provided by afl++ that allows you to specify on a source file and function
|
is provided by afl++ that allows to specify on a source file and function
|
||||||
level which function should be compiled with or without instrumentation.
|
level which function should be compiled with or without instrumentation.
|
||||||
|
|
||||||
Note: When using PCGUARD mode - and have llvm 12+ - you can use this instead:
|
Note: When using PCGUARD mode - and llvm 12+ - you can use this instead:
|
||||||
https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
|
https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
|
||||||
|
|
||||||
The llvm sancov list format is fully supported by afl++, however afl++ has
|
The llvm sancov list format is fully supported by afl++, however afl++ has
|
||||||
@ -24,8 +24,8 @@ more flexibility.
|
|||||||
|
|
||||||
## 2) Building the LLVM module
|
## 2) Building the LLVM module
|
||||||
|
|
||||||
The new code is part of the existing afl++ LLVM module in the llvm_mode/
|
The new code is part of the existing afl++ LLVM module in the instrumentation/
|
||||||
subdirectory. There is nothing specifically to do :)
|
subdirectory. There is nothing specifically to do for the build :)
|
||||||
|
|
||||||
## 3) How to use the partial instrumentation mode
|
## 3) How to use the partial instrumentation mode
|
||||||
|
|
||||||
@ -34,14 +34,14 @@ afl-clang-fast/afl-clang-fast++ or afl-clang-lto/afl-clang-lto++.
|
|||||||
The only required change is that you need to set either the environment variable
|
The only required change is that you need to set either the environment variable
|
||||||
AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST set with a filename.
|
AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST set with a filename.
|
||||||
|
|
||||||
That file then contains the filenames or functions that should be instrumented
|
That file should contain the file names or functions that are to be instrumented
|
||||||
(AFL_LLVM_ALLOWLIST) or should specifically NOT be instrumented (AFL_LLVM_DENYLIST).
|
(AFL_LLVM_ALLOWLIST) or are specifically NOT to be instrumented (AFL_LLVM_DENYLIST).
|
||||||
|
|
||||||
For matching, the function/filename that is being compiled must end in the
|
For matching to succeed, the function/file name that is being compiled must end in the
|
||||||
function/filename entry contained in this instrument file list (to avoid
|
function/file name entry contained in this instrument file list. That is to avoid
|
||||||
breaking the matching when absolute paths are used during compilation).
|
breaking the match when absolute paths are used during compilation.
|
||||||
|
|
||||||
**NOTE:** In builds with optimization enabled functions might be inlined and would not match!
|
**NOTE:** In builds with optimization enabled, functions might be inlined and would not match!
|
||||||
|
|
||||||
For example if your source tree looks like this:
|
For example if your source tree looks like this:
|
||||||
```
|
```
|
||||||
@ -52,13 +52,13 @@ project/feature_b/b1.cpp
|
|||||||
project/feature_b/b2.cpp
|
project/feature_b/b2.cpp
|
||||||
```
|
```
|
||||||
|
|
||||||
and you only want to test feature_a, then create a instrument file list file containing:
|
and you only want to test feature_a, then create an "instrument file list" file containing:
|
||||||
```
|
```
|
||||||
feature_a/a1.cpp
|
feature_a/a1.cpp
|
||||||
feature_a/a2.cpp
|
feature_a/a2.cpp
|
||||||
```
|
```
|
||||||
|
|
||||||
However if the instrument file list file contains only this, it works as well:
|
However if the "instrument file list" file contains only this, it works as well:
|
||||||
```
|
```
|
||||||
a1.cpp
|
a1.cpp
|
||||||
a2.cpp
|
a2.cpp
|
||||||
@ -67,9 +67,9 @@ but it might lead to files being unwantedly instrumented if the same filename
|
|||||||
exists somewhere else in the project directories.
|
exists somewhere else in the project directories.
|
||||||
|
|
||||||
You can also specify function names. Note that for C++ the function names
|
You can also specify function names. Note that for C++ the function names
|
||||||
must be mangled to match!
|
must be mangled to match! `nm` can print these names.
|
||||||
|
|
||||||
afl++ is able to identify if an entry is a filename or a function.
|
afl++ is able to identify whether an entry is a filename or a function.
|
||||||
However if you want to be sure (and compliant to the sancov allow/blocklist
|
However if you want to be sure (and compliant to the sancov allow/blocklist
|
||||||
format), you can specify source file entries like this:
|
format), you can specify source file entries like this:
|
||||||
```
|
```
|
||||||
@ -82,5 +82,6 @@ fun: MallocFoo
|
|||||||
Note that whitespace is ignored and comments (`# foo`) are supported.
|
Note that whitespace is ignored and comments (`# foo`) are supported.
|
||||||
|
|
||||||
## 4) UNIX-style pattern matching
|
## 4) UNIX-style pattern matching
|
||||||
You can add UNIX-style pattern matching in the the instrument file list entries.
|
|
||||||
|
You can add UNIX-style pattern matching in the "instrument file list" entries.
|
||||||
See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags.
|
See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags.
|
@ -1,5 +1,15 @@
|
|||||||
# laf-intel instrumentation
|
# laf-intel instrumentation
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This originally is the work of an individual nicknamed laf-intel.
|
||||||
|
His blog [Circumventing Fuzzing Roadblocks with Compiler Transformations]
|
||||||
|
(https://lafintel.wordpress.com/) and gitlab repo [laf-llvm-pass]
|
||||||
|
(https://gitlab.com/laf-intel/laf-llvm-pass/)
|
||||||
|
describe some code transformations that
|
||||||
|
help afl++ to enter conditional blocks, where conditions consist of
|
||||||
|
comparisons of large values.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
By default these passes will not run when you compile programs using
|
By default these passes will not run when you compile programs using
|
||||||
@ -24,18 +34,22 @@ Enables the split-compares pass.
|
|||||||
By default it will
|
By default it will
|
||||||
1. simplify operators >= (and <=) into chains of > (<) and == comparisons
|
1. simplify operators >= (and <=) into chains of > (<) and == comparisons
|
||||||
2. change signed integer comparisons to a chain of sign-only comparison
|
2. change signed integer comparisons to a chain of sign-only comparison
|
||||||
and unsigned comparisons
|
and unsigned integer comparisons
|
||||||
3. split all unsigned integer comparisons with bit widths of
|
3. split all unsigned integer comparisons with bit widths of
|
||||||
64, 32 or 16 bits to chains of 8 bits comparisons.
|
64, 32 or 16 bits to chains of 8 bits comparisons.
|
||||||
|
|
||||||
You can change the behaviour of the last step by setting
|
You can change the behaviour of the last step by setting
|
||||||
`export AFL_LLVM_LAF_SPLIT_COMPARES_BITW=<bit_width>`, where
|
`export AFL_LLVM_LAF_SPLIT_COMPARES_BITW=<bit_width>`, where
|
||||||
bit_width may be 64, 32 or 16.
|
bit_width may be 64, 32 or 16. For example, a bit_width of 16
|
||||||
|
would split larger comparisons down to 16 bit comparisons.
|
||||||
|
|
||||||
A new experimental feature is splitting floating point comparisons into a
|
A new experimental feature is splitting floating point comparisons into a
|
||||||
series of sign, exponent and mantissa comparisons followed by splitting each
|
series of sign, exponent and mantissa comparisons followed by splitting each
|
||||||
of them into 8 bit comparisons when necessary.
|
of them into 8 bit comparisons when necessary.
|
||||||
It is activated with the `AFL_LLVM_LAF_SPLIT_FLOATS` setting.
|
It is activated with the `AFL_LLVM_LAF_SPLIT_FLOATS` setting.
|
||||||
|
Please note that full IEEE 754 functionality is not preserved, that is
|
||||||
|
values of nan and infinity will probably behave differently.
|
||||||
|
|
||||||
Note that setting this automatically activates `AFL_LLVM_LAF_SPLIT_COMPARES`
|
Note that setting this automatically activates `AFL_LLVM_LAF_SPLIT_COMPARES`
|
||||||
|
|
||||||
You can also set `AFL_LLVM_LAF_ALL` and have all of the above enabled :-)
|
You can also set `AFL_LLVM_LAF_ALL` and have all of the above enabled :-)
|
@ -1,8 +1,8 @@
|
|||||||
# Fast LLVM-based instrumentation for afl-fuzz
|
# Fast LLVM-based instrumentation for afl-fuzz
|
||||||
|
|
||||||
(See [../README](../README.md) for the general instruction manual.)
|
(See [../README.md](../README.md) for the general instruction manual.)
|
||||||
|
|
||||||
(See [../gcc_plugin/README](../gcc_plugin/README.md) for the GCC-based instrumentation.)
|
(See [README.gcc_plugon.md](../README.gcc_plugin.md) for the GCC-based instrumentation.)
|
||||||
|
|
||||||
## 1) Introduction
|
## 1) Introduction
|
||||||
|
|
||||||
@ -93,15 +93,16 @@ operating mode of AFL, e.g.:
|
|||||||
|
|
||||||
Be sure to also include CXX set to afl-clang-fast++ for C++ code.
|
Be sure to also include CXX set to afl-clang-fast++ for C++ code.
|
||||||
|
|
||||||
|
Note that afl-clang-fast/afl-clang-fast++ are just pointers to afl-cc.
|
||||||
|
You can also use afl-cc/afl-c++ and instead direct it to use LLVM
|
||||||
|
instrumentation by either setting `AFL_CC_COMPILER=LLVM` or pass the parameter
|
||||||
|
`--afl-llvm` via CFLAGS/CXXFLAGS/CPPFLAGS.
|
||||||
|
|
||||||
The tool honors roughly the same environmental variables as afl-gcc (see
|
The tool honors roughly the same environmental variables as afl-gcc (see
|
||||||
[docs/env_variables.md](../docs/env_variables.md)). This includes AFL_USE_ASAN,
|
[docs/env_variables.md](../docs/env_variables.md)). This includes AFL_USE_ASAN,
|
||||||
AFL_HARDEN, and AFL_DONT_OPTIMIZE. However AFL_INST_RATIO is not honored
|
AFL_HARDEN, and AFL_DONT_OPTIMIZE. However AFL_INST_RATIO is not honored
|
||||||
as it does not serve a good purpose with the more effective instrim CFG
|
as it does not serve a good purpose with the more effective PCGUARD, LTO and
|
||||||
analysis.
|
instrim CFG analysis.
|
||||||
|
|
||||||
Note: if you want the LLVM helper to be installed on your system for all
|
|
||||||
users, you need to build it before issuing 'make install' in the parent
|
|
||||||
directory.
|
|
||||||
|
|
||||||
## 3) Options
|
## 3) Options
|
||||||
|
|
||||||
@ -109,9 +110,9 @@ Several options are present to make llvm_mode faster or help it rearrange
|
|||||||
the code to make afl-fuzz path discovery easier.
|
the code to make afl-fuzz path discovery easier.
|
||||||
|
|
||||||
If you need just to instrument specific parts of the code, you can the instrument file list
|
If you need just to instrument specific parts of the code, you can the instrument file list
|
||||||
which C/C++ files to actually instrument. See [README.instrument_list](README.instrument_list.md)
|
which C/C++ files to actually instrument. See [README.instrument_list.md](README.instrument_list.md)
|
||||||
|
|
||||||
For splitting memcmp, strncmp, etc. please see [README.laf-intel](README.laf-intel.md)
|
For splitting memcmp, strncmp, etc. please see [README.laf-intel.md](README.laf-intel.md)
|
||||||
|
|
||||||
Then there are different ways of instrumenting the target:
|
Then there are different ways of instrumenting the target:
|
||||||
|
|
||||||
@ -119,42 +120,42 @@ Then there are different ways of instrumenting the target:
|
|||||||
markers to just instrument what is needed. This increases speed by 10-15%
|
markers to just instrument what is needed. This increases speed by 10-15%
|
||||||
without any disadvantages
|
without any disadvantages
|
||||||
If you want to use this, set AFL_LLVM_INSTRUMENT=CFG or AFL_LLVM_INSTRIM=1
|
If you want to use this, set AFL_LLVM_INSTRUMENT=CFG or AFL_LLVM_INSTRIM=1
|
||||||
See [README.instrim](README.instrim.md)
|
See [README.instrim.md](README.instrim.md)
|
||||||
|
|
||||||
2. An even better instrumentation strategy uses LTO and link time
|
2. An even better instrumentation strategy uses LTO and link time
|
||||||
instrumentation. Note that not all targets can compile in this mode, however
|
instrumentation. Note that not all targets can compile in this mode, however
|
||||||
if it works it is the best option you can use.
|
if it works it is the best option you can use.
|
||||||
Simply use afl-clang-lto/afl-clang-lto++ to use this option.
|
Simply use afl-clang-lto/afl-clang-lto++ to use this option.
|
||||||
See [README.lto](README.lto.md)
|
See [README.lto.md](README.lto.md)
|
||||||
|
|
||||||
3. Alternativly you can choose a completely different coverage method:
|
3. Alternativly you can choose a completely different coverage method:
|
||||||
|
|
||||||
3a. N-GRAM coverage - which combines the previous visited edges with the
|
3a. N-GRAM coverage - which combines the previous visited edges with the
|
||||||
current one. This explodes the map but on the other hand has proven to be
|
current one. This explodes the map but on the other hand has proven to be
|
||||||
effective for fuzzing.
|
effective for fuzzing.
|
||||||
See [README.ngram](README.ngram.md)
|
See [README.ngram.md](README.ngram.md)
|
||||||
|
|
||||||
3b. Context sensitive coverage - which combines the visited edges with an
|
3b. Context sensitive coverage - which combines the visited edges with an
|
||||||
individual caller ID (the function that called the current one)
|
individual caller ID (the function that called the current one)
|
||||||
[README.ctx](README.ctx.md)
|
[README.ctx.md](README.ctx.md)
|
||||||
|
|
||||||
Then - additionally to one of the instrumentation options above - there is
|
Then - additionally to one of the instrumentation options above - there is
|
||||||
a very effective new instrumentation option called CmpLog as an alternative to
|
a very effective new instrumentation option called CmpLog as an alternative to
|
||||||
laf-intel that allow AFL++ to apply mutations similar to Redqueen.
|
laf-intel that allow AFL++ to apply mutations similar to Redqueen.
|
||||||
See [README.cmplog](README.cmplog.md)
|
See [README.cmplog.md](README.cmplog.md)
|
||||||
|
|
||||||
Finally if your llvm version is 8 or lower, you can activate a mode that
|
Finally if your llvm version is 8 or lower, you can activate a mode that
|
||||||
prevents that a counter overflow result in a 0 value. This is good for
|
prevents that a counter overflow result in a 0 value. This is good for
|
||||||
path discovery, but the llvm implementation for x86 for this functionality
|
path discovery, but the llvm implementation for x86 for this functionality
|
||||||
is not optimal and was only fixed in llvm 9.
|
is not optimal and was only fixed in llvm 9.
|
||||||
You can set this with AFL_LLVM_NOT_ZERO=1
|
You can set this with AFL_LLVM_NOT_ZERO=1
|
||||||
See [README.neverzero](README.neverzero.md)
|
See [README.neverzero.md](README.neverzero.md)
|
||||||
|
|
||||||
## 4) Snapshot feature
|
## 4) Snapshot feature
|
||||||
|
|
||||||
To speed up fuzzing you can use a linux loadable kernel module which enables
|
To speed up fuzzing you can use a linux loadable kernel module which enables
|
||||||
a snapshot feature.
|
a snapshot feature.
|
||||||
See [README.snapshot](README.snapshot.md)
|
See [README.snapshot.md](README.snapshot.md)
|
||||||
|
|
||||||
## 5) Gotchas, feedback, bugs
|
## 5) Gotchas, feedback, bugs
|
||||||
|
|
||||||
@ -182,5 +183,12 @@ targets this way:
|
|||||||
AFL_LLVM_INSTRUMENT=PCGUARD make
|
AFL_LLVM_INSTRUMENT=PCGUARD make
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this us currently the default, as it is the best mode.
|
Note that this us currently the default if you use LLVM >= 7, as it is the best
|
||||||
|
mode. Recommended is LLVM >= 9.
|
||||||
If you have llvm 11+ and compiled afl-clang-lto - this is the only better mode.
|
If you have llvm 11+ and compiled afl-clang-lto - this is the only better mode.
|
||||||
|
|
||||||
|
## 8) Bonus feature: 'dict2file' pass
|
||||||
|
|
||||||
|
Just specify `AFL_LLVM_DICT2FILE=/absolute/path/file.txt` and during compilation
|
||||||
|
all constant string compare parameters will be written to this file to be
|
||||||
|
used with afl-fuzz' `-x` option.
|
@ -95,10 +95,7 @@ export PATH=`pwd`/bin:$PATH
|
|||||||
export LLVM_CONFIG=`pwd`/bin/llvm-config
|
export LLVM_CONFIG=`pwd`/bin/llvm-config
|
||||||
cd /path/to/AFLplusplus/
|
cd /path/to/AFLplusplus/
|
||||||
make
|
make
|
||||||
cd llvm_mode
|
sudo make install
|
||||||
make
|
|
||||||
cd ..
|
|
||||||
make install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## How to use afl-clang-lto
|
## How to use afl-clang-lto
|
||||||
@ -115,18 +112,18 @@ make
|
|||||||
```
|
```
|
||||||
|
|
||||||
NOTE: some targets also need to set the linker, try both `afl-clang-lto` and
|
NOTE: some targets also need to set the linker, try both `afl-clang-lto` and
|
||||||
`afl-ld-lto` for this for `LD=` for `configure`.
|
`afl-ld-lto` for `LD=` before `configure`.
|
||||||
|
|
||||||
## AUTODICTIONARY feature
|
## AUTODICTIONARY feature
|
||||||
|
|
||||||
While compiling, automatically a dictionary based on string comparisons is
|
While compiling, a dictionary based on string comparisons is automatically
|
||||||
generated put into the target binary. This dictionary is transfered to afl-fuzz
|
generated and put into the target binary. This dictionary is transfered to afl-fuzz
|
||||||
on start. This improves coverage statistically by 5-10% :)
|
on start. This improves coverage statistically by 5-10% :)
|
||||||
|
|
||||||
## Fixed memory map
|
## Fixed memory map
|
||||||
|
|
||||||
To speed up fuzzing, it is possible to set a fixed shared memory map.
|
To speed up fuzzing, it is possible to set a fixed shared memory map.
|
||||||
Recommened is the value 0x10000.
|
Recommended is the value 0x10000.
|
||||||
In most cases this will work without any problems. However if a target uses
|
In most cases this will work without any problems. However if a target uses
|
||||||
early constructors, ifuncs or a deferred forkserver this can crash the target.
|
early constructors, ifuncs or a deferred forkserver this can crash the target.
|
||||||
On unusual operating systems/processors/kernels or weird libraries this might
|
On unusual operating systems/processors/kernels or weird libraries this might
|
||||||
@ -136,14 +133,14 @@ to be dynamic - the original afl way, which is slower).
|
|||||||
|
|
||||||
## Document edge IDs
|
## Document edge IDs
|
||||||
|
|
||||||
Setting `export AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge
|
Setting `export AFL_LLVM_DOCUMENT_IDS=file` will document in a file which edge
|
||||||
ID was given to which function. This helps to identify functions with variable
|
ID was given to which function. This helps to identify functions with variable
|
||||||
bytes or which functions were touched by an input.
|
bytes or which functions were touched by an input.
|
||||||
|
|
||||||
## Solving difficult targets
|
## Solving difficult targets
|
||||||
|
|
||||||
Some targets are difficult because the configure script does unusual stuff that
|
Some targets are difficult because the configure script does unusual stuff that
|
||||||
is unexpected for afl. See the next chapter `Potential issues` how to solve
|
is unexpected for afl. See the next chapter `Potential issues` for how to solve
|
||||||
these.
|
these.
|
||||||
|
|
||||||
### Example: ffmpeg
|
### Example: ffmpeg
|
||||||
@ -151,7 +148,7 @@ these.
|
|||||||
An example of a hard to solve target is ffmpeg. Here is how to successfully
|
An example of a hard to solve target is ffmpeg. Here is how to successfully
|
||||||
instrument it:
|
instrument it:
|
||||||
|
|
||||||
1. Get and extract the current ffmpeg and change to it's directory
|
1. Get and extract the current ffmpeg and change to its directory
|
||||||
|
|
||||||
2. Running configure with --cc=clang fails and various other items will fail
|
2. Running configure with --cc=clang fails and various other items will fail
|
||||||
when compiling, so we have to trick configure:
|
when compiling, so we have to trick configure:
|
||||||
@ -221,13 +218,13 @@ If you see this message:
|
|||||||
/bin/ld: libfoo.a: error adding symbols: archive has no index; run ranlib to add one
|
/bin/ld: libfoo.a: error adding symbols: archive has no index; run ranlib to add one
|
||||||
```
|
```
|
||||||
This is because usually gnu gcc ranlib is being called which cannot deal with clang LTO files.
|
This is because usually gnu gcc ranlib is being called which cannot deal with clang LTO files.
|
||||||
The solution is simple: when you ./configure you have also have to set RANLIB=llvm-ranlib and AR=llvm-ar
|
The solution is simple: when you ./configure you also have to set RANLIB=llvm-ranlib and AR=llvm-ar
|
||||||
|
|
||||||
Solution:
|
Solution:
|
||||||
```
|
```
|
||||||
AR=llvm-ar RANLIB=llvm-ranlib CC=afl-clang-lto CXX=afl-clang-lto++ ./configure --disable-shared
|
AR=llvm-ar RANLIB=llvm-ranlib CC=afl-clang-lto CXX=afl-clang-lto++ ./configure --disable-shared
|
||||||
```
|
```
|
||||||
and on some target you have to to AR=/RANLIB= even for make as the configure script does not save it.
|
and on some targets you have to set AR=/RANLIB= even for make as the configure script does not save it.
|
||||||
Other targets ignore environment variables and need the parameters set via
|
Other targets ignore environment variables and need the parameters set via
|
||||||
`./configure --cc=... --cxx= --ranlib= ...` etc. (I am looking at you ffmpeg!).
|
`./configure --cc=... --cxx= --ranlib= ...` etc. (I am looking at you ffmpeg!).
|
||||||
|
|
||||||
@ -246,8 +243,8 @@ AS=llvm-as ...
|
|||||||
afl-clang-lto is still work in progress.
|
afl-clang-lto is still work in progress.
|
||||||
|
|
||||||
Known issues:
|
Known issues:
|
||||||
* Anything that llvm 11+ cannot compile, afl-clang-lto can not compile either - obviously
|
* Anything that llvm 11+ cannot compile, afl-clang-lto cannot compile either - obviously
|
||||||
* Anything that does not compile with LTO, afl-clang-lto can not compile either - obviously
|
* Anything that does not compile with LTO, afl-clang-lto cannot compile either - obviously
|
||||||
|
|
||||||
Hence if building a target with afl-clang-lto fails try to build it with llvm12
|
Hence if building a target with afl-clang-lto fails try to build it with llvm12
|
||||||
and LTO enabled (`CC=clang-12` `CXX=clang++-12` `CFLAGS=-flto=full` and
|
and LTO enabled (`CC=clang-12` `CXX=clang++-12` `CFLAGS=-flto=full` and
|
||||||
@ -267,14 +264,14 @@ for this in the PassManager: EP_FullLinkTimeOptimizationLast
|
|||||||
("Fun" info - nobody knows what this is doing. And the developer who
|
("Fun" info - nobody knows what this is doing. And the developer who
|
||||||
implemented this didn't respond to emails.)
|
implemented this didn't respond to emails.)
|
||||||
|
|
||||||
In December came then the idea to implement this as a pass that is run via
|
In December then came the idea to implement this as a pass that is run via
|
||||||
the llvm "opt" program, which is performed via an own linker that afterwards
|
the llvm "opt" program, which is performed via an own linker that afterwards
|
||||||
calls the real linker.
|
calls the real linker.
|
||||||
This was first implemented in January and work ... kinda.
|
This was first implemented in January and work ... kinda.
|
||||||
The LTO time instrumentation worked, however the "how" the basic blocks were
|
The LTO time instrumentation worked, however "how" the basic blocks were
|
||||||
instrumented was a problem, as reducing duplicates turned out to be very,
|
instrumented was a problem, as reducing duplicates turned out to be very,
|
||||||
very difficult with a program that has so many paths and therefore so many
|
very difficult with a program that has so many paths and therefore so many
|
||||||
dependencies. At lot of strategies were implemented - and failed.
|
dependencies. A lot of strategies were implemented - and failed.
|
||||||
And then sat solvers were tried, but with over 10.000 variables that turned
|
And then sat solvers were tried, but with over 10.000 variables that turned
|
||||||
out to be a dead-end too.
|
out to be a dead-end too.
|
||||||
|
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
In larger, complex or reiterative programs the counters that collect the edge
|
In larger, complex or reiterative programs the byte sized counters that collect
|
||||||
coverage can easily fill up and wrap around.
|
the edge coverage can easily fill up and wrap around.
|
||||||
This is not that much of an issue - unless by chance it wraps just to a value
|
This is not that much of an issue - unless by chance it wraps just to a value
|
||||||
of zero when the program execution ends.
|
of zero when the program execution ends.
|
||||||
In this case afl-fuzz is not able to see that the edge has been accessed and
|
In this case afl-fuzz is not able to see that the edge has been accessed and
|
@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
The most effective way is to fuzz in persistent mode, as the speed can easily
|
The most effective way is to fuzz in persistent mode, as the speed can easily
|
||||||
be x10 or x20 times faster without any disadvanges.
|
be x10 or x20 times faster without any disadvanges.
|
||||||
*All professionel fuzzing is using this mode.*
|
*All professional fuzzing is using this mode.*
|
||||||
|
|
||||||
This requires that the target can be called in a (or several) function(s),
|
This requires that the target can be called in a (or several) function(s),
|
||||||
and that the state can be resetted so that multiple calls be be performed
|
and that its state can be resetted so that multiple calls can be performed
|
||||||
without memory leaking and former runs having no impact on following runs
|
without resource leaks and former runs having no impact on following runs
|
||||||
(this can be seen by the `stability` indicator in the `afl-fuzz` UI).
|
(this can be seen by the `stability` indicator in the `afl-fuzz` UI).
|
||||||
|
|
||||||
Examples can be found in [examples/persistent_mode](../examples/persistent_mode).
|
Examples can be found in [examples/persistent_mode](../examples/persistent_mode).
|
||||||
@ -67,7 +67,7 @@ add this just after the includes:
|
|||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3) deferred initialization
|
## 3) Deferred initialization
|
||||||
|
|
||||||
AFL tries to optimize performance by executing the targeted binary just once,
|
AFL tries to optimize performance by executing the targeted binary just once,
|
||||||
stopping it just before main(), and then cloning this "main" process to get
|
stopping it just before main(), and then cloning this "main" process to get
|
||||||
@ -112,7 +112,7 @@ With the location selected, add this code in the appropriate spot:
|
|||||||
You don't need the #ifdef guards, but including them ensures that the program
|
You don't need the #ifdef guards, but including them ensures that the program
|
||||||
will keep working normally when compiled with a tool other than afl-clang-fast.
|
will keep working normally when compiled with a tool other than afl-clang-fast.
|
||||||
|
|
||||||
Finally, recompile the program with afl-clang-fast (afl-gcc or afl-clang will
|
Finally, recompile the program with afl-clang-fast/lto (afl-gcc or afl-clang will
|
||||||
*not* generate a deferred-initialization binary) - and you should be all set!
|
*not* generate a deferred-initialization binary) - and you should be all set!
|
||||||
|
|
||||||
*NOTE:* In the code between `main` and `__AFL_INIT()` should not be any code
|
*NOTE:* In the code between `main` and `__AFL_INIT()` should not be any code
|
||||||
@ -142,7 +142,7 @@ and just before `__AFL_INIT()`:
|
|||||||
__afl_area_ptr = NULL;
|
__afl_area_ptr = NULL;
|
||||||
```
|
```
|
||||||
|
|
||||||
## 4) persistent mode
|
## 4) Persistent mode
|
||||||
|
|
||||||
Some libraries provide APIs that are stateless, or whose state can be reset in
|
Some libraries provide APIs that are stateless, or whose state can be reset in
|
||||||
between processing different input files. When such a reset is performed, a
|
between processing different input files. When such a reset is performed, a
|
||||||
@ -183,7 +183,7 @@ PS. Because there are task switches still involved, the mode isn't as fast as
|
|||||||
faster than the normal fork() model, and compared to in-process fuzzing,
|
faster than the normal fork() model, and compared to in-process fuzzing,
|
||||||
should be a lot more robust.
|
should be a lot more robust.
|
||||||
|
|
||||||
## 5) shared memory fuzzing
|
## 5) Shared memory fuzzing
|
||||||
|
|
||||||
You can speed up the fuzzing process even more by receiving the fuzzing data
|
You can speed up the fuzzing process even more by receiving the fuzzing data
|
||||||
via shared memory instead of stdin or files.
|
via shared memory instead of stdin or files.
|
@ -1,7 +1,7 @@
|
|||||||
# AFL++ snapshot feature
|
# AFL++ snapshot feature
|
||||||
|
|
||||||
Snapshotting is a feature that makes a snapshot from a process and then
|
Snapshotting is a feature that makes a snapshot from a process and then
|
||||||
restores it's state, which is faster then forking it again.
|
restores its state, which is faster then forking it again.
|
||||||
|
|
||||||
All targets compiled with llvm_mode are automatically enabled for the
|
All targets compiled with llvm_mode are automatically enabled for the
|
||||||
snapshot feature.
|
snapshot feature.
|
@ -1,11 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
american fuzzy lop++ - LLVM instrumentation bootstrap
|
american fuzzy lop++ - instrumentation bootstrap
|
||||||
---------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
Written by Laszlo Szekeres <lszekeres@google.com> and
|
|
||||||
Michal Zalewski
|
|
||||||
|
|
||||||
LLVM integration design comes from Laszlo Szekeres.
|
|
||||||
|
|
||||||
Copyright 2015, 2016 Google Inc. All rights reserved.
|
Copyright 2015, 2016 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||||
@ -16,7 +11,6 @@
|
|||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
This code is the rewrite of afl-as.h's main_payload.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -111,6 +105,22 @@ static u8 is_persistent;
|
|||||||
|
|
||||||
static u8 _is_sancov;
|
static u8 _is_sancov;
|
||||||
|
|
||||||
|
/* Uninspired gcc plugin instrumentation */
|
||||||
|
|
||||||
|
void __afl_trace(const u32 x) {
|
||||||
|
|
||||||
|
#if 1 /* enable for neverZero feature. */
|
||||||
|
__afl_area_ptr[__afl_prev_loc[0] ^ x] +=
|
||||||
|
1 + ((u8)(1 + __afl_area_ptr[__afl_prev_loc[0] ^ x]) == 0);
|
||||||
|
#else
|
||||||
|
++__afl_area_ptr[__afl_prev_loc[0] ^ x];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__afl_prev_loc[0] = (x >> 1);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Error reporting to forkserver controller */
|
/* Error reporting to forkserver controller */
|
||||||
|
|
||||||
void send_forkserver_error(int error) {
|
void send_forkserver_error(int error) {
|
||||||
@ -808,7 +818,7 @@ static void __afl_start_forkserver(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* A simplified persistent mode handler, used as explained in
|
/* A simplified persistent mode handler, used as explained in
|
||||||
* llvm_mode/README.md. */
|
* README.llvm.md. */
|
||||||
|
|
||||||
int __afl_persistent_loop(unsigned int max_cnt) {
|
int __afl_persistent_loop(unsigned int max_cnt) {
|
||||||
|
|
||||||
@ -958,7 +968,7 @@ __attribute__((constructor(0))) void __afl_auto_first(void) {
|
|||||||
|
|
||||||
/* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard.
|
/* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard.
|
||||||
It remains non-operational in the traditional, plugin-backed LLVM mode.
|
It remains non-operational in the traditional, plugin-backed LLVM mode.
|
||||||
For more info about 'trace-pc-guard', see llvm_mode/README.md.
|
For more info about 'trace-pc-guard', see README.llvm.md.
|
||||||
|
|
||||||
The first function (__sanitizer_cov_trace_pc_guard) is called back on every
|
The first function (__sanitizer_cov_trace_pc_guard) is called back on every
|
||||||
edge (as opposed to every basic block). */
|
edge (as opposed to every basic block). */
|
599
instrumentation/afl-llvm-dict2file.so.cc
Normal file
599
instrumentation/afl-llvm-dict2file.so.cc
Normal file
@ -0,0 +1,599 @@
|
|||||||
|
/*
|
||||||
|
american fuzzy lop++ - LLVM LTO instrumentation pass
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Written by Marc Heuse <mh@mh-sec.de>
|
||||||
|
|
||||||
|
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at:
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
This library is plugged into LLVM when invoking clang through afl-clang-lto.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AFL_LLVM_PASS
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "llvm/Config/llvm-config.h"
|
||||||
|
#include "llvm/ADT/Statistic.h"
|
||||||
|
#include "llvm/IR/IRBuilder.h"
|
||||||
|
#include "llvm/IR/LegacyPassManager.h"
|
||||||
|
#include "llvm/IR/BasicBlock.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/IR/DebugInfo.h"
|
||||||
|
#include "llvm/IR/CFG.h"
|
||||||
|
#include "llvm/IR/Verifier.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||||
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
|
#include "llvm/Analysis/MemorySSAUpdater.h"
|
||||||
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/IR/Constants.h"
|
||||||
|
|
||||||
|
#include "afl-llvm-common.h"
|
||||||
|
|
||||||
|
#ifndef O_DSYNC
|
||||||
|
#define O_DSYNC O_SYNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class AFLdict2filePass : public ModulePass {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static char ID;
|
||||||
|
|
||||||
|
AFLdict2filePass() : ModulePass(ID) {
|
||||||
|
|
||||||
|
if (getenv("AFL_DEBUG")) debug = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runOnModule(Module &M) override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void dict2file(int fd, u8 *mem, u32 len) {
|
||||||
|
|
||||||
|
int i, j, binary = 0;
|
||||||
|
char line[MAX_AUTO_EXTRA * 8], tmp[8];
|
||||||
|
|
||||||
|
strcpy(line, "\"");
|
||||||
|
j = 1;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
|
||||||
|
if (isprint(mem[i])) {
|
||||||
|
|
||||||
|
line[j++] = mem[i];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) {
|
||||||
|
|
||||||
|
line[j] = 0;
|
||||||
|
sprintf(tmp, "\\x%02x", (u8)mem[i]);
|
||||||
|
strcat(line, tmp);
|
||||||
|
j = strlen(line);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
binary = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
line[j] = 0;
|
||||||
|
strcat(line, "\"\n");
|
||||||
|
if (write(fd, line, strlen(line)) <= 0)
|
||||||
|
PFATAL("Could not write to dictionary file");
|
||||||
|
fsync(fd);
|
||||||
|
|
||||||
|
if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AFLdict2filePass::runOnModule(Module &M) {
|
||||||
|
|
||||||
|
DenseMap<Value *, std::string *> valueMap;
|
||||||
|
char * ptr;
|
||||||
|
int fd, found = 0;
|
||||||
|
|
||||||
|
/* Show a banner */
|
||||||
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
|
||||||
|
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
|
||||||
|
|
||||||
|
SAYF(cCYA "afl-llvm-dict2file" VERSION cRST
|
||||||
|
" by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
be_quiet = 1;
|
||||||
|
|
||||||
|
scanForDangerousFunctions(&M);
|
||||||
|
|
||||||
|
ptr = getenv("AFL_LLVM_DICT2FILE");
|
||||||
|
|
||||||
|
if (!ptr || *ptr != '/')
|
||||||
|
FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr);
|
||||||
|
|
||||||
|
if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0)
|
||||||
|
PFATAL("Could not open/create %s.", ptr);
|
||||||
|
|
||||||
|
/* Instrument all the things! */
|
||||||
|
|
||||||
|
for (auto &F : M) {
|
||||||
|
|
||||||
|
if (isIgnoreFunction(&F)) continue;
|
||||||
|
|
||||||
|
/* Some implementation notes.
|
||||||
|
*
|
||||||
|
* We try to handle 3 cases:
|
||||||
|
* - memcmp("foo", arg, 3) <- literal string
|
||||||
|
* - static char globalvar[] = "foo";
|
||||||
|
* memcmp(globalvar, arg, 3) <- global variable
|
||||||
|
* - char localvar[] = "foo";
|
||||||
|
* memcmp(locallvar, arg, 3) <- local variable
|
||||||
|
*
|
||||||
|
* The local variable case is the hardest. We can only detect that
|
||||||
|
* case if there is no reassignment or change in the variable.
|
||||||
|
* And it might not work across llvm version.
|
||||||
|
* What we do is hooking the initializer function for local variables
|
||||||
|
* (llvm.memcpy.p0i8.p0i8.i64) and note the string and the assigned
|
||||||
|
* variable. And if that variable is then used in a compare function
|
||||||
|
* we use that noted string.
|
||||||
|
* This seems not to work for tokens that have a size <= 4 :-(
|
||||||
|
*
|
||||||
|
* - if the compared length is smaller than the string length we
|
||||||
|
* save the full string. This is likely better for fuzzing but
|
||||||
|
* might be wrong in a few cases depending on optimizers
|
||||||
|
*
|
||||||
|
* - not using StringRef because there is a bug in the llvm 11
|
||||||
|
* checkout I am using which sometimes points to wrong strings
|
||||||
|
*
|
||||||
|
* Over and out. Took me a full day. damn. mh/vh
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (auto &BB : F) {
|
||||||
|
|
||||||
|
for (auto &IN : BB) {
|
||||||
|
|
||||||
|
CallInst *callInst = nullptr;
|
||||||
|
CmpInst * cmpInst = nullptr;
|
||||||
|
|
||||||
|
if ((cmpInst = dyn_cast<CmpInst>(&IN))) {
|
||||||
|
|
||||||
|
Value * op = cmpInst->getOperand(1);
|
||||||
|
ConstantInt *ilen = dyn_cast<ConstantInt>(op);
|
||||||
|
|
||||||
|
if (ilen) {
|
||||||
|
|
||||||
|
u64 val2 = 0, val = ilen->getZExtValue();
|
||||||
|
u32 len = 0;
|
||||||
|
if (val > 0x10000 && val < 0xffffffff) len = 4;
|
||||||
|
if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
|
||||||
|
auto c = cmpInst->getPredicate();
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
|
||||||
|
case CmpInst::FCMP_OGT: // fall through
|
||||||
|
case CmpInst::FCMP_OLE: // fall through
|
||||||
|
case CmpInst::ICMP_SLE: // fall through
|
||||||
|
case CmpInst::ICMP_SGT:
|
||||||
|
|
||||||
|
// signed comparison and it is a negative constant
|
||||||
|
if ((len == 4 && (val & 80000000)) ||
|
||||||
|
(len == 8 && (val & 8000000000000000))) {
|
||||||
|
|
||||||
|
if ((val & 0xffff) != 1) val2 = val - 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
case CmpInst::FCMP_UGT: // fall through
|
||||||
|
case CmpInst::FCMP_ULE: // fall through
|
||||||
|
case CmpInst::ICMP_UGT: // fall through
|
||||||
|
case CmpInst::ICMP_ULE:
|
||||||
|
if ((val & 0xffff) != 0xfffe) val2 = val + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CmpInst::FCMP_OLT: // fall through
|
||||||
|
case CmpInst::FCMP_OGE: // fall through
|
||||||
|
case CmpInst::ICMP_SLT: // fall through
|
||||||
|
case CmpInst::ICMP_SGE:
|
||||||
|
|
||||||
|
// signed comparison and it is a negative constant
|
||||||
|
if ((len == 4 && (val & 80000000)) ||
|
||||||
|
(len == 8 && (val & 8000000000000000))) {
|
||||||
|
|
||||||
|
if ((val & 0xffff) != 1) val2 = val - 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
case CmpInst::FCMP_ULT: // fall through
|
||||||
|
case CmpInst::FCMP_UGE: // fall through
|
||||||
|
case CmpInst::ICMP_ULT: // fall through
|
||||||
|
case CmpInst::ICMP_UGE:
|
||||||
|
if ((val & 0xffff) != 1) val2 = val - 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
val2 = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dict2file(fd, (u8 *)&val, len);
|
||||||
|
found++;
|
||||||
|
if (val2) {
|
||||||
|
|
||||||
|
dict2file(fd, (u8 *)&val2, len);
|
||||||
|
found++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||||
|
|
||||||
|
bool isStrcmp = true;
|
||||||
|
bool isMemcmp = true;
|
||||||
|
bool isStrncmp = true;
|
||||||
|
bool isStrcasecmp = true;
|
||||||
|
bool isStrncasecmp = true;
|
||||||
|
bool isIntMemcpy = true;
|
||||||
|
bool addedNull = false;
|
||||||
|
size_t optLen = 0;
|
||||||
|
|
||||||
|
Function *Callee = callInst->getCalledFunction();
|
||||||
|
if (!Callee) continue;
|
||||||
|
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
|
||||||
|
std::string FuncName = Callee->getName().str();
|
||||||
|
isStrcmp &= !FuncName.compare("strcmp");
|
||||||
|
isMemcmp &= !FuncName.compare("memcmp");
|
||||||
|
isStrncmp &= !FuncName.compare("strncmp");
|
||||||
|
isStrcasecmp &= !FuncName.compare("strcasecmp");
|
||||||
|
isStrncasecmp &= !FuncName.compare("strncasecmp");
|
||||||
|
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
|
||||||
|
|
||||||
|
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
|
||||||
|
!isStrncasecmp && !isIntMemcpy)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function
|
||||||
|
* prototype */
|
||||||
|
FunctionType *FT = Callee->getFunctionType();
|
||||||
|
|
||||||
|
isStrcmp &=
|
||||||
|
FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
|
||||||
|
FT->getParamType(0) == FT->getParamType(1) &&
|
||||||
|
FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
|
||||||
|
isStrcasecmp &=
|
||||||
|
FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
|
||||||
|
FT->getParamType(0) == FT->getParamType(1) &&
|
||||||
|
FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
|
||||||
|
isMemcmp &= FT->getNumParams() == 3 &&
|
||||||
|
FT->getReturnType()->isIntegerTy(32) &&
|
||||||
|
FT->getParamType(0)->isPointerTy() &&
|
||||||
|
FT->getParamType(1)->isPointerTy() &&
|
||||||
|
FT->getParamType(2)->isIntegerTy();
|
||||||
|
isStrncmp &= FT->getNumParams() == 3 &&
|
||||||
|
FT->getReturnType()->isIntegerTy(32) &&
|
||||||
|
FT->getParamType(0) == FT->getParamType(1) &&
|
||||||
|
FT->getParamType(0) ==
|
||||||
|
IntegerType::getInt8PtrTy(M.getContext()) &&
|
||||||
|
FT->getParamType(2)->isIntegerTy();
|
||||||
|
isStrncasecmp &= FT->getNumParams() == 3 &&
|
||||||
|
FT->getReturnType()->isIntegerTy(32) &&
|
||||||
|
FT->getParamType(0) == FT->getParamType(1) &&
|
||||||
|
FT->getParamType(0) ==
|
||||||
|
IntegerType::getInt8PtrTy(M.getContext()) &&
|
||||||
|
FT->getParamType(2)->isIntegerTy();
|
||||||
|
|
||||||
|
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
|
||||||
|
!isStrncasecmp && !isIntMemcpy)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* is a str{n,}{case,}cmp/memcmp, check if we have
|
||||||
|
* str{case,}cmp(x, "const") or str{case,}cmp("const", x)
|
||||||
|
* strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x, ..)
|
||||||
|
* memcmp(x, "const", ..) or memcmp("const", x, ..) */
|
||||||
|
Value *Str1P = callInst->getArgOperand(0),
|
||||||
|
*Str2P = callInst->getArgOperand(1);
|
||||||
|
std::string Str1, Str2;
|
||||||
|
StringRef TmpStr;
|
||||||
|
bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
|
||||||
|
if (TmpStr.empty()) {
|
||||||
|
|
||||||
|
HasStr1 = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
HasStr1 = true;
|
||||||
|
Str1 = TmpStr.str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
|
||||||
|
if (TmpStr.empty()) {
|
||||||
|
|
||||||
|
HasStr2 = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
HasStr2 = true;
|
||||||
|
Str2 = TmpStr.str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n",
|
||||||
|
FuncName.c_str(), Str1P, Str1P->getName().str().c_str(),
|
||||||
|
Str1.c_str(), HasStr1 == true ? "true" : "false", Str2P,
|
||||||
|
Str2P->getName().str().c_str(), Str2.c_str(),
|
||||||
|
HasStr2 == true ? "true" : "false");
|
||||||
|
|
||||||
|
// we handle the 2nd parameter first because of llvm memcpy
|
||||||
|
if (!HasStr2) {
|
||||||
|
|
||||||
|
auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
|
||||||
|
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
|
||||||
|
|
||||||
|
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
|
||||||
|
|
||||||
|
if (Var->hasInitializer()) {
|
||||||
|
|
||||||
|
if (auto *Array =
|
||||||
|
dyn_cast<ConstantDataArray>(Var->getInitializer())) {
|
||||||
|
|
||||||
|
HasStr2 = true;
|
||||||
|
Str2 = Array->getAsString().str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// for the internal memcpy routine we only care for the second
|
||||||
|
// parameter and are not reporting anything.
|
||||||
|
if (isIntMemcpy == true) {
|
||||||
|
|
||||||
|
if (HasStr2 == true) {
|
||||||
|
|
||||||
|
Value * op2 = callInst->getArgOperand(2);
|
||||||
|
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
|
||||||
|
if (ilen) {
|
||||||
|
|
||||||
|
uint64_t literalLength = Str2.size();
|
||||||
|
uint64_t optLength = ilen->getZExtValue();
|
||||||
|
if (literalLength + 1 == optLength) {
|
||||||
|
|
||||||
|
Str2.append("\0", 1); // add null byte
|
||||||
|
addedNull = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
valueMap[Str1P] = new std::string(Str2);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(), Str1P);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neither a literal nor a global variable?
|
||||||
|
// maybe it is a local variable that we saved
|
||||||
|
if (!HasStr2) {
|
||||||
|
|
||||||
|
std::string *strng = valueMap[Str2P];
|
||||||
|
if (strng && !strng->empty()) {
|
||||||
|
|
||||||
|
Str2 = *strng;
|
||||||
|
HasStr2 = true;
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Filled2: %s for %p\n", strng->c_str(), Str2P);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasStr1) {
|
||||||
|
|
||||||
|
auto Ptr = dyn_cast<ConstantExpr>(Str1P);
|
||||||
|
|
||||||
|
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
|
||||||
|
|
||||||
|
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
|
||||||
|
|
||||||
|
if (Var->hasInitializer()) {
|
||||||
|
|
||||||
|
if (auto *Array =
|
||||||
|
dyn_cast<ConstantDataArray>(Var->getInitializer())) {
|
||||||
|
|
||||||
|
HasStr1 = true;
|
||||||
|
Str1 = Array->getAsString().str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neither a literal nor a global variable?
|
||||||
|
// maybe it is a local variable that we saved
|
||||||
|
if (!HasStr1) {
|
||||||
|
|
||||||
|
std::string *strng = valueMap[Str1P];
|
||||||
|
if (strng && !strng->empty()) {
|
||||||
|
|
||||||
|
Str1 = *strng;
|
||||||
|
HasStr1 = true;
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Filled1: %s for %p\n", strng->c_str(), Str1P);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle cases of one string is const, one string is variable */
|
||||||
|
if (!(HasStr1 ^ HasStr2)) continue;
|
||||||
|
|
||||||
|
std::string thestring;
|
||||||
|
|
||||||
|
if (HasStr1)
|
||||||
|
thestring = Str1;
|
||||||
|
else
|
||||||
|
thestring = Str2;
|
||||||
|
|
||||||
|
optLen = thestring.length();
|
||||||
|
|
||||||
|
if (isMemcmp || isStrncmp || isStrncasecmp) {
|
||||||
|
|
||||||
|
Value * op2 = callInst->getArgOperand(2);
|
||||||
|
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
|
||||||
|
if (ilen) {
|
||||||
|
|
||||||
|
uint64_t literalLength = optLen;
|
||||||
|
optLen = ilen->getZExtValue();
|
||||||
|
if (literalLength + 1 == optLen) { // add null byte
|
||||||
|
thestring.append("\0", 1);
|
||||||
|
addedNull = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// add null byte if this is a string compare function and a null
|
||||||
|
// was not already added
|
||||||
|
if (!isMemcmp) {
|
||||||
|
|
||||||
|
if (addedNull == false) {
|
||||||
|
|
||||||
|
thestring.append("\0", 1); // add null byte
|
||||||
|
optLen++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure we do not have garbage
|
||||||
|
size_t offset = thestring.find('\0', 0);
|
||||||
|
if (offset + 1 < optLen) optLen = offset + 1;
|
||||||
|
thestring = thestring.substr(0, optLen);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// we take the longer string, even if the compare was to a
|
||||||
|
// shorter part. Note that depending on the optimizer of the
|
||||||
|
// compiler this can be wrong, but it is more likely that this
|
||||||
|
// is helping the fuzzer
|
||||||
|
if (optLen != thestring.length()) optLen = thestring.length();
|
||||||
|
if (optLen > MAX_AUTO_EXTRA) optLen = MAX_AUTO_EXTRA;
|
||||||
|
if (optLen < 3) // too short? skip
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ptr = (char *)thestring.c_str();
|
||||||
|
|
||||||
|
dict2file(fd, (u8 *)ptr, optLen);
|
||||||
|
found++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* Say something nice. */
|
||||||
|
|
||||||
|
if (!be_quiet) {
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
OKF("No entries for a dictionary found.");
|
||||||
|
else
|
||||||
|
OKF("Wrote %d entries to the dictionary file.\n", found);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char AFLdict2filePass::ID = 0;
|
||||||
|
|
||||||
|
static void registerAFLdict2filePass(const PassManagerBuilder &,
|
||||||
|
legacy::PassManagerBase &PM) {
|
||||||
|
|
||||||
|
PM.add(new AFLdict2filePass());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterPass<AFLdict2filePass> X("afl-dict2file",
|
||||||
|
"afl++ dict2file instrumentation pass",
|
||||||
|
false, false);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterAFLdict2filePass(
|
||||||
|
PassManagerBuilder::EP_OptimizerLast, registerAFLdict2filePass);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterAFLdict2filePass0(
|
||||||
|
PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLdict2filePass);
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
all:
|
|
||||||
@gmake all || echo please install GNUmake
|
|
@ -1,25 +0,0 @@
|
|||||||
# InsTrim
|
|
||||||
|
|
||||||
InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
InsTrim uses CFG and markers to instrument just what is necessary in the
|
|
||||||
binary in llvm_mode. It is about 10-15% faster without disadvantages.
|
|
||||||
It requires at least llvm version 3.8.0.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Set the environment variable `AFL_LLVM_INSTRUMENT=CFG` or `AFL_LLVM_INSTRIM=1`
|
|
||||||
during compilation of the target.
|
|
||||||
|
|
||||||
There is also an advanced mode which instruments loops in a way so that
|
|
||||||
afl-fuzz can see which loop path has been selected but not being able to
|
|
||||||
see how often the loop has been rerun.
|
|
||||||
This again is a tradeoff for speed for less path information.
|
|
||||||
To enable this mode set `AFL_LLVM_INSTRIM_LOOPHEAD=1`.
|
|
||||||
|
|
||||||
## Background
|
|
||||||
|
|
||||||
The paper: [InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing]
|
|
||||||
(https://www.ndss-symposium.org/wp-content/uploads/2018/07/bar2018_14_Hsu_paper.pdf)
|
|
File diff suppressed because it is too large
Load Diff
1544
src/afl-cc.c
Normal file
1544
src/afl-cc.c
Normal file
File diff suppressed because it is too large
Load Diff
488
src/afl-gcc.c
488
src/afl-gcc.c
@ -1,488 +0,0 @@
|
|||||||
/*
|
|
||||||
american fuzzy lop++ - wrapper for GCC and clang
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
Originally written by Michal Zalewski
|
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
|
||||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at:
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
This program is a drop-in replacement for GCC or clang. The most common way
|
|
||||||
of using it is to pass the path to afl-gcc or afl-clang via CC when invoking
|
|
||||||
./configure.
|
|
||||||
|
|
||||||
(Of course, use CXX and point it to afl-g++ / afl-clang++ for C++ code.)
|
|
||||||
|
|
||||||
The wrapper needs to know the path to afl-as (renamed to 'as'). The default
|
|
||||||
is /usr/local/lib/afl/. A convenient way to specify alternative directories
|
|
||||||
would be to set AFL_PATH.
|
|
||||||
|
|
||||||
If AFL_HARDEN is set, the wrapper will compile the target app with various
|
|
||||||
hardening options that may help detect memory management issues more
|
|
||||||
reliably. You can also specify AFL_USE_ASAN to enable ASAN.
|
|
||||||
|
|
||||||
If you want to call a non-default compiler as a next step of the chain,
|
|
||||||
specify its location via AFL_CC or AFL_CXX.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define AFL_MAIN
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "alloc-inl.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static u8 * as_path; /* Path to the AFL 'as' wrapper */
|
|
||||||
static u8 **cc_params; /* Parameters passed to the real CC */
|
|
||||||
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
|
|
||||||
static u8 be_quiet, /* Quiet mode */
|
|
||||||
clang_mode; /* Invoked as afl-clang*? */
|
|
||||||
|
|
||||||
/* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
|
|
||||||
from argv[0]. If that fails, abort. */
|
|
||||||
|
|
||||||
static void find_as(u8 *argv0) {
|
|
||||||
|
|
||||||
u8 *afl_path = getenv("AFL_PATH");
|
|
||||||
u8 *slash, *tmp;
|
|
||||||
|
|
||||||
if (afl_path) {
|
|
||||||
|
|
||||||
tmp = alloc_printf("%s/as", afl_path);
|
|
||||||
|
|
||||||
if (!access(tmp, X_OK)) {
|
|
||||||
|
|
||||||
as_path = afl_path;
|
|
||||||
ck_free(tmp);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
slash = strrchr(argv0, '/');
|
|
||||||
|
|
||||||
if (slash) {
|
|
||||||
|
|
||||||
u8 *dir;
|
|
||||||
|
|
||||||
*slash = 0;
|
|
||||||
dir = ck_strdup(argv0);
|
|
||||||
*slash = '/';
|
|
||||||
|
|
||||||
tmp = alloc_printf("%s/afl-as", dir);
|
|
||||||
|
|
||||||
if (!access(tmp, X_OK)) {
|
|
||||||
|
|
||||||
as_path = dir;
|
|
||||||
ck_free(tmp);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
ck_free(dir);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!access(AFL_PATH "/as", X_OK)) {
|
|
||||||
|
|
||||||
as_path = AFL_PATH;
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
FATAL("Unable to find AFL wrapper binary for 'as'. Please set AFL_PATH");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy argv to cc_params, making the necessary edits. */
|
|
||||||
|
|
||||||
static void edit_params(u32 argc, char **argv) {
|
|
||||||
|
|
||||||
u8 fortify_set = 0, asan_set = 0;
|
|
||||||
u8 *name;
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
|
||||||
u8 m32_set = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
|
|
||||||
|
|
||||||
name = strrchr(argv[0], '/');
|
|
||||||
if (!name) {
|
|
||||||
|
|
||||||
name = argv[0];
|
|
||||||
|
|
||||||
/* This should never happen but fixes a scan-build warning */
|
|
||||||
if (!name) { FATAL("Empty argv set"); }
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
++name;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(name, "afl-clang", 9)) {
|
|
||||||
|
|
||||||
clang_mode = 1;
|
|
||||||
|
|
||||||
setenv(CLANG_ENV_VAR, "1", 1);
|
|
||||||
|
|
||||||
if (!strcmp(name, "afl-clang++")) {
|
|
||||||
|
|
||||||
u8 *alt_cxx = getenv("AFL_CXX");
|
|
||||||
cc_params[0] = alt_cxx && *alt_cxx ? alt_cxx : (u8 *)"clang++";
|
|
||||||
|
|
||||||
} else if (!strcmp(name, "afl-clang")) {
|
|
||||||
|
|
||||||
u8 *alt_cc = getenv("AFL_CC");
|
|
||||||
cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)"clang";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
fprintf(stderr, "Name of the binary: %s\n", argv[0]);
|
|
||||||
FATAL("Name of the binary is not a known name, expected afl-clang(++)");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* With GCJ and Eclipse installed, you can actually compile Java! The
|
|
||||||
instrumentation will work (amazingly). Alas, unhandled exceptions do
|
|
||||||
not call abort(), so afl-fuzz would need to be modified to equate
|
|
||||||
non-zero exit codes with crash conditions when working with Java
|
|
||||||
binaries. Meh. */
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
if (!strcmp(name, "afl-g++")) {
|
|
||||||
|
|
||||||
cc_params[0] = getenv("AFL_CXX");
|
|
||||||
|
|
||||||
} else if (!strcmp(name, "afl-gcj")) {
|
|
||||||
|
|
||||||
cc_params[0] = getenv("AFL_GCJ");
|
|
||||||
|
|
||||||
} else if (!strcmp(name, "afl-gcc")) {
|
|
||||||
|
|
||||||
cc_params[0] = getenv("AFL_CC");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
fprintf(stderr, "Name of the binary: %s\n", argv[0]);
|
|
||||||
FATAL("Name of the binary is not a known name, expected afl-gcc/g++/gcj");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cc_params[0]) {
|
|
||||||
|
|
||||||
SAYF("\n" cLRD "[-] " cRST
|
|
||||||
"On Apple systems, 'gcc' is usually just a wrapper for clang. "
|
|
||||||
"Please use the\n"
|
|
||||||
" 'afl-clang' utility instead of 'afl-gcc'. If you really have "
|
|
||||||
"GCC installed,\n"
|
|
||||||
" set AFL_CC or AFL_CXX to specify the correct path to that "
|
|
||||||
"compiler.\n");
|
|
||||||
|
|
||||||
FATAL("AFL_CC or AFL_CXX required on MacOS X");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
if (!strcmp(name, "afl-g++")) {
|
|
||||||
|
|
||||||
u8 *alt_cxx = getenv("AFL_CXX");
|
|
||||||
cc_params[0] = alt_cxx && *alt_cxx ? alt_cxx : (u8 *)"g++";
|
|
||||||
|
|
||||||
} else if (!strcmp(name, "afl-gcj")) {
|
|
||||||
|
|
||||||
u8 *alt_cc = getenv("AFL_GCJ");
|
|
||||||
cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)"gcj";
|
|
||||||
|
|
||||||
} else if (!strcmp(name, "afl-gcc")) {
|
|
||||||
|
|
||||||
u8 *alt_cc = getenv("AFL_CC");
|
|
||||||
cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)"gcc";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
fprintf(stderr, "Name of the binary: %s\n", argv[0]);
|
|
||||||
FATAL("Name of the binary is not a known name, expected afl-gcc/g++/gcj");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __APPLE__ */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (--argc) {
|
|
||||||
|
|
||||||
u8 *cur = *(++argv);
|
|
||||||
|
|
||||||
if (!strncmp(cur, "-B", 2)) {
|
|
||||||
|
|
||||||
if (!be_quiet) { WARNF("-B is already set, overriding"); }
|
|
||||||
|
|
||||||
if (!cur[2] && argc > 1) {
|
|
||||||
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-integrated-as")) { continue; }
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-pipe")) { continue; }
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
|
||||||
if (!strcmp(cur, "-m32")) m32_set = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!strcmp(cur, "-fsanitize=address") ||
|
|
||||||
!strcmp(cur, "-fsanitize=memory")) {
|
|
||||||
|
|
||||||
asan_set = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strstr(cur, "FORTIFY_SOURCE")) { fortify_set = 1; }
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = cur;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-B";
|
|
||||||
cc_params[cc_par_cnt++] = as_path;
|
|
||||||
|
|
||||||
if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
|
|
||||||
|
|
||||||
if (getenv("AFL_HARDEN")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fstack-protector-all";
|
|
||||||
|
|
||||||
if (!fortify_set) { cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asan_set) {
|
|
||||||
|
|
||||||
/* Pass this on to afl-as to adjust map density. */
|
|
||||||
|
|
||||||
setenv("AFL_USE_ASAN", "1", 1);
|
|
||||||
|
|
||||||
} else if (getenv("AFL_USE_ASAN")) {
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_MSAN")) {
|
|
||||||
|
|
||||||
FATAL("ASAN and MSAN are mutually exclusive");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_HARDEN")) {
|
|
||||||
|
|
||||||
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize=address";
|
|
||||||
|
|
||||||
} else if (getenv("AFL_USE_MSAN")) {
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_ASAN")) {
|
|
||||||
|
|
||||||
FATAL("ASAN and MSAN are mutually exclusive");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_HARDEN")) {
|
|
||||||
|
|
||||||
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize=memory";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_USE_UBSAN")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize=undefined";
|
|
||||||
cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(USEMMAP) && !defined(__HAIKU__)
|
|
||||||
cc_params[cc_par_cnt++] = "-lrt";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!getenv("AFL_DONT_OPTIMIZE")) {
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
|
||||||
|
|
||||||
/* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself
|
|
||||||
works OK. This has nothing to do with us, but let's avoid triggering
|
|
||||||
that bug. */
|
|
||||||
|
|
||||||
if (!clang_mode || !m32_set) cc_params[cc_par_cnt++] = "-g";
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-g";
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-O3";
|
|
||||||
cc_params[cc_par_cnt++] = "-funroll-loops";
|
|
||||||
|
|
||||||
/* Two indicators that you're building for fuzzing; one of them is
|
|
||||||
AFL-specific, the other is shared with libfuzzer. */
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
|
|
||||||
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_NO_BUILTIN")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt] = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main entry point */
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
|
|
||||||
char *env_info =
|
|
||||||
"Environment variables used by afl-gcc:\n"
|
|
||||||
"AFL_CC: path to the C compiler to use\n"
|
|
||||||
"AFL_CXX: path to the C++ compiler to use\n"
|
|
||||||
"AFL_GCJ: path to the java compiler to use\n"
|
|
||||||
"AFL_PATH: path to the instrumenting assembler\n"
|
|
||||||
"AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
|
|
||||||
"AFL_NO_BUILTIN: compile for use with libtokencap.so\n"
|
|
||||||
"AFL_QUIET: suppress verbose output\n"
|
|
||||||
"AFL_CAL_FAST: speed up the initial calibration\n"
|
|
||||||
"AFL_HARDEN: adds code hardening to catch memory bugs\n"
|
|
||||||
"AFL_USE_ASAN: activate address sanitizer\n"
|
|
||||||
"AFL_USE_MSAN: activate memory sanitizer\n"
|
|
||||||
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
|
|
||||||
|
|
||||||
"\nEnvironment variables used by afl-as (called by afl-gcc):\n"
|
|
||||||
"AFL_AS: path to the assembler to use\n"
|
|
||||||
"TMPDIR: set the directory for temporary files of afl-as\n"
|
|
||||||
"TEMP: fall back path to directory for temporary files\n"
|
|
||||||
"TMP: fall back path to directory for temporary files\n"
|
|
||||||
"AFL_INST_RATIO: percentage of branches to instrument\n"
|
|
||||||
"AFL_QUIET: suppress verbose output\n"
|
|
||||||
"AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n"
|
|
||||||
"AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n";
|
|
||||||
|
|
||||||
if (argc == 2 && strncmp(argv[1], "-h", 2) == 0) {
|
|
||||||
|
|
||||||
printf("afl-cc" VERSION " by Michal Zalewski\n\n");
|
|
||||||
printf("%s \n\n", argv[0]);
|
|
||||||
printf("afl-gcc has no command line options\n\n%s\n", env_info);
|
|
||||||
printf(
|
|
||||||
"NOTE: afl-gcc is deprecated, llvm_mode is much faster and has more "
|
|
||||||
"options\n");
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
|
|
||||||
|
|
||||||
SAYF(cCYA "afl-cc" VERSION cRST " by Michal Zalewski\n");
|
|
||||||
SAYF(cYEL "[!] " cBRI "NOTE: " cRST
|
|
||||||
"afl-gcc is deprecated, llvm_mode is much faster and has more "
|
|
||||||
"options\n");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
be_quiet = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
|
|
||||||
SAYF(
|
|
||||||
"\n"
|
|
||||||
"This is a helper application for afl-fuzz. It serves as a drop-in "
|
|
||||||
"replacement\n"
|
|
||||||
"for gcc or clang, letting you recompile third-party code with the "
|
|
||||||
"required\n"
|
|
||||||
"runtime instrumentation. A common use pattern would be one of the "
|
|
||||||
"following:\n\n"
|
|
||||||
|
|
||||||
" CC=%s/afl-gcc ./configure\n"
|
|
||||||
" CXX=%s/afl-g++ ./configure\n\n%s"
|
|
||||||
|
|
||||||
,
|
|
||||||
BIN_PATH, BIN_PATH, env_info);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *ptr;
|
|
||||||
if (!be_quiet &&
|
|
||||||
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
|
|
||||||
|
|
||||||
u32 map_size = atoi(ptr);
|
|
||||||
if (map_size != MAP_SIZE) {
|
|
||||||
|
|
||||||
WARNF("AFL_MAP_SIZE is not supported by afl-gcc");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
find_as(argv[0]);
|
|
||||||
|
|
||||||
edit_params(argc, argv);
|
|
||||||
|
|
||||||
execvp(cc_params[0], (char **)cc_params);
|
|
||||||
|
|
||||||
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Reference in New Issue
Block a user