mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 19:08:08 +00:00
remove afl-gcc/afl-clang
This commit is contained in:
38
GNUmakefile
38
GNUmakefile
@ -30,12 +30,10 @@ INCLUDE_PATH = $(PREFIX)/include/afl
|
||||
PROGNAME = afl
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
# PROGS intentionally omit afl-as, which gets installed elsewhere.
|
||||
|
||||
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
|
||||
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-addseeds afl-system-config afl-persistent-config afl-cc
|
||||
HEADERS = include/afl-as.h include/afl-fuzz.h include/afl-mutations.h include/afl-persistent-replay.h include/afl-prealloc.h include/afl-record-compat.h include/alloc-inl.h include/android-ashmem.h include/cmplog.h include/common.h include/config.h include/coverage-32.h include/coverage-64.h include/debug.h include/envs.h include/forkserver.h include/hash.h include/list.h include/sharedmem.h include/snapshot-inl.h include/t1ha.h include/t1ha0_ia32aes_b.h include/t1ha_bits.h include/t1ha_selfcheck.h include/types.h include/xxhash.h
|
||||
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
|
||||
HEADERS = include/afl-fuzz.h include/afl-mutations.h include/afl-persistent-replay.h include/afl-prealloc.h include/afl-record-compat.h include/alloc-inl.h include/android-ashmem.h include/cmplog.h include/common.h include/config.h include/coverage-32.h include/coverage-64.h include/debug.h include/envs.h include/forkserver.h include/hash.h include/list.h include/sharedmem.h include/snapshot-inl.h include/t1ha.h include/t1ha0_ia32aes_b.h include/t1ha_bits.h include/t1ha_selfcheck.h include/types.h include/xxhash.h
|
||||
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8)
|
||||
ASAN_OPTIONS=detect_leaks=0
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
@ -327,10 +325,12 @@ ifdef TEST_MMAP
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_build all_done
|
||||
all: test_x86 test_shm test_python ready $(PROGS) llvm gcc_plugin test_build all_done
|
||||
-$(MAKE) -C utils/aflpp_driver
|
||||
@echo
|
||||
@echo
|
||||
@echo
|
||||
@echo
|
||||
@echo Build Summary:
|
||||
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
|
||||
@test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
|
||||
@ -339,6 +339,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
||||
endif
|
||||
@test -e afl-cc || echo "[-] AFL++ instrumentation compilers could not be built! Install llvm-VERSION-dev or gcc-VERSION-plugin-dev, see docs/INSTALL.md!"
|
||||
@echo
|
||||
|
||||
.PHONY: llvm
|
||||
@ -465,10 +466,6 @@ endif
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))"
|
||||
|
||||
afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
@ln -sf afl-as as
|
||||
|
||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
|
||||
@ -576,7 +573,7 @@ code-format:
|
||||
|
||||
.PHONY: test_build
|
||||
ifndef AFL_NO_X86
|
||||
test_build: afl-cc afl-gcc afl-as afl-showmap
|
||||
test_build: afl-cc afl-showmap
|
||||
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
|
||||
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
|
||||
-ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null
|
||||
@ -585,18 +582,18 @@ test_build: afl-cc afl-gcc afl-as afl-showmap
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc 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
|
||||
@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
|
||||
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
|
||||
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
|
||||
# @echo "[*] Testing the CC wrapper and its instrumentation output..."
|
||||
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-clang-fast test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-clang-fast failed"; exit 1 )
|
||||
# ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
# echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
# @rm -f test-instr
|
||||
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
|
||||
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-clang-fast does not seem to be behaving correctly!"; \
|
||||
# gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option." ) || \
|
||||
# ( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
|
||||
# @echo
|
||||
# @echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
|
||||
# @echo "[+] All right, the instrumentation of afl-clang-fast seems to be working!"
|
||||
else
|
||||
test_build: afl-cc afl-as afl-showmap
|
||||
test_build: afl-cc afl-showmap
|
||||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
|
||||
endif
|
||||
|
||||
@ -606,7 +603,8 @@ all_done: test_build
|
||||
@test -e cmplog-instructions-pass.so && echo "[+] LLVM mode for 'afl-cc' successfully built!" || echo "[-] LLVM mode for 'afl-cc' failed to build, likely you either don't have llvm installed, or you need to set LLVM_CONFIG, to point to e.g. llvm-config-11. See instrumentation/README.llvm.md how to do this. Highly recommended!"
|
||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc' failed to build, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc' failed to build, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
|
||||
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@test -e afl-cc && echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@test -e afl-cc || echo "[-] ERROR - neither afl-clang-fast or afl-gcc-fast could be compiled - YOU ARE MISSING PACKAGES! Read docs/INSTALL.md!"
|
||||
@if [ "$(SYS)" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD for fuzzing software not\nspecifically for MacOS.\n\n"; fi
|
||||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
@ -614,7 +612,7 @@ all_done: test_build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
|
||||
rm -rf $(PROGS) afl-fuzz-document as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
|
||||
-$(MAKE) -f GNUmakefile.llvm clean
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||
-$(MAKE) -C utils/libdislocator clean
|
||||
@ -831,8 +829,6 @@ endif
|
||||
install -m 644 $(HEADERS) $${DESTDIR}$(INCLUDE_PATH)
|
||||
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
|
||||
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
|
||||
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
|
||||
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
|
||||
@ -840,9 +836,9 @@ endif
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
|
||||
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-ld-lto afl-c* afl-lto*
|
||||
-cd $${DESTDIR}$(INCLUDE_PATH) && rm -f $(HEADERS:include/%=%)
|
||||
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt injections.dic
|
||||
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt injections.dic
|
||||
-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
|
||||
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
|
||||
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
|
||||
|
@ -45,14 +45,10 @@ fairly broad use of environment variables instead:
|
||||
make
|
||||
```
|
||||
|
||||
- Setting `AFL_AS`, `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
|
||||
compilation tools, rather than the default 'as', 'clang', or 'gcc' binaries
|
||||
- Setting `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
|
||||
compilation tools, rather than the default 'clang', or 'gcc' binaries
|
||||
in your `$PATH`.
|
||||
|
||||
- If you are a weird person that wants to compile and instrument asm text
|
||||
files, then use the `AFL_AS_FORCE_INSTRUMENT` variable:
|
||||
`AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo`
|
||||
|
||||
- Most AFL tools do not print any output if stdout/stderr are redirected. If
|
||||
you want to get the output into a file, then set the `AFL_DEBUG` environment
|
||||
variable. This is sadly necessary for various build processes which fail
|
||||
@ -83,17 +79,13 @@ fairly broad use of environment variables instead:
|
||||
Setting `AFL_INST_RATIO` to 0 is a valid choice. This will instrument only
|
||||
the transitions between function entry points, but not individual branches.
|
||||
|
||||
Note that this is an outdated variable. A few instances (e.g., afl-gcc)
|
||||
still support these, but state-of-the-art (e.g., LLVM LTO and LLVM PCGUARD)
|
||||
do not need this.
|
||||
Note that this is an outdated variable. Only LLVM CLASSIC pass can use this.
|
||||
|
||||
- `AFL_NO_BUILTIN` causes the compiler to generate code suitable for use with
|
||||
libtokencap.so (but perhaps running a bit slower than without the flag).
|
||||
|
||||
- `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
|
||||
One possible use of this is utils/clang_asm_normalize/, which lets you
|
||||
instrument hand-written assembly when compiling clang code by plugging a
|
||||
normalizer into the chain. (There is no equivalent feature for GCC.)
|
||||
- `AFL_PATH` can be used to point a directory that contains LLVM/GCC plugins
|
||||
for AFL++, AFL++'s runtime objects and QEMU/Frida support files.
|
||||
|
||||
- Setting `AFL_QUIET` will prevent afl-as and afl-cc banners from being
|
||||
displayed during compilation, in case you find them distracting.
|
||||
|
@ -6,20 +6,22 @@ QEMU 5.1 with laf-intel and Redqueen, FRIDA mode, unicorn mode, gcc plugin, full
|
||||
|
||||
## Features and instrumentation
|
||||
|
||||
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
|
||||
| ------------------------------|:--------:|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
|
||||
| Threadsafe counters [A] | | x(3) | | | | | x | |
|
||||
| NeverZero [B] | x86[_64] | x(1) | x | x | x | x | | |
|
||||
| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
|
||||
| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
|
||||
| CmpLog [E] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
|
||||
| Selective Instrumentation [F] | | x | x | x | x | | | |
|
||||
| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | |
|
||||
| Ngram prev_loc Coverage [H] | | x(6) | | | | | | |
|
||||
| Context Coverage [I] | | x(6) | | | | | | |
|
||||
| Auto Dictionary [J] | | x(7) | | | | | | |
|
||||
| Snapshot Support [K] | | (x)(8) | (x)(8) | | (x)(5) | | x | |
|
||||
| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | |
|
||||
Note that afl-gcc and afl-clang have been removed because their instrumentation is absolutely outdated.
|
||||
|
||||
| Feature/Instrumentation | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
|
||||
| ------------------------------|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
|
||||
| Threadsafe counters [A] | x(3) | | | | | x | |
|
||||
| NeverZero [B] | x(1) | x | x | x | x | | |
|
||||
| Persistent Mode [C] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
|
||||
| LAF-Intel / CompCov [D] | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
|
||||
| CmpLog [E] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
|
||||
| Selective Instrumentation [F] | x | x | x | x | | | |
|
||||
| Non-Colliding Coverage [G] | x(4) | | | (x)(5) | | | |
|
||||
| Ngram prev_loc Coverage [H] | x(6) | | | | | | |
|
||||
| Context Coverage [I] | x(6) | | | | | | |
|
||||
| Auto Dictionary [J] | x(7) | | | | | | |
|
||||
| Snapshot Support [K] | (x)(8) | (x)(8) | | (x)(5) | | x | |
|
||||
| Shared Memory Test cases [L] | x | x | x86[_64]/arm64 | x | x | x | |
|
||||
|
||||
## More information about features
|
||||
|
||||
@ -94,7 +96,7 @@ L. Faster fuzzing and less kernel syscall overhead by in-memory fuzz testcase
|
||||
|
||||
Among others, the following features and patches have been integrated:
|
||||
|
||||
* NeverZero patch for afl-gcc, instrumentation, QEMU mode and unicorn_mode which
|
||||
* NeverZero for llvm/gcc instrumentation, QEMU mode and unicorn_mode which
|
||||
prevents a wrapping map value to zero, increases coverage
|
||||
* Persistent mode, deferred forkserver and in-memory fuzzing for QEMU mode
|
||||
* Unicorn mode which allows fuzzing of binaries from completely different
|
||||
|
@ -200,6 +200,7 @@ have an x86_64 or arm64 binary that does not contain C++ exceptions and - if
|
||||
x86_64 - still has it's symbols and compiled with position independent code
|
||||
(PIC/PIE), then the RetroWrite solution might be for you.
|
||||
It decompiles to ASM files which can then be instrumented with afl-gcc.
|
||||
Note that afl-gcc is only present until AFL++ v4.21c and was subsequently removed as it is obsolete.
|
||||
|
||||
Binaries that are statically instrumented for fuzzing using RetroWrite are close
|
||||
in performance to compiler-instrumented binaries and outperform the QEMU-based
|
||||
|
@ -61,6 +61,8 @@ evaluation flow will help you to select the best possible.
|
||||
It is highly recommended to have the newest llvm version possible installed,
|
||||
anything below 9 is not recommended.
|
||||
|
||||
IMPORTANT NOTICE: afl-gcc/afl-clang have been removed from AFL++ as they are obsolete.
|
||||
|
||||
```
|
||||
+--------------------------------+
|
||||
| clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++)
|
||||
@ -84,7 +86,7 @@ anything below 9 is not recommended.
|
||||
| if not, or if you do not have a gcc with plugin support
|
||||
|
|
||||
v
|
||||
use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)
|
||||
GAME OVER! Install gcc-VERSION-plugin-dev or llvm-VERSION-dev
|
||||
```
|
||||
|
||||
Clickable README links for the chosen compiler:
|
||||
@ -92,14 +94,12 @@ Clickable README links for the chosen compiler:
|
||||
* [LTO mode - afl-clang-lto](../instrumentation/README.lto.md)
|
||||
* [LLVM mode - afl-clang-fast](../instrumentation/README.llvm.md)
|
||||
* [GCC_PLUGIN mode - afl-gcc-fast](../instrumentation/README.gcc_plugin.md)
|
||||
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own
|
||||
features
|
||||
|
||||
You can select the mode for the afl-cc compiler by one of the following methods:
|
||||
|
||||
* Using a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
||||
* Using a symlink to afl-cc:
|
||||
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
||||
afl-gcc-fast, afl-g++-fast (recommended!).
|
||||
afl-gcc-fast, afl-g++-fast.
|
||||
* Using the environment variable `AFL_CC_COMPILER` with `MODE`.
|
||||
* Passing --afl-`MODE` command line options to the compiler via
|
||||
`CFLAGS`/`CXXFLAGS`/`CPPFLAGS`.
|
||||
@ -108,8 +108,7 @@ You can select the mode for the afl-cc compiler by one of the following methods:
|
||||
|
||||
* LTO (afl-clang-lto*)
|
||||
* LLVM (afl-clang-fast*)
|
||||
* GCC_PLUGIN (afl-g*-fast) or GCC (afl-gcc/afl-g++)
|
||||
* CLANG(afl-clang/afl-clang++)
|
||||
* GCC_PLUGIN (afl-g*-fast)
|
||||
|
||||
Because no AFL++ specific command-line options are accepted (beside the
|
||||
--afl-MODE command), the compile-time tools make fairly broad use of environment
|
||||
|
775
include/afl-as.h
775
include/afl-as.h
@ -1,775 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop++ - injectable parts
|
||||
---------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 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:
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
This file houses the assembly-level instrumentation injected into fuzzed
|
||||
programs. The instrumentation stores XORed pairs of data: identifiers of the
|
||||
currently executing branch and the one that executed immediately before.
|
||||
|
||||
TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++
|
||||
|
||||
The code is designed for 32-bit and 64-bit x86 systems. Both modes should
|
||||
work everywhere except for Apple systems. Apple does relocations differently
|
||||
from everybody else, so since their OSes have been 64-bit for a longer while,
|
||||
I didn't go through the mental effort of porting the 32-bit code.
|
||||
|
||||
In principle, similar code should be easy to inject into any well-behaved
|
||||
binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural
|
||||
targets for instrumentation, and should offer comparable probe density.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HAVE_AFL_AS_H
|
||||
#define _HAVE_AFL_AS_H
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
|
||||
/*
|
||||
------------------
|
||||
Performances notes
|
||||
------------------
|
||||
|
||||
Contributions to make this code faster are appreciated! Here are some
|
||||
rough notes that may help with the task:
|
||||
|
||||
- Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are
|
||||
really worth optimizing; the setup / fork server stuff matters a lot less
|
||||
and should be mostly just kept readable.
|
||||
|
||||
- We're aiming for modern CPUs with out-of-order execution and large
|
||||
pipelines; the code is mostly follows intuitive, human-readable
|
||||
instruction ordering, because "textbook" manual reorderings make no
|
||||
substantial difference.
|
||||
|
||||
- Interestingly, instrumented execution isn't a lot faster if we store a
|
||||
variable pointer to the setup, log, or return routine and then do a reg
|
||||
call from within trampoline_fmt. It does speed up non-instrumented
|
||||
execution quite a bit, though, since that path just becomes
|
||||
push-call-ret-pop.
|
||||
|
||||
- There is also not a whole lot to be gained by doing SHM attach at a
|
||||
fixed address instead of retrieving __afl_area_ptr. Although it allows us
|
||||
to have a shorter log routine inserted for conditional jumps and jump
|
||||
labels (for a ~10% perf gain), there is a risk of bumping into other
|
||||
allocations created by the program or by tools such as ASAN.
|
||||
|
||||
- popf is *awfully* slow, which is why we're doing the lahf / sahf +
|
||||
overflow test trick. Unfortunately, this forces us to taint eax / rax, but
|
||||
this dependency on a commonly-used register still beats the alternative of
|
||||
using pushf / popf.
|
||||
|
||||
One possible optimization is to avoid touching flags by using a circular
|
||||
buffer that stores just a sequence of current locations, with the XOR stuff
|
||||
happening offline. Alas, this doesn't seem to have a huge impact:
|
||||
|
||||
https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ
|
||||
|
||||
- Preforking one child a bit sooner, and then waiting for the "go" command
|
||||
from within the child, doesn't offer major performance gains; fork() seems
|
||||
to be relatively inexpensive these days. Preforking multiple children does
|
||||
help, but badly breaks the "~1 core per fuzzer" design, making it harder to
|
||||
scale up. Maybe there is some middle ground.
|
||||
|
||||
Perhaps of note: in the 64-bit version for all platforms except for Apple,
|
||||
the instrumentation is done slightly differently than on 32-bit, with
|
||||
__afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm),
|
||||
rather than global (.comm). This is to avoid GOTRELPC lookups in the critical
|
||||
code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to
|
||||
work; simple relocations between .bss and .text won't work on most 64-bit
|
||||
platforms in such a case.
|
||||
|
||||
(Fun fact: on Apple systems, .lcomm can segfault the linker.)
|
||||
|
||||
The side effect is that state transitions are measured in a somewhat
|
||||
different way, with previous tuple being recorded separately within the scope
|
||||
of every .c file. This should have no impact in any practical sense.
|
||||
|
||||
Another side effect of this design is that getenv() will be called once per
|
||||
every .o file when running in non-instrumented mode; and since getenv() tends
|
||||
to be optimized in funny ways, we need to be very careful to save every
|
||||
oddball register it may touch.
|
||||
|
||||
*/
|
||||
|
||||
static const u8 *trampoline_fmt_32 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL TRAMPOLINE (32-BIT) --- */\n"
|
||||
"\n"
|
||||
".align 4\n"
|
||||
"\n"
|
||||
"leal -16(%%esp), %%esp\n"
|
||||
"movl %%edi, 0(%%esp)\n"
|
||||
"movl %%edx, 4(%%esp)\n"
|
||||
"movl %%ecx, 8(%%esp)\n"
|
||||
"movl %%eax, 12(%%esp)\n"
|
||||
"movl $0x%08x, %%ecx\n"
|
||||
"call __afl_maybe_log\n"
|
||||
"movl 12(%%esp), %%eax\n"
|
||||
"movl 8(%%esp), %%ecx\n"
|
||||
"movl 4(%%esp), %%edx\n"
|
||||
"movl 0(%%esp), %%edi\n"
|
||||
"leal 16(%%esp), %%esp\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
static const u8 *trampoline_fmt_64 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL TRAMPOLINE (64-BIT) --- */\n"
|
||||
"\n"
|
||||
".align 4\n"
|
||||
"\n"
|
||||
"leaq -(128+24)(%%rsp), %%rsp\n"
|
||||
"movq %%rdx, 0(%%rsp)\n"
|
||||
"movq %%rcx, 8(%%rsp)\n"
|
||||
"movq %%rax, 16(%%rsp)\n"
|
||||
"movq $0x%08x, %%rcx\n"
|
||||
"call __afl_maybe_log\n"
|
||||
"movq 16(%%rsp), %%rax\n"
|
||||
"movq 8(%%rsp), %%rcx\n"
|
||||
"movq 0(%%rsp), %%rdx\n"
|
||||
"leaq (128+24)(%%rsp), %%rsp\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
static const u8 *main_payload_32 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n"
|
||||
"\n"
|
||||
".text\n"
|
||||
".att_syntax\n"
|
||||
".code32\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
|
||||
"__afl_maybe_log:\n"
|
||||
"\n"
|
||||
" lahf\n"
|
||||
" seto %al\n"
|
||||
"\n"
|
||||
" /* Check if SHM region is already mapped. */\n"
|
||||
"\n"
|
||||
" movl __afl_area_ptr, %edx\n"
|
||||
" testl %edx, %edx\n"
|
||||
" je __afl_setup\n"
|
||||
"\n"
|
||||
"__afl_store:\n"
|
||||
"\n"
|
||||
" /* Calculate and store hit for the code location specified in ecx. There\n"
|
||||
" is a double-XOR way of doing this without tainting another register,\n"
|
||||
" and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n"
|
||||
"\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" movl __afl_prev_loc, %edi\n"
|
||||
" xorl %ecx, %edi\n"
|
||||
" shrl $1, %ecx\n"
|
||||
" movl %ecx, __afl_prev_loc\n"
|
||||
#else
|
||||
" movl %ecx, %edi\n"
|
||||
#endif /* ^!COVERAGE_ONLY */
|
||||
"\n"
|
||||
#ifdef SKIP_COUNTS
|
||||
" orb $1, (%edx, %edi, 1)\n"
|
||||
#else
|
||||
" addb $1, (%edx, %edi, 1)\n"
|
||||
" adcb $0, (%edx, %edi, 1)\n" // never zero counter implementation. slightly better path discovery and little performance impact
|
||||
#endif /* ^SKIP_COUNTS */
|
||||
"\n"
|
||||
"__afl_return:\n"
|
||||
"\n"
|
||||
" addb $127, %al\n"
|
||||
" sahf\n"
|
||||
" ret\n"
|
||||
"\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
"__afl_setup:\n"
|
||||
"\n"
|
||||
" /* Do not retry setup if we had previous failures. */\n"
|
||||
"\n"
|
||||
" cmpb $0, __afl_setup_failure\n"
|
||||
" jne __afl_return\n"
|
||||
"\n"
|
||||
" /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n"
|
||||
" We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n"
|
||||
" will notice this early in the game. */\n"
|
||||
"\n"
|
||||
" pushl %eax\n"
|
||||
" pushl %ecx\n"
|
||||
"\n"
|
||||
" pushl $.AFL_SHM_ENV\n"
|
||||
" call getenv\n"
|
||||
" addl $4, %esp\n"
|
||||
"\n"
|
||||
" testl %eax, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#ifdef USEMMAP
|
||||
" pushl $384 /* shm_open mode 0600 */\n"
|
||||
" pushl $2 /* flags O_RDWR */\n"
|
||||
" pushl %eax /* SHM file path */\n"
|
||||
" call shm_open\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $-1, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
" pushl $0 /* mmap off */\n"
|
||||
" pushl %eax /* shm fd */\n"
|
||||
" pushl $1 /* mmap flags */\n"
|
||||
" pushl $3 /* mmap prot */\n"
|
||||
" pushl $"STRINGIFY(MAP_SIZE)" /* mmap len */\n"
|
||||
" pushl $0 /* mmap addr */\n"
|
||||
" call mmap\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $-1, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#else
|
||||
" pushl %eax\n"
|
||||
" call atoi\n"
|
||||
" addl $4, %esp\n"
|
||||
"\n"
|
||||
" pushl $0 /* shmat flags */\n"
|
||||
" pushl $0 /* requested addr */\n"
|
||||
" pushl %eax /* SHM ID */\n"
|
||||
" call shmat\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $-1, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#endif
|
||||
" movb $1, (%eax)\n"
|
||||
" /* Store the address of the SHM region. */\n"
|
||||
"\n"
|
||||
" movl %eax, __afl_area_ptr\n"
|
||||
" movl %eax, %edx\n"
|
||||
"\n"
|
||||
" popl %ecx\n"
|
||||
" popl %eax\n"
|
||||
"\n"
|
||||
"__afl_forkserver:\n"
|
||||
"\n"
|
||||
" /* Enter the fork server mode to avoid the overhead of execve() calls. */\n"
|
||||
"\n"
|
||||
" pushl %eax\n"
|
||||
" pushl %ecx\n"
|
||||
" pushl %edx\n"
|
||||
"\n"
|
||||
" /* Phone home and tell the parent that we're OK. (Note that signals with\n"
|
||||
" no SA_RESTART will mess it up). If this fails, assume that the fd is\n"
|
||||
" closed because we were execve()d from an instrumented binary, or because\n"
|
||||
" the parent doesn't want to use the fork server. */\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_temp /* data */\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
|
||||
" call write\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $4, %eax\n"
|
||||
" jne __afl_fork_resume\n"
|
||||
"\n"
|
||||
"__afl_fork_wait_loop:\n"
|
||||
"\n"
|
||||
" /* Wait for parent by reading from the pipe. Abort if read fails. */\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_temp /* data */\n"
|
||||
" pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n"
|
||||
" call read\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $4, %eax\n"
|
||||
" jne __afl_die\n"
|
||||
"\n"
|
||||
" /* Once woken up, create a clone of our process. This is an excellent use\n"
|
||||
" case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n"
|
||||
" caches getpid() results and offers no way to update the value, breaking\n"
|
||||
" abort(), raise(), and a bunch of other things :-( */\n"
|
||||
"\n"
|
||||
" call fork\n"
|
||||
"\n"
|
||||
" cmpl $0, %eax\n"
|
||||
" jl __afl_die\n"
|
||||
" je __afl_fork_resume\n"
|
||||
"\n"
|
||||
" /* In parent process: write PID to pipe, then wait for child. */\n"
|
||||
"\n"
|
||||
" movl %eax, __afl_fork_pid\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_fork_pid /* data */\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
|
||||
" call write\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" pushl $0 /* no flags */\n"
|
||||
" pushl $__afl_temp /* status */\n"
|
||||
" pushl __afl_fork_pid /* PID */\n"
|
||||
" call waitpid\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $0, %eax\n"
|
||||
" jle __afl_die\n"
|
||||
"\n"
|
||||
" /* Relay wait status to pipe, then loop back. */\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_temp /* data */\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
|
||||
" call write\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" jmp __afl_fork_wait_loop\n"
|
||||
"\n"
|
||||
"__afl_fork_resume:\n"
|
||||
"\n"
|
||||
" /* In child process: close fds, resume execution. */\n"
|
||||
"\n"
|
||||
" pushl $" STRINGIFY(FORKSRV_FD) "\n"
|
||||
" call close\n"
|
||||
"\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n"
|
||||
" call close\n"
|
||||
"\n"
|
||||
" addl $8, %esp\n"
|
||||
"\n"
|
||||
" popl %edx\n"
|
||||
" popl %ecx\n"
|
||||
" popl %eax\n"
|
||||
" jmp __afl_store\n"
|
||||
"\n"
|
||||
"__afl_die:\n"
|
||||
"\n"
|
||||
" xorl %eax, %eax\n"
|
||||
" call _exit\n"
|
||||
"\n"
|
||||
"__afl_setup_abort:\n"
|
||||
"\n"
|
||||
" /* Record setup failure so that we don't keep calling\n"
|
||||
" shmget() / shmat() over and over again. */\n"
|
||||
"\n"
|
||||
" incb __afl_setup_failure\n"
|
||||
" popl %ecx\n"
|
||||
" popl %eax\n"
|
||||
" jmp __afl_return\n"
|
||||
"\n"
|
||||
".AFL_VARS:\n"
|
||||
"\n"
|
||||
" .comm __afl_area_ptr, 4, 32\n"
|
||||
" .comm __afl_setup_failure, 1, 32\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" .comm __afl_prev_loc, 4, 32\n"
|
||||
#endif /* !COVERAGE_ONLY */
|
||||
" .comm __afl_final_loc, 4, 32\n"
|
||||
" .comm __afl_fork_pid, 4, 32\n"
|
||||
" .comm __afl_temp, 4, 32\n"
|
||||
"\n"
|
||||
".AFL_SHM_ENV:\n"
|
||||
" .asciz \"" SHM_ENV_VAR "\"\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
/* The OpenBSD hack is due to lahf and sahf not being recognized by some
|
||||
versions of binutils: https://marc.info/?l=openbsd-cvs&m=141636589924400
|
||||
|
||||
The Apple code is a bit different when calling libc functions because
|
||||
they are doing relocations differently from everybody else. We also need
|
||||
to work around the crash issue with .lcomm and the fact that they don't
|
||||
recognize .string. */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define CALL_L64(str) "call _" str "\n"
|
||||
#else
|
||||
#define CALL_L64(str) "call " str "@PLT\n"
|
||||
#endif /* ^__APPLE__ */
|
||||
|
||||
static const u8 *main_payload_64 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n"
|
||||
"\n"
|
||||
".text\n"
|
||||
".att_syntax\n"
|
||||
".code64\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
"__afl_maybe_log:\n"
|
||||
"\n"
|
||||
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9))
|
||||
" .byte 0x9f /* lahf */\n"
|
||||
#else
|
||||
" lahf\n"
|
||||
#endif /* ^__OpenBSD__, etc */
|
||||
" seto %al\n"
|
||||
"\n"
|
||||
" /* Check if SHM region is already mapped. */\n"
|
||||
"\n"
|
||||
" movq __afl_area_ptr(%rip), %rdx\n"
|
||||
" testq %rdx, %rdx\n"
|
||||
" je __afl_setup\n"
|
||||
"\n"
|
||||
"__afl_store:\n"
|
||||
"\n"
|
||||
" /* Calculate and store hit for the code location specified in rcx. */\n"
|
||||
"\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" xorq __afl_prev_loc(%rip), %rcx\n"
|
||||
" xorq %rcx, __afl_prev_loc(%rip)\n"
|
||||
" shrq $1, __afl_prev_loc(%rip)\n"
|
||||
#endif /* ^!COVERAGE_ONLY */
|
||||
"\n"
|
||||
#ifdef SKIP_COUNTS
|
||||
" orb $1, (%rdx, %rcx, 1)\n"
|
||||
#else
|
||||
" addb $1, (%rdx, %rcx, 1)\n"
|
||||
" adcb $0, (%rdx, %rcx, 1)\n" // never zero counter implementation. slightly better path discovery and little performance impact
|
||||
#endif /* ^SKIP_COUNTS */
|
||||
"\n"
|
||||
"__afl_return:\n"
|
||||
"\n"
|
||||
" addb $127, %al\n"
|
||||
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9))
|
||||
" .byte 0x9e /* sahf */\n"
|
||||
#else
|
||||
" sahf\n"
|
||||
#endif /* ^__OpenBSD__, etc */
|
||||
" ret\n"
|
||||
"\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
"__afl_setup:\n"
|
||||
"\n"
|
||||
" /* Do not retry setup if we had previous failures. */\n"
|
||||
"\n"
|
||||
" cmpb $0, __afl_setup_failure(%rip)\n"
|
||||
" jne __afl_return\n"
|
||||
"\n"
|
||||
" /* Check out if we have a global pointer on file. */\n"
|
||||
"\n"
|
||||
#ifndef __APPLE__
|
||||
" movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n"
|
||||
" movq (%rdx), %rdx\n"
|
||||
#else
|
||||
" movq __afl_global_area_ptr(%rip), %rdx\n"
|
||||
#endif /* !^__APPLE__ */
|
||||
" testq %rdx, %rdx\n"
|
||||
" je __afl_setup_first\n"
|
||||
"\n"
|
||||
" movq %rdx, __afl_area_ptr(%rip)\n"
|
||||
" jmp __afl_store\n"
|
||||
"\n"
|
||||
"__afl_setup_first:\n"
|
||||
"\n"
|
||||
" /* Save everything that is not yet saved and that may be touched by\n"
|
||||
" getenv() and several other libcalls we'll be relying on. */\n"
|
||||
"\n"
|
||||
" leaq -352(%rsp), %rsp\n"
|
||||
"\n"
|
||||
" movq %rax, 0(%rsp)\n"
|
||||
" movq %rcx, 8(%rsp)\n"
|
||||
" movq %rdi, 16(%rsp)\n"
|
||||
" movq %rsi, 32(%rsp)\n"
|
||||
" movq %r8, 40(%rsp)\n"
|
||||
" movq %r9, 48(%rsp)\n"
|
||||
" movq %r10, 56(%rsp)\n"
|
||||
" movq %r11, 64(%rsp)\n"
|
||||
"\n"
|
||||
" movq %xmm0, 96(%rsp)\n"
|
||||
" movq %xmm1, 112(%rsp)\n"
|
||||
" movq %xmm2, 128(%rsp)\n"
|
||||
" movq %xmm3, 144(%rsp)\n"
|
||||
" movq %xmm4, 160(%rsp)\n"
|
||||
" movq %xmm5, 176(%rsp)\n"
|
||||
" movq %xmm6, 192(%rsp)\n"
|
||||
" movq %xmm7, 208(%rsp)\n"
|
||||
" movq %xmm8, 224(%rsp)\n"
|
||||
" movq %xmm9, 240(%rsp)\n"
|
||||
" movq %xmm10, 256(%rsp)\n"
|
||||
" movq %xmm11, 272(%rsp)\n"
|
||||
" movq %xmm12, 288(%rsp)\n"
|
||||
" movq %xmm13, 304(%rsp)\n"
|
||||
" movq %xmm14, 320(%rsp)\n"
|
||||
" movq %xmm15, 336(%rsp)\n"
|
||||
"\n"
|
||||
" /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n"
|
||||
"\n"
|
||||
" /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n"
|
||||
" original stack ptr in the callee-saved r12. */\n"
|
||||
"\n"
|
||||
" pushq %r12\n"
|
||||
" movq %rsp, %r12\n"
|
||||
" subq $16, %rsp\n"
|
||||
" andq $0xfffffffffffffff0, %rsp\n"
|
||||
"\n"
|
||||
" leaq .AFL_SHM_ENV(%rip), %rdi\n"
|
||||
CALL_L64("getenv")
|
||||
"\n"
|
||||
" testq %rax, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#ifdef USEMMAP
|
||||
" movl $384, %edx /* shm_open mode 0600 */\n"
|
||||
" movl $2, %esi /* flags O_RDWR */\n"
|
||||
" movq %rax, %rdi /* SHM file path */\n"
|
||||
CALL_L64("shm_open")
|
||||
"\n"
|
||||
" cmpq $-1, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
" movl $0, %r9d\n"
|
||||
" movl %eax, %r8d\n"
|
||||
" movl $1, %ecx\n"
|
||||
" movl $3, %edx\n"
|
||||
" movl $"STRINGIFY(MAP_SIZE)", %esi\n"
|
||||
" movl $0, %edi\n"
|
||||
CALL_L64("mmap")
|
||||
"\n"
|
||||
" cmpq $-1, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#else
|
||||
" movq %rax, %rdi\n"
|
||||
CALL_L64("atoi")
|
||||
"\n"
|
||||
" xorq %rdx, %rdx /* shmat flags */\n"
|
||||
" xorq %rsi, %rsi /* requested addr */\n"
|
||||
" movq %rax, %rdi /* SHM ID */\n"
|
||||
CALL_L64("shmat")
|
||||
"\n"
|
||||
" cmpq $-1, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#endif
|
||||
" movb $1, (%rax)\n"
|
||||
" /* Store the address of the SHM region. */\n"
|
||||
"\n"
|
||||
" movq %rax, %rdx\n"
|
||||
" movq %rax, __afl_area_ptr(%rip)\n"
|
||||
"\n"
|
||||
#ifdef __APPLE__
|
||||
" movq %rax, __afl_global_area_ptr(%rip)\n"
|
||||
#else
|
||||
" movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n"
|
||||
" movq %rax, (%rdx)\n"
|
||||
#endif /* ^__APPLE__ */
|
||||
" movq %rax, %rdx\n"
|
||||
"\n"
|
||||
"__afl_forkserver:\n"
|
||||
"\n"
|
||||
" /* Enter the fork server mode to avoid the overhead of execve() calls. We\n"
|
||||
" push rdx (area ptr) twice to keep stack alignment neat. */\n"
|
||||
"\n"
|
||||
" pushq %rdx\n"
|
||||
" pushq %rdx\n"
|
||||
"\n"
|
||||
" /* Phone home and tell the parent that we're OK. (Note that signals with\n"
|
||||
" no SA_RESTART will mess it up). If this fails, assume that the fd is\n"
|
||||
" closed because we were execve()d from an instrumented binary, or because\n"
|
||||
" the parent doesn't want to use the fork server. */\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
|
||||
CALL_L64("write")
|
||||
"\n"
|
||||
" cmpq $4, %rax\n"
|
||||
" jne __afl_fork_resume\n"
|
||||
"\n"
|
||||
"__afl_fork_wait_loop:\n"
|
||||
"\n"
|
||||
" /* Wait for parent by reading from the pipe. Abort if read fails. */\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n"
|
||||
CALL_L64("read")
|
||||
" cmpq $4, %rax\n"
|
||||
" jne __afl_die\n"
|
||||
"\n"
|
||||
" /* Once woken up, create a clone of our process. This is an excellent use\n"
|
||||
" case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n"
|
||||
" caches getpid() results and offers no way to update the value, breaking\n"
|
||||
" abort(), raise(), and a bunch of other things :-( */\n"
|
||||
"\n"
|
||||
CALL_L64("fork")
|
||||
" cmpq $0, %rax\n"
|
||||
" jl __afl_die\n"
|
||||
" je __afl_fork_resume\n"
|
||||
"\n"
|
||||
" /* In parent process: write PID to pipe, then wait for child. */\n"
|
||||
"\n"
|
||||
" movl %eax, __afl_fork_pid(%rip)\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_fork_pid(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
|
||||
CALL_L64("write")
|
||||
"\n"
|
||||
" movq $0, %rdx /* no flags */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* status */\n"
|
||||
" movq __afl_fork_pid(%rip), %rdi /* PID */\n"
|
||||
CALL_L64("waitpid")
|
||||
" cmpq $0, %rax\n"
|
||||
" jle __afl_die\n"
|
||||
"\n"
|
||||
" /* Relay wait status to pipe, then loop back. */\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
|
||||
CALL_L64("write")
|
||||
"\n"
|
||||
" jmp __afl_fork_wait_loop\n"
|
||||
"\n"
|
||||
"__afl_fork_resume:\n"
|
||||
"\n"
|
||||
" /* In child process: close fds, resume execution. */\n"
|
||||
"\n"
|
||||
" movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n"
|
||||
CALL_L64("close")
|
||||
"\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n"
|
||||
CALL_L64("close")
|
||||
"\n"
|
||||
" popq %rdx\n"
|
||||
" popq %rdx\n"
|
||||
"\n"
|
||||
" movq %r12, %rsp\n"
|
||||
" popq %r12\n"
|
||||
"\n"
|
||||
" movq 0(%rsp), %rax\n"
|
||||
" movq 8(%rsp), %rcx\n"
|
||||
" movq 16(%rsp), %rdi\n"
|
||||
" movq 32(%rsp), %rsi\n"
|
||||
" movq 40(%rsp), %r8\n"
|
||||
" movq 48(%rsp), %r9\n"
|
||||
" movq 56(%rsp), %r10\n"
|
||||
" movq 64(%rsp), %r11\n"
|
||||
"\n"
|
||||
" movq 96(%rsp), %xmm0\n"
|
||||
" movq 112(%rsp), %xmm1\n"
|
||||
" movq 128(%rsp), %xmm2\n"
|
||||
" movq 144(%rsp), %xmm3\n"
|
||||
" movq 160(%rsp), %xmm4\n"
|
||||
" movq 176(%rsp), %xmm5\n"
|
||||
" movq 192(%rsp), %xmm6\n"
|
||||
" movq 208(%rsp), %xmm7\n"
|
||||
" movq 224(%rsp), %xmm8\n"
|
||||
" movq 240(%rsp), %xmm9\n"
|
||||
" movq 256(%rsp), %xmm10\n"
|
||||
" movq 272(%rsp), %xmm11\n"
|
||||
" movq 288(%rsp), %xmm12\n"
|
||||
" movq 304(%rsp), %xmm13\n"
|
||||
" movq 320(%rsp), %xmm14\n"
|
||||
" movq 336(%rsp), %xmm15\n"
|
||||
"\n"
|
||||
" leaq 352(%rsp), %rsp\n"
|
||||
"\n"
|
||||
" jmp __afl_store\n"
|
||||
"\n"
|
||||
"__afl_die:\n"
|
||||
"\n"
|
||||
" xorq %rax, %rax\n"
|
||||
CALL_L64("_exit")
|
||||
"\n"
|
||||
"__afl_setup_abort:\n"
|
||||
"\n"
|
||||
" /* Record setup failure so that we don't keep calling\n"
|
||||
" shmget() / shmat() over and over again. */\n"
|
||||
"\n"
|
||||
" incb __afl_setup_failure(%rip)\n"
|
||||
"\n"
|
||||
" movq %r12, %rsp\n"
|
||||
" popq %r12\n"
|
||||
"\n"
|
||||
" movq 0(%rsp), %rax\n"
|
||||
" movq 8(%rsp), %rcx\n"
|
||||
" movq 16(%rsp), %rdi\n"
|
||||
" movq 32(%rsp), %rsi\n"
|
||||
" movq 40(%rsp), %r8\n"
|
||||
" movq 48(%rsp), %r9\n"
|
||||
" movq 56(%rsp), %r10\n"
|
||||
" movq 64(%rsp), %r11\n"
|
||||
"\n"
|
||||
" movq 96(%rsp), %xmm0\n"
|
||||
" movq 112(%rsp), %xmm1\n"
|
||||
" movq 128(%rsp), %xmm2\n"
|
||||
" movq 144(%rsp), %xmm3\n"
|
||||
" movq 160(%rsp), %xmm4\n"
|
||||
" movq 176(%rsp), %xmm5\n"
|
||||
" movq 192(%rsp), %xmm6\n"
|
||||
" movq 208(%rsp), %xmm7\n"
|
||||
" movq 224(%rsp), %xmm8\n"
|
||||
" movq 240(%rsp), %xmm9\n"
|
||||
" movq 256(%rsp), %xmm10\n"
|
||||
" movq 272(%rsp), %xmm11\n"
|
||||
" movq 288(%rsp), %xmm12\n"
|
||||
" movq 304(%rsp), %xmm13\n"
|
||||
" movq 320(%rsp), %xmm14\n"
|
||||
" movq 336(%rsp), %xmm15\n"
|
||||
"\n"
|
||||
" leaq 352(%rsp), %rsp\n"
|
||||
"\n"
|
||||
" jmp __afl_return\n"
|
||||
"\n"
|
||||
".AFL_VARS:\n"
|
||||
"\n"
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
" .comm __afl_area_ptr, 8\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" .comm __afl_prev_loc, 8\n"
|
||||
#endif /* !COVERAGE_ONLY */
|
||||
" .comm __afl_fork_pid, 4\n"
|
||||
" .comm __afl_temp, 4\n"
|
||||
" .comm __afl_setup_failure, 1\n"
|
||||
|
||||
#else
|
||||
|
||||
" .lcomm __afl_area_ptr, 8\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" .lcomm __afl_prev_loc, 8\n"
|
||||
#endif /* !COVERAGE_ONLY */
|
||||
" .lcomm __afl_fork_pid, 4\n"
|
||||
" .lcomm __afl_temp, 4\n"
|
||||
" .lcomm __afl_setup_failure, 1\n"
|
||||
|
||||
#endif /* ^__APPLE__ */
|
||||
|
||||
" .comm __afl_global_area_ptr, 8, 8\n"
|
||||
"\n"
|
||||
".AFL_SHM_ENV:\n"
|
||||
" .asciz \"" SHM_ENV_VAR "\"\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
#endif /* !_HAVE_AFL_AS_H */
|
||||
|
@ -21,7 +21,7 @@ TL;DR:
|
||||
|
||||
The code in this directory allows to instrument programs for AFL++ using true
|
||||
compiler-level instrumentation, instead of the more crude assembly-level
|
||||
rewriting approach taken by afl-gcc and afl-clang. This has several interesting
|
||||
rewriting approach taken by obsolete afl-gcc and afl-clang. This has several interesting
|
||||
properties:
|
||||
|
||||
- The compiler can make many optimizations that are hard to pull off when
|
||||
@ -40,10 +40,6 @@ properties:
|
||||
will *not* work with LLVM (see [README.llvm.md](README.llvm.md) for an
|
||||
alternative).
|
||||
|
||||
Once this implementation is shown to be sufficiently robust and portable, it
|
||||
will probably replace afl-gcc. For now, it can be built separately and co-exists
|
||||
with the original code.
|
||||
|
||||
The idea and much of the implementation comes from Laszlo Szekeres.
|
||||
|
||||
## 2) How to use
|
||||
@ -77,7 +73,7 @@ standard operating mode of AFL++, e.g.:
|
||||
|
||||
Note: We also used `CXX` to set the C++ compiler to `afl-g++-fast` for C++ code.
|
||||
|
||||
The tool honors roughly the same environmental variables as `afl-gcc` (see
|
||||
The tool honors some environmental variables of `afl-clang-fast` (see
|
||||
[docs/env_variables.md](../docs/env_variables.md). This includes
|
||||
`AFL_INST_RATIO`, `AFL_USE_ASAN`, `AFL_HARDEN`, and `AFL_DONT_OPTIMIZE`.
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
This file describes two different mechanisms to selectively instrument only
|
||||
specific parts in the target.
|
||||
|
||||
Both mechanisms work for LLVM and GCC_PLUGIN, but not for afl-clang/afl-gcc.
|
||||
Both mechanisms work for LLVM and GCC_PLUGIN.
|
||||
|
||||
## 1) Description and purpose
|
||||
|
||||
|
@ -11,7 +11,7 @@ For the GCC-based instrumentation, see
|
||||
|
||||
The code in this directory allows you to instrument programs for AFL++ using
|
||||
true compiler-level instrumentation, instead of the more crude assembly-level
|
||||
rewriting approach taken by afl-gcc and afl-clang. This has several interesting
|
||||
rewriting approach taken by obsolete afl-gcc and afl-clang. This has several interesting
|
||||
properties:
|
||||
|
||||
- The compiler can make many optimizations that are hard to pull off when
|
||||
@ -32,10 +32,6 @@ properties:
|
||||
will *not* work with GCC (see ../gcc_plugin/ for an alternative once it is
|
||||
available).
|
||||
|
||||
Once this implementation is shown to be sufficiently robust and portable, it
|
||||
will probably replace afl-clang. For now, it can be built separately and
|
||||
co-exists with the original code.
|
||||
|
||||
The idea and much of the initial implementation came from Laszlo Szekeres.
|
||||
|
||||
## 2a) How to use this - short
|
||||
@ -105,7 +101,7 @@ 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 supports a lot of environmental variables(see
|
||||
[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 as it does not serve a good purpose with the more effective
|
||||
@ -255,10 +251,6 @@ low cost (one instruction per edge).
|
||||
(The alternative of saturated counters has been tested also and proved to be
|
||||
inferior in terms of path discovery.)
|
||||
|
||||
This is implemented in afl-gcc and afl-gcc-fast, however, for llvm_mode this is
|
||||
optional if multithread safe counters are selected or the llvm version is below
|
||||
9 - as there are severe performance costs in these cases.
|
||||
|
||||
If you want to enable this for llvm versions below 9 or thread safe counters,
|
||||
then set
|
||||
|
||||
|
@ -57,8 +57,8 @@ libtool: link: afl-clang-lto -g -O2 -Wall -W -o thumbnail thumbnail.o ../libtif
|
||||
afl-clang-lto++2.63d by Marc "vanHauser" Heuse <mh@mh-sec.de> in mode LTO
|
||||
afl-llvm-lto++2.63d by Marc "vanHauser" Heuse <mh@mh-sec.de>
|
||||
AUTODICTIONARY: 11 strings found
|
||||
[+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode).
|
||||
```
|
||||
[+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-clang-fast CLASSIC) (non-hardened mode).
|
||||
s```
|
||||
|
||||
## Getting LLVM 12+
|
||||
|
||||
@ -90,7 +90,7 @@ sudo make install
|
||||
|
||||
## How to use afl-clang-lto
|
||||
|
||||
Just use afl-clang-lto like you did with afl-clang-fast or afl-gcc.
|
||||
Just use afl-clang-lto like you did with afl-clang-fast.
|
||||
|
||||
Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST ->
|
||||
[README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov
|
||||
|
@ -124,7 +124,6 @@ will keep working normally when compiled with a tool other than afl-clang-fast/
|
||||
afl-clang-lto/afl-gcc-fast.
|
||||
|
||||
Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
|
||||
(afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
|
||||
and you should be all set!
|
||||
|
||||
## 4) Persistent mode
|
||||
|
@ -5,9 +5,6 @@
|
||||
Written by Laszlo Szekeres <lszekeres@google.com> and
|
||||
Michal Zalewski
|
||||
|
||||
LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
|
||||
from afl-as.c are Michal's fault.
|
||||
|
||||
Copyright 2015, 2016 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
|
||||
@ -17,10 +14,6 @@
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
This library is plugged into LLVM when invoking clang through afl-clang-fast.
|
||||
It tells the compiler to add code roughly equivalent to the bits discussed
|
||||
in ../afl-as.h.
|
||||
|
||||
*/
|
||||
|
||||
#define AFL_LLVM_PASS
|
||||
|
@ -6,9 +6,6 @@
|
||||
Adrian Herrera <adrian.herrera@anu.edu.au>,
|
||||
Michal Zalewski
|
||||
|
||||
LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
|
||||
from afl-as.c are Michal's fault.
|
||||
|
||||
NGRAM previous location coverage comes from Adrian Herrera.
|
||||
|
||||
Copyright 2015, 2016 Google Inc. All rights reserved.
|
||||
@ -20,10 +17,6 @@
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
This library is plugged into LLVM when invoking clang through afl-clang-fast.
|
||||
It tells the compiler to add code roughly equivalent to the bits discussed
|
||||
in ../afl-as.h.
|
||||
|
||||
*/
|
||||
|
||||
#define AFL_LLVM_PASS
|
||||
|
671
src/afl-as.c
671
src/afl-as.c
@ -1,671 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop++ - wrapper for GNU as
|
||||
-----------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 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:
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The sole purpose of this wrapper is to preprocess assembly files generated
|
||||
by GCC / clang and inject the instrumentation bits included from afl-as.h. It
|
||||
is automatically invoked by the toolchain when compiling programs using
|
||||
afl-gcc / afl-clang.
|
||||
|
||||
Note that it's an explicit non-goal to instrument hand-written assembly,
|
||||
be it in separate .s files or in __asm__ blocks. The only aspiration this
|
||||
utility has right now is to be able to skip them gracefully and allow the
|
||||
compilation process to continue.
|
||||
|
||||
That said, see utils/clang_asm_normalize/ for a solution that may
|
||||
allow clang users to make things work even with hand-crafted assembly. Just
|
||||
note that there is no equivalent for GCC.
|
||||
|
||||
*/
|
||||
|
||||
#define AFL_MAIN
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
#include "alloc-inl.h"
|
||||
|
||||
#include "afl-as.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static u8 **as_params; /* Parameters passed to the real 'as' */
|
||||
|
||||
static u8 *input_file; /* Originally specified input file */
|
||||
static u8 *modified_file; /* Instrumented file for the real 'as' */
|
||||
|
||||
static u8 be_quiet, /* Quiet mode (no stderr output) */
|
||||
clang_mode, /* Running in clang mode? */
|
||||
pass_thru, /* Just pass data through? */
|
||||
just_version, /* Just show version? */
|
||||
sanitizer; /* Using ASAN / MSAN */
|
||||
|
||||
static u32 inst_ratio = 100, /* Instrumentation probability (%) */
|
||||
as_par_cnt = 1; /* Number of params to 'as' */
|
||||
|
||||
/* If we don't find --32 or --64 in the command line, default to
|
||||
instrumentation for whichever mode we were compiled with. This is not
|
||||
perfect, but should do the trick for almost all use cases. */
|
||||
|
||||
#ifdef WORD_SIZE_64
|
||||
|
||||
static u8 use_64bit = 1;
|
||||
|
||||
#else
|
||||
|
||||
static u8 use_64bit = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
#error "Sorry, 32-bit Apple platforms are not supported."
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
/* Examine and modify parameters to pass to 'as'. Note that the file name
|
||||
is always the last parameter passed by GCC, so we exploit this property
|
||||
to keep the code simple. */
|
||||
|
||||
static void edit_params(int argc, char **argv) {
|
||||
|
||||
u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS");
|
||||
u32 i, input_index;
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
u8 use_clang_as = 0;
|
||||
|
||||
/* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work
|
||||
with the code generated by newer versions of clang that are hand-built
|
||||
by the user. See the thread here: https://goo.gl/HBWDtn.
|
||||
|
||||
To work around this, when using clang and running without AFL_AS
|
||||
specified, we will actually call 'clang -c' instead of 'as -q' to
|
||||
compile the assembly file.
|
||||
|
||||
The tools aren't cmdline-compatible, but at least for now, we can
|
||||
seemingly get away with this by making only very minor tweaks. Thanks
|
||||
to Nico Weber for the idea. */
|
||||
|
||||
if (clang_mode && !afl_as) {
|
||||
|
||||
use_clang_as = 1;
|
||||
|
||||
afl_as = getenv("AFL_CC");
|
||||
if (!afl_as) afl_as = getenv("AFL_CXX");
|
||||
if (!afl_as) afl_as = "clang";
|
||||
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/* Although this is not documented, GCC also uses TEMP and TMP when TMPDIR
|
||||
is not set. We need to check these non-standard variables to properly
|
||||
handle the pass_thru logic later on. */
|
||||
|
||||
if (!tmp_dir) { tmp_dir = getenv("TEMP"); }
|
||||
if (!tmp_dir) { tmp_dir = getenv("TMP"); }
|
||||
if (!tmp_dir) { tmp_dir = "/tmp"; }
|
||||
|
||||
as_params = ck_alloc((argc + 32) * sizeof(u8 *));
|
||||
if (unlikely((INT_MAX - 32) < argc || !as_params)) {
|
||||
|
||||
FATAL("Too many parameters passed to as");
|
||||
|
||||
}
|
||||
|
||||
as_params[0] = afl_as ? afl_as : (u8 *)"as";
|
||||
|
||||
as_params[argc] = 0;
|
||||
|
||||
/* Find the input file. It's usually located near the end.
|
||||
Assume there won't be any arguments referring to files after the input
|
||||
file, e.g. as input.s -o output.o */
|
||||
for (input_index = argc - 1; input_index > 0; input_index--) {
|
||||
|
||||
input_file = argv[input_index];
|
||||
/* Clang may add debug arguments after the input file. */
|
||||
if (strncmp(input_file, "-g", 2)) break;
|
||||
|
||||
}
|
||||
|
||||
if (input_index == 0)
|
||||
FATAL("Could not find input file (not called through afl-gcc?)");
|
||||
|
||||
for (i = 1; (s32)i < argc; i++) {
|
||||
|
||||
if (i == input_index) continue;
|
||||
|
||||
if (!strcmp(argv[i], "--64")) {
|
||||
|
||||
use_64bit = 1;
|
||||
|
||||
} else if (!strcmp(argv[i], "--32")) {
|
||||
|
||||
use_64bit = 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* The Apple case is a bit different... */
|
||||
|
||||
if (!strcmp(argv[i], "-arch") && i + 1 < (u32)argc) {
|
||||
|
||||
if (!strcmp(argv[i + 1], "x86_64"))
|
||||
use_64bit = 1;
|
||||
else if (!strcmp(argv[i + 1], "i386"))
|
||||
FATAL("Sorry, 32-bit Apple platforms are not supported.");
|
||||
|
||||
}
|
||||
|
||||
/* Strip options that set the preference for a particular upstream
|
||||
assembler in Xcode. */
|
||||
|
||||
if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q")))
|
||||
continue;
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
as_params[as_par_cnt++] = argv[i];
|
||||
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* When calling clang as the upstream assembler, append -c -x assembler
|
||||
and hope for the best. */
|
||||
|
||||
if (use_clang_as) {
|
||||
|
||||
as_params[as_par_cnt++] = "-c";
|
||||
as_params[as_par_cnt++] = "-x";
|
||||
as_params[as_par_cnt++] = "assembler";
|
||||
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
if (input_file[0] == '-') {
|
||||
|
||||
if (!strcmp(input_file + 1, "-version")) {
|
||||
|
||||
just_version = 1;
|
||||
modified_file = input_file;
|
||||
goto wrap_things_up;
|
||||
|
||||
}
|
||||
|
||||
if (input_file[1]) {
|
||||
|
||||
FATAL("Incorrect use (not called through afl-gcc?)");
|
||||
|
||||
} else {
|
||||
|
||||
input_file = NULL;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Check if this looks like a standard invocation as a part of an attempt
|
||||
to compile a program, rather than using gcc on an ad-hoc .s file in
|
||||
a format we may not understand. This works around an issue compiling
|
||||
NSS. */
|
||||
|
||||
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
|
||||
strncmp(input_file, "/var/tmp/", 9) &&
|
||||
strncmp(input_file, "/tmp/", 5) &&
|
||||
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) {
|
||||
|
||||
pass_thru = 1;
|
||||
|
||||
} else if (getenv("AFL_AS_FORCE_INSTRUMENT")) {
|
||||
|
||||
unsetenv("AFL_AS_FORCE_INSTRUMENT");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
modified_file = alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(),
|
||||
(u32)time(NULL), (u32)random());
|
||||
|
||||
wrap_things_up:
|
||||
|
||||
as_params[as_par_cnt++] = modified_file;
|
||||
as_params[as_par_cnt] = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Process input file, generate modified_file. Insert instrumentation in all
|
||||
the appropriate places. */
|
||||
|
||||
static void add_instrumentation(void) {
|
||||
|
||||
static u8 line[MAX_LINE];
|
||||
|
||||
FILE *inf;
|
||||
FILE *outf;
|
||||
s32 outfd;
|
||||
u32 ins_lines = 0;
|
||||
|
||||
u8 instr_ok = 0, skip_csect = 0, skip_next_label = 0, skip_intel = 0,
|
||||
skip_app = 0, instrument_next = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
u8 *colon_pos;
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
if (input_file) {
|
||||
|
||||
inf = fopen(input_file, "r");
|
||||
if (!inf) { PFATAL("Unable to read '%s'", input_file); }
|
||||
|
||||
} else {
|
||||
|
||||
inf = stdin;
|
||||
|
||||
}
|
||||
|
||||
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, DEFAULT_PERMISSION);
|
||||
|
||||
if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); }
|
||||
|
||||
outf = fdopen(outfd, "w");
|
||||
|
||||
if (!outf) { PFATAL("fdopen() failed"); }
|
||||
|
||||
while (fgets(line, MAX_LINE, inf)) {
|
||||
|
||||
/* In some cases, we want to defer writing the instrumentation trampoline
|
||||
until after all the labels, macros, comments, etc. If we're in this
|
||||
mode, and if the line starts with a tab followed by a character, dump
|
||||
the trampoline now. */
|
||||
|
||||
if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok &&
|
||||
instrument_next && line[0] == '\t' && isalpha(line[1])) {
|
||||
|
||||
fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
|
||||
R(MAP_SIZE));
|
||||
|
||||
instrument_next = 0;
|
||||
ins_lines++;
|
||||
|
||||
}
|
||||
|
||||
/* Output the actual line, call it a day in pass-thru mode. */
|
||||
|
||||
fputs(line, outf);
|
||||
|
||||
if (pass_thru) { continue; }
|
||||
|
||||
/* All right, this is where the actual fun begins. For one, we only want to
|
||||
instrument the .text section. So, let's keep track of that in processed
|
||||
files - and let's set instr_ok accordingly. */
|
||||
|
||||
if (line[0] == '\t' && line[1] == '.') {
|
||||
|
||||
/* OpenBSD puts jump tables directly inline with the code, which is
|
||||
a bit annoying. They use a specific format of p2align directives
|
||||
around them, so we use that as a signal. */
|
||||
|
||||
if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) &&
|
||||
isdigit(line[10]) && line[11] == '\n') {
|
||||
|
||||
skip_next_label = 1;
|
||||
|
||||
}
|
||||
|
||||
if (!strncmp(line + 2, "text\n", 5) ||
|
||||
!strncmp(line + 2, "section\t.text", 13) ||
|
||||
!strncmp(line + 2, "section\t__TEXT,__text", 21) ||
|
||||
!strncmp(line + 2, "section __TEXT,__text", 21)) {
|
||||
|
||||
instr_ok = 1;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (!strncmp(line + 2, "section\t", 8) ||
|
||||
!strncmp(line + 2, "section ", 8) || !strncmp(line + 2, "bss\n", 4) ||
|
||||
!strncmp(line + 2, "data\n", 5)) {
|
||||
|
||||
instr_ok = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Detect off-flavor assembly (rare, happens in gdb). When this is
|
||||
encountered, we set skip_csect until the opposite directive is
|
||||
seen, and we do not instrument. */
|
||||
|
||||
if (strstr(line, ".code")) {
|
||||
|
||||
if (strstr(line, ".code32")) { skip_csect = use_64bit; }
|
||||
if (strstr(line, ".code64")) { skip_csect = !use_64bit; }
|
||||
|
||||
}
|
||||
|
||||
/* Detect syntax changes, as could happen with hand-written assembly.
|
||||
Skip Intel blocks, resume instrumentation when back to AT&T. */
|
||||
|
||||
if (strstr(line, ".intel_syntax")) { skip_intel = 1; }
|
||||
if (strstr(line, ".att_syntax")) { skip_intel = 0; }
|
||||
|
||||
/* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */
|
||||
|
||||
if (line[0] == '#' || line[1] == '#') {
|
||||
|
||||
if (strstr(line, "#APP")) { skip_app = 1; }
|
||||
if (strstr(line, "#NO_APP")) { skip_app = 0; }
|
||||
|
||||
}
|
||||
|
||||
/* If we're in the right mood for instrumenting, check for function
|
||||
names or conditional labels. This is a bit messy, but in essence,
|
||||
we want to catch:
|
||||
|
||||
^main: - function entry point (always instrumented)
|
||||
^.L0: - GCC branch label
|
||||
^.LBB0_0: - clang branch label (but only in clang mode)
|
||||
^\tjnz foo - conditional branches
|
||||
|
||||
...but not:
|
||||
|
||||
^# BB#0: - clang comments
|
||||
^ # BB#0: - ditto
|
||||
^.Ltmp0: - clang non-branch labels
|
||||
^.LC0 - GCC non-branch labels
|
||||
^.LBB0_0: - ditto (when in GCC mode)
|
||||
^\tjmp foo - non-conditional jumps
|
||||
|
||||
Additionally, clang and GCC on MacOS X follow a different convention
|
||||
with no leading dots on labels, hence the weird maze of #ifdefs
|
||||
later on.
|
||||
|
||||
*/
|
||||
|
||||
if (skip_intel || skip_app || skip_csect || !instr_ok || line[0] == '#' ||
|
||||
line[0] == ' ') {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Conditional branch instruction (jnz, etc). We append the instrumentation
|
||||
right after the branch (to instrument the not-taken path) and at the
|
||||
branch destination label (handled later on). */
|
||||
|
||||
if (line[0] == '\t') {
|
||||
|
||||
if (line[1] == 'j' && line[2] != 'm' && R(100) < (long)inst_ratio) {
|
||||
|
||||
fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
|
||||
R(MAP_SIZE));
|
||||
|
||||
ins_lines++;
|
||||
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Label of some sort. This may be a branch destination, but we need to
|
||||
read carefully and account for several different formatting
|
||||
conventions. */
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* Apple: L<whatever><digit>: */
|
||||
|
||||
if ((colon_pos = strstr(line, ":"))) {
|
||||
|
||||
if (line[0] == 'L' && isdigit(*(colon_pos - 1))) {
|
||||
|
||||
#else
|
||||
|
||||
/* Everybody else: .L<whatever>: */
|
||||
|
||||
if (strstr(line, ":")) {
|
||||
|
||||
if (line[0] == '.') {
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/* .L0: or LBB0_0: style jump destination */
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* Apple: L<num> / LBB<num> */
|
||||
|
||||
if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3))) &&
|
||||
R(100) < (long)inst_ratio) {
|
||||
|
||||
#else
|
||||
|
||||
/* Apple: .L<num> / .LBB<num> */
|
||||
|
||||
if ((isdigit(line[2]) ||
|
||||
(clang_mode && !strncmp(line + 1, "LBB", 3))) &&
|
||||
R(100) < (long)inst_ratio) {
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/* An optimization is possible here by adding the code only if the
|
||||
label is mentioned in the code in contexts other than call / jmp.
|
||||
That said, this complicates the code by requiring two-pass
|
||||
processing (messy with stdin), and results in a speed gain
|
||||
typically under 10%, because compilers are generally pretty good
|
||||
about not generating spurious intra-function jumps.
|
||||
|
||||
We use deferred output chiefly to avoid disrupting
|
||||
.Lfunc_begin0-style exception handling calculations (a problem on
|
||||
MacOS X). */
|
||||
|
||||
if (!skip_next_label) {
|
||||
|
||||
instrument_next = 1;
|
||||
|
||||
} else {
|
||||
|
||||
skip_next_label = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Function label (always instrumented, deferred mode). */
|
||||
|
||||
instrument_next = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ins_lines) { fputs(use_64bit ? main_payload_64 : main_payload_32, outf); }
|
||||
|
||||
if (input_file) { fclose(inf); }
|
||||
fclose(outf);
|
||||
|
||||
if (!be_quiet) {
|
||||
|
||||
if (!ins_lines) {
|
||||
|
||||
WARNF("No instrumentation targets found%s.",
|
||||
pass_thru ? " (pass-thru mode)" : "");
|
||||
|
||||
} else {
|
||||
|
||||
char modeline[100];
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s",
|
||||
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
|
||||
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
|
||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||
getenv("AFL_USE_TSAN") ? ", TSAN" : "",
|
||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "",
|
||||
getenv("AFL_USE_LSAN") ? ", LSAN" : "");
|
||||
|
||||
OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).", ins_lines,
|
||||
use_64bit ? "64" : "32", modeline, inst_ratio);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Main entry point */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
s32 pid;
|
||||
u32 rand_seed, i, j;
|
||||
int status;
|
||||
u8 *inst_ratio_str = getenv("AFL_INST_RATIO");
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
clang_mode = !!getenv(CLANG_ENV_VAR);
|
||||
|
||||
if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
|
||||
|
||||
SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n");
|
||||
|
||||
} else {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
}
|
||||
|
||||
if (argc < 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) {
|
||||
|
||||
fprintf(
|
||||
stdout,
|
||||
"afl-as" VERSION
|
||||
" by Michal Zalewski\n"
|
||||
"\n%s [-h]\n\n"
|
||||
"This is a helper application for afl-fuzz. It is a wrapper around GNU "
|
||||
"'as',\n"
|
||||
"executed by the toolchain whenever using afl-gcc or afl-clang. You "
|
||||
"probably\n"
|
||||
"don't want to run this program directly.\n\n"
|
||||
|
||||
"Rarely, when dealing with extremely complex projects, it may be "
|
||||
"advisable\n"
|
||||
"to set AFL_INST_RATIO to a value less than 100 in order to reduce "
|
||||
"the\n"
|
||||
"odds of instrumenting every discovered branch.\n\n"
|
||||
"Environment variables used:\n"
|
||||
"AFL_AS: path to assembler to use for instrumented files\n"
|
||||
"AFL_CC: fall back path to assembler\n"
|
||||
"AFL_CXX: fall back path to assembler\n"
|
||||
"TMPDIR: directory to use for temporary files\n"
|
||||
"TEMP: fall back path to directory for temporary files\n"
|
||||
"TMP: fall back path to directory for temporary files\n"
|
||||
"AFL_INST_RATIO: user specified instrumentation ratio\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"
|
||||
"AFL_HARDEN, AFL_USE_ASAN, AFL_USE_MSAN, AFL_USE_UBSAN, AFL_USE_LSAN:\n"
|
||||
" used in the instrumentation summary message\n",
|
||||
argv[0]);
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
||||
// in fast systems where pids can repeat in the same seconds we need this
|
||||
for (i = 1; (s32)i < argc; i++)
|
||||
for (j = 0; j < strlen(argv[i]); j++)
|
||||
rand_seed += argv[i][j];
|
||||
|
||||
srandom(rand_seed);
|
||||
|
||||
edit_params(argc, argv);
|
||||
|
||||
if (inst_ratio_str) {
|
||||
|
||||
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) {
|
||||
|
||||
FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (getenv(AS_LOOP_ENV_VAR)) {
|
||||
|
||||
FATAL("Endless loop when calling 'as' (remove '.' from your PATH)");
|
||||
|
||||
}
|
||||
|
||||
setenv(AS_LOOP_ENV_VAR, "1", 1);
|
||||
|
||||
/* When compiling with ASAN, we don't have a particularly elegant way to skip
|
||||
ASAN-specific branches. But we can probabilistically compensate for
|
||||
that... */
|
||||
|
||||
if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) {
|
||||
|
||||
sanitizer = 1;
|
||||
if (!getenv("AFL_INST_RATIO")) { inst_ratio /= 3; }
|
||||
|
||||
}
|
||||
|
||||
if (!just_version) { add_instrumentation(); }
|
||||
|
||||
if (!(pid = fork())) {
|
||||
|
||||
execvp(as_params[0], (char **)as_params);
|
||||
FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]);
|
||||
|
||||
}
|
||||
|
||||
if (pid < 0) { PFATAL("fork() failed"); }
|
||||
|
||||
if (waitpid(pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); }
|
||||
|
||||
if (!getenv("AFL_KEEP_ASSEMBLY")) { unlink(modified_file); }
|
||||
|
||||
exit(WEXITSTATUS(status));
|
||||
|
||||
}
|
||||
|
33
src/afl-cc.c
33
src/afl-cc.c
@ -602,7 +602,6 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) {
|
||||
if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) {
|
||||
|
||||
/* afl-clang-fast is always created there by makefile
|
||||
just like afl-clang, burdened with special purposes:
|
||||
- If llvm-config is not available (i.e. LLVM_MAJOR is 0),
|
||||
or too old, it falls back to LLVM-NATIVE mode and let
|
||||
the actual compiler complain if doesn't work.
|
||||
@ -1220,11 +1219,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
switch (aflcc->compiler_mode) {
|
||||
|
||||
case GCC:
|
||||
if (!aflcc->have_gcc) FATAL("afl-gcc is not available on your platform!");
|
||||
break;
|
||||
case CLANG:
|
||||
if (!aflcc->have_clang)
|
||||
FATAL("afl-clang is not available on your platform!");
|
||||
break;
|
||||
case LLVM:
|
||||
if (!aflcc->have_llvm)
|
||||
@ -1564,7 +1560,6 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
|
||||
/*
|
||||
Macro defs for persistent mode. As documented in
|
||||
instrumentation/README.persistent_mode.md, deferred forkserver initialization
|
||||
and persistent mode are not available in afl-gcc and afl-clang.
|
||||
*/
|
||||
void add_defs_persistent_mode(aflcc_state_t *aflcc) {
|
||||
|
||||
@ -2845,10 +2840,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
" yes\n"
|
||||
" [GCC_PLUGIN] gcc plugin: %s%s\n"
|
||||
" CLASSIC DEFAULT no yes no no no "
|
||||
"yes\n"
|
||||
" [GCC/CLANG] simple gcc/clang: %s%s\n"
|
||||
" CLASSIC DEFAULT no no no no no "
|
||||
"no\n\n",
|
||||
"yes\n\n",
|
||||
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
|
||||
aflcc->compiler_mode == LLVM ? " [SELECTED]" : "",
|
||||
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
|
||||
@ -2856,15 +2848,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
aflcc->have_lto ? "AVAILABLE" : "unavailable!",
|
||||
aflcc->compiler_mode == LTO ? " [SELECTED]" : "",
|
||||
aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!",
|
||||
aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "",
|
||||
aflcc->have_gcc && aflcc->have_clang
|
||||
? "AVAILABLE"
|
||||
: (aflcc->have_gcc
|
||||
? "GCC ONLY "
|
||||
: (aflcc->have_clang ? "CLANG ONLY" : "unavailable!")),
|
||||
(aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG)
|
||||
? " [SELECTED]"
|
||||
: "");
|
||||
aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "");
|
||||
|
||||
SAYF(
|
||||
"Modes:\n"
|
||||
@ -3554,10 +3538,12 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
maybe_usage(aflcc, argc, argv);
|
||||
|
||||
if ((aflcc->compiler_mode == CLANG || aflcc->compiler_mode == GCC) &&
|
||||
aflcc->need_aflpplib) {
|
||||
if (aflcc->instrument_mode == INSTRUMENT_GCC || aflcc->instrument_mode ==
|
||||
INSTRUMENT_CLANG) {
|
||||
|
||||
FATAL("afl-gcc/afl-clang cannot be used together with -fsanitize=fuzzer");
|
||||
FATAL(
|
||||
"afl-gcc/afl-clang are obsolete and has been removed. Use "
|
||||
"afl-clang-fast/afl-gcc-fast for instrumentation instead.");
|
||||
|
||||
}
|
||||
|
||||
@ -3567,9 +3553,12 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
edit_params(aflcc, argc, argv, envp);
|
||||
|
||||
if (aflcc->debug)
|
||||
if (aflcc->debug) {
|
||||
|
||||
debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params);
|
||||
|
||||
}
|
||||
|
||||
if (aflcc->passthrough) {
|
||||
|
||||
argv[0] = aflcc->cc_params[0];
|
||||
|
@ -552,7 +552,7 @@ void nyx_load_target_hash(afl_forkserver_t *fsrv) {
|
||||
|
||||
In essence, the instrumentation allows us to skip execve(), and just keep
|
||||
cloning a stopped child. So, we just execute once, and then send commands
|
||||
through a pipe. The other part of this logic is in afl-as.h / llvm_mode */
|
||||
through a pipe. The other part of this logic is in afl-compilter-rt.o */
|
||||
|
||||
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
volatile u8 *stop_soon_p, u8 debug_child_output) {
|
||||
|
@ -3096,9 +3096,9 @@ void check_binary(afl_state_t *afl, u8 *fname) {
|
||||
afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
|
||||
|
||||
SAYF("\n" cLRD "[-] " cRST
|
||||
"This program appears to be instrumented with afl-gcc, but is being "
|
||||
"run in\n"
|
||||
" QEMU mode (-Q). This is probably not what you "
|
||||
"This program appears to be instrumented with AFL++ compilers, but is "
|
||||
"being run\n"
|
||||
" in QEMU mode (-Q). This is probably not what you "
|
||||
"want -\n"
|
||||
" this setup will be slow and offer no practical benefits.\n");
|
||||
|
||||
|
@ -4,60 +4,58 @@
|
||||
|
||||
OS=$(uname -s)
|
||||
|
||||
AFL_GCC=afl-gcc
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
|
||||
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "i386" && {
|
||||
test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
../${AFL_GCC} -v 2>&1 | grep -qi "gcc version" && {
|
||||
../${AFL_GCC} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1
|
||||
AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
|
||||
AFL_COMPILER=afl-clang-fast
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_COMPILER}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
|
||||
test -e ../${AFL_COMPILER} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
../${AFL_COMPILER} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1
|
||||
AFL_HARDEN=1 ../${AFL_COMPILER} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
|
||||
test -e test-instr.plain && {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded"
|
||||
$ECHO "$GREEN[+] ${AFL_COMPILER} compilation succeeded"
|
||||
echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1
|
||||
AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1
|
||||
test -e test-instr.plain.0 -a -e test-instr.plain.1 && {
|
||||
diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] ${AFL_GCC} instrumentation should be different on different input but is not"
|
||||
$ECHO "$RED[!] ${AFL_COMPILER} instrumentation should be different on different input but is not"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} instrumentation present and working correctly"
|
||||
$ECHO "$GREEN[+] ${AFL_COMPILER} instrumentation present and working correctly"
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} instrumentation failed"
|
||||
$ECHO "$RED[!] ${AFL_COMPILER} instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-instr.plain.0 test-instr.plain.1
|
||||
SKIP=
|
||||
TUPLES=`echo 1|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 1 -a "$TUPLES" -lt 22 && {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine"
|
||||
$ECHO "$GREEN[+] ${AFL_COMPILER} run reported $TUPLES instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} instrumentation produces weird numbers: $TUPLES"
|
||||
$ECHO "$RED[!] ${AFL_COMPILER} instrumentation produces weird numbers: $TUPLES"
|
||||
CODE=1
|
||||
}
|
||||
test "$TUPLES" -lt 3 && SKIP=1
|
||||
true # this is needed because of the test above
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} failed"
|
||||
$ECHO "$RED[!] ${AFL_COMPILER} failed"
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
uname -a
|
||||
../${AFL_GCC} -o test-instr.plain -O0 ../test-instr.c
|
||||
../${AFL_COMPILER} -o test-instr.plain -O0 ../test-instr.c
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
CODE=1
|
||||
}
|
||||
test -e test-compcov.harden && {
|
||||
nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working"
|
||||
$ECHO "$GREEN[+] ${AFL_COMPILER} hardened mode succeeded and is working"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened"
|
||||
$ECHO "$RED[!] ${AFL_COMPILER} hardened mode is not hardened"
|
||||
env | grep -E 'AFL|PATH|LLVM'
|
||||
AFL_DEBUG=1 AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c
|
||||
AFL_DEBUG=1 AFL_HARDEN=1 ../${AFL_COMPILER} -o test-compcov.harden test-compcov.c
|
||||
nm test-compcov.harden
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
|
||||
$ECHO "$RED[!] ${AFL_COMPILER} hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
@ -69,17 +67,17 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
|
||||
mkdir -p in
|
||||
echo 0 > in/in
|
||||
test -z "$SKIP" && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds"
|
||||
$ECHO "$GREY[*] running afl-fuzz for ${AFL_COMPILER}, this will take approx 10 seconds"
|
||||
{
|
||||
../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}"
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_COMPILER}"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}"
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_COMPILER}"
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
@ -124,159 +122,9 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
|
||||
unset AFL_QUIET
|
||||
}
|
||||
rm -f test-instr.plain
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl-gcc executes clang, cannot test!"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
AFL_CLANG=afl-clang
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_CLANG}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
|
||||
SKIP=
|
||||
test -e ../${AFL_CLANG} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
../${AFL_CLANG} -v 2>&1 | grep -qi "clang version" && {
|
||||
../${AFL_CLANG} -O0 -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
AFL_HARDEN=1 ../${AFL_CLANG} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
|
||||
test -e test-instr.plain && {
|
||||
$ECHO "$GREEN[+] ${AFL_CLANG} compilation succeeded"
|
||||
echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1
|
||||
AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1
|
||||
test -e test-instr.plain.0 -a -e test-instr.plain.1 && {
|
||||
diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] ${AFL_CLANG} instrumentation should be different on different input but is not"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] ${AFL_CLANG} instrumentation present and working correctly"
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_CLANG} instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-instr.plain.0 test-instr.plain.1
|
||||
TUPLES=`echo 1|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 1 -a "$TUPLES" -lt 22 && {
|
||||
$ECHO "$GREEN[+] ${AFL_CLANG} run reported $TUPLES instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_CLANG} instrumentation produces weird numbers: $TUPLES"
|
||||
CODE=1
|
||||
}
|
||||
test "$TUPLES" -lt 3 && SKIP=1
|
||||
true # this is needed because of the test above
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_CLANG} failed"
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
uname -a
|
||||
../${AFL_CLANG} -o test-instr.plain ../test-instr.c
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
CODE=1
|
||||
}
|
||||
test -e test-compcov.harden && {
|
||||
nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] ${AFL_CLANG} hardened mode succeeded and is working"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_CLANG} hardened mode is not hardened"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_CLANG} hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
(test "$OS" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
|
||||
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) || {
|
||||
mkdir -p in
|
||||
echo 0 > in/in
|
||||
test -z "$SKIP" && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for ${AFL_CLANG}, this will take approx 10 seconds"
|
||||
{
|
||||
../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_CLANG}"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_CLANG}"
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
echo 000000000000000000000000 > in/in2
|
||||
echo AAA > in/in2
|
||||
test "$OS" = "Darwin" && {
|
||||
$ECHO "$GREY[*] afl-cmin not available on macOS, cannot test afl-cmin"
|
||||
} || {
|
||||
mkdir -p in2
|
||||
../afl-cmin -m ${MEM_LIMIT} -i in -o in2 -- ./test-instr.plain >/dev/null 2>&1 # why is afl-forkserver writing to stderr?
|
||||
CNT=`ls in2/* 2>/dev/null | wc -l`
|
||||
case "$CNT" in
|
||||
*2) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
|
||||
\ *1|1) { # allow leading whitecase for portability
|
||||
test -s in2/* && $ECHO "$YELLOW[?] afl-cmin did minimize to one testcase. This can be a bug or due compiler optimization."
|
||||
test -s in2/* || {
|
||||
$ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases ($CNT)"
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
;;
|
||||
*) $ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases ($CNT)"
|
||||
CODE=1
|
||||
;;
|
||||
esac
|
||||
rm -f in2/in*
|
||||
}
|
||||
export AFL_QUIET=1
|
||||
if command -v bash >/dev/null ; then {
|
||||
../afl-cmin.bash -m ${MEM_LIMIT} -i in -o in2 -- ./test-instr.plain >/dev/null
|
||||
CNT=`ls in2/* 2>/dev/null | wc -l`
|
||||
case "$CNT" in
|
||||
*2) $ECHO "$GREEN[+] afl-cmin.bash correctly minimized the number of testcases" ;;
|
||||
\ *1|1) { # allow leading whitecase for portability
|
||||
test -s in2/* && $ECHO "$YELLOW[?] afl-cmin.bash did minimize to one testcase. This can be a bug or due compiler optimization."
|
||||
test -s in2/* || {
|
||||
$ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
;;
|
||||
*) $ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
|
||||
CODE=1
|
||||
;;
|
||||
esac
|
||||
} else {
|
||||
$ECHO "$GREY[*] no bash available, cannot test afl-cmin.bash"
|
||||
}
|
||||
fi
|
||||
../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
|
||||
SIZE=`ls -l in2/in2 2>/dev/null | awk '{print$5}'`
|
||||
test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase"
|
||||
test "$SIZE" = 1 || {
|
||||
$ECHO "$RED[!] afl-tmin did incorrectly minimize the testcase to $SIZE"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors in2
|
||||
unset AFL_QUIET
|
||||
}
|
||||
rm -f test-instr.plain
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl-clang executes gcc, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$GREY[*] not an intel platform, skipped tests of afl-gcc"
|
||||
#this is not incomplete as this feature doesnt exist, so all good
|
||||
AFL_TEST_COUNT=$((AFL_TEST_COUNT-1))
|
||||
}
|
||||
|
||||
. ./test-post.sh
|
||||
|
@ -11,21 +11,13 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS
|
||||
test -e ../afl-clang-fast && {
|
||||
../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
} || {
|
||||
test -e ../afl-gcc-fast && {
|
||||
../afl-gcc-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
} || {
|
||||
../afl-gcc -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
}
|
||||
../afl-gcc-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
}
|
||||
# Compile the vulnerable program for multiple mutators
|
||||
test -e ../afl-clang-fast && {
|
||||
../afl-clang-fast -o test-multiple-mutators test-multiple-mutators.c > /dev/null 2>&1
|
||||
} || {
|
||||
test -e ../afl-gcc-fast && {
|
||||
../afl-gcc-fast -o test-multiple-mutators test-multiple-mutators.c > /dev/null 2>&1
|
||||
} || {
|
||||
../afl-gcc -o test-multiple-mutators test-multiple-mutators.c > /dev/null 2>&1
|
||||
}
|
||||
../afl-gcc-fast -o test-multiple-mutators test-multiple-mutators.c > /dev/null 2>&1
|
||||
}
|
||||
# Compile the custom mutator
|
||||
cc -D_FIXED_CHAR=0x41 -g -fPIC -shared -I../include ../custom_mutators/examples/simple_example.c -o libexamplemutator.so > /dev/null 2>&1
|
||||
|
@ -81,7 +81,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
|
||||
|
||||
# now for the special gcc_plugin things
|
||||
echo foobar.c > instrumentlist.txt
|
||||
AFL_GCC_INSTRUMENT_FILE=instrumentlist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1
|
||||
AFL_COMPILER_INSTRUMENT_FILE=instrumentlist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1
|
||||
test -x test-compcov && test_compcov_binary_functionality ./test-compcov && {
|
||||
echo 1 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 0 tuples" && {
|
||||
$ECHO "$GREEN[+] gcc_plugin instrumentlist feature works correctly"
|
||||
|
@ -26,7 +26,7 @@ unset AFL_USE_ASAN
|
||||
unset AFL_USE_MSAN
|
||||
unset AFL_CC
|
||||
unset AFL_PRELOAD
|
||||
unset AFL_GCC_INSTRUMENT_FILE
|
||||
unset AFL_COMPILER_INSTRUMENT_FILE
|
||||
unset AFL_LLVM_INSTRUMENT_FILE
|
||||
unset AFL_LLVM_INSTRIM
|
||||
unset AFL_LLVM_LAF_SPLIT_SWITCHES
|
||||
@ -37,15 +37,6 @@ unset AFL_LLVM_LAF_SPLIT_COMPARES
|
||||
test -e /usr/local/bin/opt && {
|
||||
export PATH=/usr/local/bin:${PATH}
|
||||
}
|
||||
# on MacOS X we prefer afl-clang over afl-gcc, because
|
||||
# afl-gcc does not work there
|
||||
test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && {
|
||||
AFL_GCC=afl-clang
|
||||
CC=clang
|
||||
} || {
|
||||
AFL_GCC=afl-gcc
|
||||
CC=gcc
|
||||
}
|
||||
|
||||
ECHO="printf %b\\n"
|
||||
$ECHO \\101 2>&1 | grep -qE '^A' || {
|
||||
@ -76,30 +67,6 @@ echo
|
||||
|
||||
$ECHO "${RESET}${GREY}[*] starting AFL++ performance test framework ..."
|
||||
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_GCC}"
|
||||
GCC=x
|
||||
test -e ../${AFL_GCC} -a -e ../afl-fuzz && {
|
||||
../${AFL_GCC} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
test -e test-instr.plain && {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded"
|
||||
mkdir -p in
|
||||
echo 0 > in/in
|
||||
$ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC} for 30 seconds"
|
||||
{
|
||||
../afl-fuzz -V 30 -s 123 -m ${MEM_LIMIT} -i in -o out-gcc -- ./test-instr.plain
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out-gcc/default/queue/id:000002* 2> /dev/null )" && {
|
||||
GCC=`grep execs_done out-gcc/default/fuzzer_stats | awk '{print$3}'`
|
||||
} || {
|
||||
echo CUT----------------------------------------------------------------
|
||||
cat errors
|
||||
echo CUT----------------------------------------------------------------
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}"
|
||||
}
|
||||
rm -rf in out-gcc errors test-instr.plain
|
||||
} || $ECHO "$RED[!] ${AFL_GCC} instrumentation failed"
|
||||
} || $ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
|
||||
$ECHO "$BLUE[*] Testing: llvm_mode"
|
||||
LLVM=x
|
||||
test -e ../afl-clang-fast -a -e ../afl-fuzz && {
|
||||
@ -232,7 +199,7 @@ test -s $FILE && {
|
||||
$ECHO "$BLUE[!] qemu_mode: lowest=$LOW_QEMU highest=$HIGH_QEMU last=$LAST_QEMU current=$QEMU"
|
||||
} || {
|
||||
$ECHO "$YELLOW[!] First run, just saving data"
|
||||
$ECHO "$BLUE[!] afl-gcc=$GCC llvm_mode=$LLVM gcc_plugin=$GCCP qemu_mode=$QEMU"
|
||||
$ECHO "$BLUE[!] llvm_mode=$LLVM gcc_plugin=$GCCP qemu_mode=$QEMU"
|
||||
}
|
||||
echo "$GCC $LLVM $GCCP $QEMU" >> $FILE
|
||||
$ECHO "$GREY[*] done."
|
||||
|
@ -111,14 +111,7 @@ test -n "$TRAVIS_OS_NAME" && {
|
||||
test -e /usr/local/bin/opt && {
|
||||
test `uname -s` = 'Darwin' || export PATH="/usr/local/bin:${PATH}"
|
||||
}
|
||||
# on MacOS X we prefer afl-clang over afl-gcc, because
|
||||
# afl-gcc does not work there (it is a symlink from clang)
|
||||
test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && {
|
||||
AFL_GCC=afl-clang
|
||||
} || {
|
||||
AFL_GCC=afl-gcc
|
||||
}
|
||||
command -v gcc >/dev/null 2>&1 || AFL_GCC=afl-clang
|
||||
AFL_COMPILER=afl-clang-fast
|
||||
|
||||
SYS=`uname -m`
|
||||
|
||||
|
Reference in New Issue
Block a user