about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-08-12 14:29:34 +0200
committerGitHub <noreply@github.com>2020-08-12 14:29:34 +0200
commit8044ae28be2dd109ac16719ce2e304074fa74efd (patch)
treededf9bafaf8d176bc07912a2f512187af9048f36
parent986af28df27016813abdfdde8bdedda1f571703c (diff)
parentb38837f4ff8f2e52597b7908b9226500e5c61933 (diff)
downloadafl++-8044ae28be2dd109ac16719ce2e304074fa74efd.tar.gz
Merge pull request #496 from AFLplusplus/dev
push to stable
-rw-r--r--.travis.yml2
-rw-r--r--GNUmakefile11
-rw-r--r--README.md92
-rw-r--r--TODO.md1
-rw-r--r--custom_mutators/README.md13
-rw-r--r--custom_mutators/honggfuzz/Makefile2
-rw-r--r--custom_mutators/honggfuzz/honggfuzz.h561
-rw-r--r--custom_mutators/honggfuzz/mangle.c34
-rw-r--r--custom_mutators/honggfuzz/mangle.h3
-rw-r--r--docs/Changelog.md9
-rw-r--r--docs/FAQ.md7
-rw-r--r--docs/env_variables.md11
-rw-r--r--docs/perf_tips.md2
-rw-r--r--dynamic_list.txt10
-rw-r--r--examples/aflpp_driver/aflpp_driver.c58
-rw-r--r--gcc_plugin/GNUmakefile2
-rw-r--r--gcc_plugin/Makefile2
-rw-r--r--gcc_plugin/README.instrument_list.md (renamed from gcc_plugin/README.instrument_file.md)0
-rw-r--r--include/afl-fuzz.h29
-rw-r--r--include/debug.h67
-rw-r--r--include/envs.h3
-rw-r--r--llvm_mode/GNUmakefile13
-rw-r--r--llvm_mode/README.instrument_file.md81
-rw-r--r--llvm_mode/README.instrument_list.md86
-rw-r--r--llvm_mode/README.lto.md25
-rw-r--r--llvm_mode/README.md2
-rw-r--r--llvm_mode/README.persistent_mode.md27
-rw-r--r--llvm_mode/afl-clang-fast.c54
-rw-r--r--llvm_mode/afl-llvm-common.cc487
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc111
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentlist.so.cc156
-rw-r--r--llvm_mode/afl-llvm-rt.o.c47
-rwxr-xr-xqemu_mode/build_qemu_support.sh1
-rw-r--r--qemu_mode/patches/mips-fpu.diff15
-rw-r--r--src/afl-analyze.c5
-rw-r--r--src/afl-as.c10
-rw-r--r--src/afl-forkserver.c27
-rw-r--r--src/afl-fuzz-bitmap.c8
-rw-r--r--src/afl-fuzz-cmplog.c4
-rw-r--r--src/afl-fuzz-extras.c8
-rw-r--r--src/afl-fuzz-init.c13
-rw-r--r--src/afl-fuzz-mutators.c1
-rw-r--r--src/afl-fuzz-one.c103
-rw-r--r--src/afl-fuzz-python.c7
-rw-r--r--src/afl-fuzz-queue.c2
-rw-r--r--src/afl-fuzz-redqueen.c19
-rw-r--r--src/afl-fuzz-run.c29
-rw-r--r--src/afl-fuzz-stats.c6
-rw-r--r--src/afl-fuzz.c15
-rw-r--r--src/afl-showmap.c7
-rw-r--r--src/afl-tmin.c17
-rwxr-xr-xtest/test-all.sh23
-rwxr-xr-xtest/test-basic.sh126
-rwxr-xr-xtest/test-custom-mutators.sh125
-rwxr-xr-xtest/test-gcc-plugin.sh116
-rwxr-xr-xtest/test-libextensions.sh51
-rwxr-xr-xtest/test-llvm-lto.sh78
-rwxr-xr-xtest/test-llvm.sh230
-rwxr-xr-xtest/test-post.sh14
-rwxr-xr-xtest/test-pre.sh131
-rwxr-xr-xtest/test-qemu-mode.sh217
-rwxr-xr-xtest/test-unicorn-mode.sh112
-rwxr-xr-xtest/test-unittests.sh9
-rwxr-xr-xtest/test.sh1181
-rw-r--r--test/travis/bionic/Dockerfile1
-rw-r--r--test/unittests/unit_hash.c5
-rw-r--r--test/unittests/unit_list.c11
-rw-r--r--test/unittests/unit_maybe_alloc.c11
-rw-r--r--test/unittests/unit_preallocable.c10
-rw-r--r--test/unittests/unit_rand.c8
70 files changed, 2671 insertions, 2093 deletions
diff --git a/.travis.yml b/.travis.yml
index 96cdc86c..0155aa68 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -54,6 +54,6 @@ script:
   - sudo sysctl -w kernel.shmmax=10000000000
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then export LLVM_CONFIG=`pwd`/"$NAME" ; make source-only ASAN_BUILD=1 ; fi
   - if [ "$TRAVIS_OS_NAME" = "linux" -a "$TRAVIS_CPU_ARCH" = "amd64" ]; then make distrib ASAN_BUILD=1 ; fi
-  - if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then echo DEBUG ; find / -name llvm-config.h 2>/dev/null; apt-cache search clang | grep clang- ; apt-cache search llvm | grep llvm- ; dpkg -l | egrep 'clang|llvm'; echo DEBUG ; export LLVM_CONFIG=llvm-config-6.0 ; make ASAN_BUILD=1 ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi
+  - if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then export LLVM_CONFIG=llvm-config-6.0 ; make ASAN_BUILD=1 ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi
   - make tests
 #  - travis_terminate 0
diff --git a/GNUmakefile b/GNUmakefile
index e0d89274..fe5f8c03 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -98,7 +98,7 @@ ifneq "$(shell uname -m)" "x86_64"
 endif
 
 CFLAGS     ?= -O3 -funroll-loops $(CFLAGS_OPT)
-override CFLAGS += -Wall -g -Wno-pointer-sign \
+override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
 			  -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
 			  -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
 
@@ -198,6 +198,7 @@ else
 endif
 
 ifneq "$(filter Linux GNU%,$(shell uname))" ""
+  override CFLAGS += -D_FORTIFY_SOURCE=2
   LDFLAGS += -ldl -lrt
 endif
 
@@ -270,7 +271,7 @@ all:	test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
 man:    $(MANPAGES)
 
 tests:	source-only
-	@cd test ; ./test.sh
+	@cd test ; ./test-all.sh
 	@rm -f test/errors
 
 performance-tests:	performance-test
@@ -551,9 +552,9 @@ source-only: all
 	-$(MAKE) -C gcc_plugin
 	$(MAKE) -C libdislocator
 	$(MAKE) -C libtokencap
-	#$(MAKE) -C examples/afl_network_proxy
-	#$(MAKE) -C examples/socket_fuzzing
-	#$(MAKE) -C examples/argv_fuzzing
+	@#$(MAKE) -C examples/afl_network_proxy
+	@#$(MAKE) -C examples/socket_fuzzing
+	@#$(MAKE) -C examples/argv_fuzzing
 
 %.8:	%
 	@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
diff --git a/README.md b/README.md
index b42fed2e..18983832 100644
--- a/README.md
+++ b/README.md
@@ -39,19 +39,19 @@
   with laf-intel and redqueen, unicorn mode, gcc plugin, full *BSD, Solaris and
   Android support and much, much, much more.
 
-  | Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode        | unicorn_mode |
-  | ----------------------- |:-------:|:---------:|:----------:|:----------------:|:------------:|
-  | NeverZero               | x86[_64]|     x(1)  |      (2)   |         x        |       x      |
-  | Persistent mode         |         |     x     |     x      | x86[_64]/arm[64] |       x      |
-  | LAF-Intel / CompCov     |         |     x     |            | x86[_64]/arm[64] | x86[_64]/arm |
-  | CmpLog                  |         |     x     |            | x86[_64]/arm[64] |              |
-  | Instrument file list    |         |     x     |     x      |        (x)(3)    |              |
-  | Non-colliding coverage  |         |     x(4)  |            |        (x)(5)    |              |
-  | InsTrim                 |         |     x     |            |                  |              |
-  | Ngram prev_loc coverage |         |     x(6)  |            |                  |              |
-  | Context coverage        |         |     x     |            |                  |              |
-  | Auto dictionary         |         |     x(7)  |            |                  |              |
-  | Snapshot LKM support    |         |     x     |            |        (x)(5)    |              |
+  | Feature/Instrumentation  | afl-gcc | llvm_mode | gcc_plugin | qemu_mode        | unicorn_mode |
+  | -------------------------|:-------:|:---------:|:----------:|:----------------:|:------------:|
+  | NeverZero                | x86[_64]|     x(1)  |      (2)   |         x        |       x      |
+  | Persistent Mode          |         |     x     |     x      | x86[_64]/arm[64] |       x      |
+  | LAF-Intel / CompCov      |         |     x     |            | x86[_64]/arm[64] | x86[_64]/arm |
+  | CmpLog                   |         |     x     |            | x86[_64]/arm[64] |              |
+  | Selective Instrumentation|         |     x     |     x      |        (x)(3)    |              |
+  | Non-Colliding Coverage   |         |     x(4)  |            |        (x)(5)    |              |
+  | InsTrim                  |         |     x     |            |                  |              |
+  | Ngram prev_loc Coverage  |         |     x(6)  |            |                  |              |
+  | Context Coverage         |         |     x     |            |                  |              |
+  | Auto Dictionary          |         |     x(7)  |            |                  |              |
+  | Snapshot LKM Support     |         |     x     |            |        (x)(5)    |              |
 
   1. default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8
   2. GCC creates non-performant code, hence it is disabled in gcc_plugin
@@ -64,21 +64,20 @@
   Among others, the following features and patches have been integrated:
 
   * NeverZero patch for afl-gcc, llvm_mode, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage
-  * Persistent mode and deferred forkserver for qemu_mode
+  * Persistent mode, deferred forkserver and in-memory fuzzing for qemu_mode
   * Unicorn mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk)
   * The new CmpLog instrumentation for LLVM and QEMU inspired by [Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
   * Win32 PE binary-only fuzzing with QEMU and Wine
   * AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
   * The MOpt mutator: [https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL)
   * LLVM mode Ngram coverage by Adrian Herrera [https://github.com/adrianherrera/afl-ngram-pass](https://github.com/adrianherrera/afl-ngram-pass)
-  * InsTrim, an effective CFG llvm_mode instrumentation implementation for large targets: [https://github.com/csienslab/instrim](https://github.com/csienslab/instrim)
-  * C. Holler's afl-fuzz Python mutator module and llvm_mode instrument file support: [https://github.com/choller/afl](https://github.com/choller/afl)
+  * InsTrim, a CFG llvm_mode instrumentation implementation: [https://github.com/csienslab/instrim](https://github.com/csienslab/instrim)
+  * C. Holler's afl-fuzz Python mutator module: [https://github.com/choller/afl](https://github.com/choller/afl)
   * Custom mutator by a library (instead of Python) by kyakdan
   * LAF-Intel/CompCov support for llvm_mode, qemu_mode and unicorn_mode (with enhanced capabilities)
   * Radamsa and hongfuzz mutators (as custom mutators).
   * QBDI mode to fuzz android native libraries via Quarkslab's [QBDI](https://github.com/QBDI/QBDI) framework
-
-  A more thorough list is available in the [PATCHES](docs/PATCHES.md) file.
+  * Frida and ptrace mode to fuzz binary-only libraries, etc.
 
   So all in all this is the best-of afl that is out there :-)
 
@@ -195,6 +194,7 @@ Here are some good writeups to show how to effectively use AFL++:
  * [https://securitylab.github.com/research/fuzzing-challenges-solutions-1](https://securitylab.github.com/research/fuzzing-challenges-solutions-1)
  * [https://securitylab.github.com/research/fuzzing-software-2](https://securitylab.github.com/research/fuzzing-software-2)
  * [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
+ * [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP)
 
 If you are interested in fuzzing structured data (where you define what the
 structure is), these links have you covered:
@@ -246,7 +246,7 @@ anything below 9 is not recommended.
  +--------------------------------+
  | if you want to instrument only | -> use afl-gcc-fast and afl-gcc-fast++
  | parts of the target            |    see [gcc_plugin/README.md](gcc_plugin/README.md) and
- +--------------------------------+    [gcc_plugin/README.instrument_file.md](gcc_plugin/README.instrument_file.md)
+ +--------------------------------+    [gcc_plugin/README.instrument_list.md](gcc_plugin/README.instrument_list.md)
     |
     | if not, or if you do not have a gcc with plugin support
     |
@@ -272,15 +272,17 @@ afl-clang-lto:
    To use this set the following environment variable before compiling the
    target: `export AFL_LLVM_LAF_ALL=1`
    You can read more about this in [llvm/README.laf-intel.md](llvm/README.laf-intel.md)
- * A different technique (and usually a bit better than laf-intel) is to
+ * A different technique (and usually a better than laf-intel) is to
    instrument the target so that any compare values in the target are sent to
-   afl++ which then tries to put this value into the fuzzing data at different
+   afl++ which then tries to put these values into the fuzzing data at different
    locations. This technique is very fast and good - if the target does not
    transform input data before comparison. Therefore this technique is called
    `input to state` or `redqueen`.
    If you want to use this technique, then you have to compile the target
    twice, once specifically with/for this mode, and pass this binary to afl-fuzz
    via the `-c` parameter.
+   Not that you can compile also just a cmplog binary and use that for both
+   however there will a performance penality.
    You can read more about this in [llvm_mode/README.cmplog.md](llvm_mode/README.cmplog.md)
 
 If you use afl-clang-fast, afl-clang-lto or afl-gcc-fast you have the option to
@@ -290,24 +292,33 @@ selectively only instrument parts of the target that you are interested in:
    create a file with all the filenames of the source code that should be
    instrumented.
    For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if either the clang
-   version is < 7 or the CLASSIC instrumentation is used - just put one
-   filename per line, no directory information necessary, and set
-   `export AFL_LLVM_INSTRUMENT_FILE=yourfile.txt`
-   see [llvm_mode/README.instrument_file.md](llvm_mode/README.instrument_file.md)
+   version is below 7 or the CLASSIC instrumentation is used - just put one
+   filename or function per line (no directory information necessary for
+   filenames9, and either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or**
+   `export AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per
+   default to instrument unless noted (DENYLIST) or not perform instrumentation
+   unless requested (ALLOWLIST).
+   **NOTE:** In optimization functions might be inlined and then not match!
+   see [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md)
    For afl-clang-fast > 6.0 or if PCGUARD instrumentation is used then use the
    llvm sancov allow-list feature: [http://clang.llvm.org/docs/SanitizerCoverage.html](http://clang.llvm.org/docs/SanitizerCoverage.html)
+   The llvm sancov format works with the allowlist/denylist feature of afl++
+   however afl++ is more flexible in the format.
 
 There are many more options and modes available however these are most of the
 time less effective. See:
  * [llvm_mode/README.ctx.md](llvm_mode/README.ctx.md)
  * [llvm_mode/README.ngram.md](llvm_mode/README.ngram.md)
  * [llvm_mode/README.instrim.md](llvm_mode/README.instrim.md)
+
+afl++ employs never zero counting in its bitmap. You can read more about this
+here:
  * [llvm_mode/README.neverzero.md](llvm_mode/README.neverzero.md)
 
 #### c) Modify the target
 
 If the target has features that makes fuzzing more difficult, e.g.
-checksums, HMAC etc. then modify the source code so that this is
+checksums, HMAC, etc. then modify the source code so that this is
 removed.
 This can even be done for productional source code be eliminating
 these checks within this specific defines:
@@ -382,6 +393,7 @@ As you fuzz the target with mutated input, having as diverse inputs for the
 target as possible improves the efficiency a lot.
 
 #### a) Collect inputs
+
 Try to gather valid inputs for the target from wherever you can. E.g. if it is
 the PNG picture format try to find as many png files as possible, e.g. from
 reported bugs, test suites, random downloads from the internet, unit test
@@ -430,23 +442,24 @@ to be used in fuzzing! :-)
 ### 3. Fuzzing the target
 
 In this final step we fuzz the target.
-There are not that many useful options to run the target - unless you want to
-use many CPU cores/threads for the fuzzing, which will make the fuzzing much
+There are not that many important options to run the target - unless you want
+to use many CPU cores/threads for the fuzzing, which will make the fuzzing much
 more useful.
 
 If you just use one CPU for fuzzing, then you are fuzzing just for fun and not
 seriously :-)
 
 Pro tip: load the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) 
-before the start of afl-fuzz as this improves performance by a x2 speed increase!
+before the start of afl-fuzz as this improves performance by a x2 speed increase
+(less if you use a persistent mode harness)!
 
 #### a) Running afl-fuzz
 
 Before to do even a test run of afl-fuzz execute `sudo afl-system-config` (on
 the host if you execute afl-fuzz in a docker container). This reconfigures the
 system for optimal speed - which afl-fuzz checks and bails otherwise.
-Set `export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot run
-afl-system-config with root privileges on the host for whatever reason.
+Set `export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot
+run afl-system-config with root privileges on the host for whatever reason.
 
 If you have an input corpus from step 2 then specify this directory with the `-i`
 option. Otherwise create a new directory and create a file with any content
@@ -468,7 +481,7 @@ of memory. By default this is 50MB for a process. If this is too little for
 the target (which you can usually see by afl-fuzz bailing with the message
 that it could not connect to the forkserver), then you can increase this
 with the `-m` option, the value is in MB. To disable any memory limits
-(beware!) set `-m 0` - which is usually required for ASAN compiled targets.
+(beware!) set `-m none` - which is usually required for ASAN compiled targets.
 
 Adding a dictionary is helpful. See the [dictionaries/](dictionaries/) if
 something is already included for your data format, and tell afl-fuzz to load
@@ -529,7 +542,7 @@ Examples are:
 
 A long list can be found at [https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL)
 
-However you can also sync afl++ with honggfuzz, libfuzzer, entropic, etc.
+However you can also sync afl++ with honggfuzz, libfuzzer with -entropic, etc.
 Just show the main fuzzer (-M) with the `-F` option where the queue
 directory of a different fuzzer is, e.g. `-F /src/target/honggfuzz`.
 
@@ -547,7 +560,14 @@ To have only the summary use the `-s` switch e.g.: `afl-whatsup -s output/`
 #### d) Checking the coverage of the fuzzing
 
 The `paths found` value is a bad indicator how good the coverage is.
-It is better to check out the exact lines of code that have been reached -
+
+A better indicator - if you use default llvm instrumentation with at least
+version 9 - to use `afl-showmap` on the target with all inputs of the
+queue/ directory one after another and collecting the found edge IDs (`-o N.out`),
+removing the counters of the edge IDs, making them unique - and there you have
+the total number of found instrumented edges.
+
+It is even better to check out the exact lines of code that have been reached -
 and which have not been found so far.
 
 An "easy" helper script for this is [https://github.com/vanhauser-thc/afl-cov](https://github.com/vanhauser-thc/afl-cov),
@@ -568,6 +588,10 @@ then you can expect that your fuzzing won't be fruitful anymore.
 However often this just means that you should switch out secondaries for
 others, e.g. custom mutator modules, sync to very different fuzzers, etc.
 
+Keep the queue/ directory (for future fuzzings of the same or similar targets)
+and use them to seed other good fuzzers like libfuzzer with the -entropic
+switch or honggfuzz.
+
 #### f) Improve the speed!
 
  * Use [persistent mode](llvm_mode/README.persistent_mode.md) (x2-x20 speed increase)
diff --git a/TODO.md b/TODO.md
index 999cb9d3..e81b82a3 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,7 +2,6 @@
 
 ## Roadmap 2.67+
 
- - expand on AFL_LLVM_INSTRUMENT_FILE to also support sancov allowlist format
  - AFL_MAP_SIZE for qemu_mode and unicorn_mode
  - CPU affinity for many cores? There seems to be an issue > 96 cores
 
diff --git a/custom_mutators/README.md b/custom_mutators/README.md
index a3b164be..3abcfef3 100644
--- a/custom_mutators/README.md
+++ b/custom_mutators/README.md
@@ -1,4 +1,9 @@
-# production ready custom mutators
+# Custom Mutators
+
+Custom mutators enhance and alter the mutation strategies of afl++.
+For further information and documentation on how to write your own, read [the docs](../docs/custom_mutators.md).
+
+## Production-Ready Custom Mutators
 
 This directory holds ready to use custom mutators.
 Just type "make" in the individual subdirectories.
@@ -11,15 +16,15 @@ and add `AFL_CUSTOM_MUTATOR_ONLY=1` if you only want to use the custom mutator.
 
 Multiple custom mutators can be used by separating their paths with `:` in the environment variable.
 
-# Other custom mutators
+## 3rd Party Custom Mutators
 
-## Superion port
+### Superion Mutators
 
 Adrian Tiron ported the Superion grammar fuzzer to afl++, it is WIP and
 requires cmake (among other things):
 [https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
 
-## Protobuf
+### libprotobuf Mutators
 
 There are two WIP protobuf projects, that require work to be working though:
 
diff --git a/custom_mutators/honggfuzz/Makefile b/custom_mutators/honggfuzz/Makefile
index 2f46d0e7..1d46f163 100644
--- a/custom_mutators/honggfuzz/Makefile
+++ b/custom_mutators/honggfuzz/Makefile
@@ -7,6 +7,8 @@ honggfuzz.so:	honggfuzz.c input.h mangle.c ../../src/afl-performance.c
 	$(CC) $(CFLAGS) -I../../include -I. -shared -o honggfuzz.so honggfuzz.c mangle.c ../../src/afl-performance.c
 
 update:
+	@# seriously? --unlink is a dud option? sigh ...
+	rm -f mangle.c mangle.h honggfuzz.h
 	wget --unlink https://github.com/google/honggfuzz/raw/master/mangle.c
 	wget --unlink https://github.com/google/honggfuzz/raw/master/mangle.h
 	wget --unlink https://github.com/google/honggfuzz/raw/master/honggfuzz.h
diff --git a/custom_mutators/honggfuzz/honggfuzz.h b/custom_mutators/honggfuzz/honggfuzz.h
index 4e045272..9d07fdf4 100644
--- a/custom_mutators/honggfuzz/honggfuzz.h
+++ b/custom_mutators/honggfuzz/honggfuzz.h
@@ -38,18 +38,17 @@
 
 #include "libhfcommon/util.h"
 
-#define PROG_NAME "honggfuzz"
-#define PROG_VERSION "2.2"
+#define PROG_NAME    "honggfuzz"
+#define PROG_VERSION "2.3"
 
-/* Name of the template which will be replaced with the proper name of the file
- */
+/* Name of the template which will be replaced with the proper name of the file */
 #define _HF_FILE_PLACEHOLDER "___FILE___"
 
 /* Default name of the report created with some architectures */
 #define _HF_REPORT_FILE "HONGGFUZZ.REPORT.TXT"
 
 /* Default stack-size of created threads. */
-#define _HF_PTHREAD_STACKSIZE (1024ULL * 1024ULL * 2ULL)             /* 2MB */
+#define _HF_PTHREAD_STACKSIZE (1024ULL * 1024ULL * 2ULL) /* 2MB */
 
 /* Name of envvar which indicates sequential number of fuzzer */
 #define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO"
@@ -63,12 +62,11 @@
 /* Number of crash verifier iterations before tag crash as stable */
 #define _HF_VERIFIER_ITER 5
 
-/* Size (in bytes) for report data to be stored in stack before written to file
- */
+/* Size (in bytes) for report data to be stored in stack before written to file */
 #define _HF_REPORT_SIZE 32768
 
 /* Perf bitmap size */
-#define _HF_PERF_BITMAP_SIZE_16M (1024U * 1024U * 16U)
+#define _HF_PERF_BITMAP_SIZE_16M   (1024U * 1024U * 16U)
 #define _HF_PERF_BITMAP_BITSZ_MASK 0x7FFFFFFULL
 /* Maximum number of PC guards (=trace-pc-guard) we support */
 #define _HF_PC_GUARD_MAX (1024ULL * 1024ULL * 64ULL)
@@ -89,7 +87,7 @@
 #define _HF_INPUT_FD 1021
 /* FD used to pass coverage feedback from the fuzzed process */
 #define _HF_COV_BITMAP_FD 1022
-#define _HF_BITMAP_FD _HF_COV_BITMAP_FD   /* Old name for _HF_COV_BITMAP_FD */
+#define _HF_BITMAP_FD     _HF_COV_BITMAP_FD /* Old name for _HF_COV_BITMAP_FD */
 /* FD used to pass data to a persistent process */
 #define _HF_PERSISTENT_FD 1023
 
@@ -105,356 +103,283 @@ static const uint8_t HFReadyTag = 'R';
 /* Maximum number of active fuzzing threads */
 #define _HF_THREAD_MAX 1024U
 
-/* Persistent-binary signature - if found within file, it means it's a
- * persistent mode binary */
+/* Persistent-binary signature - if found within file, it means it's a persistent mode binary */
 #define _HF_PERSISTENT_SIG "\x01_LIBHFUZZ_PERSISTENT_BINARY_SIGNATURE_\x02\xFF"
-/* HF NetDriver signature - if found within file, it means it's a
- * NetDriver-based binary */
+/* HF NetDriver signature - if found within file, it means it's a NetDriver-based binary */
 #define _HF_NETDRIVER_SIG "\x01_LIBHFUZZ_NETDRIVER_BINARY_SIGNATURE_\x02\xFF"
 
-/* printf() nonmonetary separator. According to MacOSX's man it's supported
- * there as well */
+/* printf() nonmonetary separator. According to MacOSX's man it's supported there as well */
 #define _HF_NONMON_SEP "'"
 
 typedef enum {
-
-  _HF_DYNFILE_NONE = 0x0,
-  _HF_DYNFILE_INSTR_COUNT = 0x1,
-  _HF_DYNFILE_BRANCH_COUNT = 0x2,
-  _HF_DYNFILE_BTS_EDGE = 0x10,
-  _HF_DYNFILE_IPT_BLOCK = 0x20,
-  _HF_DYNFILE_SOFT = 0x40,
-
+    _HF_DYNFILE_NONE         = 0x0,
+    _HF_DYNFILE_INSTR_COUNT  = 0x1,
+    _HF_DYNFILE_BRANCH_COUNT = 0x2,
+    _HF_DYNFILE_BTS_EDGE     = 0x10,
+    _HF_DYNFILE_IPT_BLOCK    = 0x20,
+    _HF_DYNFILE_SOFT         = 0x40,
 } dynFileMethod_t;
 
 typedef struct {
-
-  uint64_t cpuInstrCnt;
-  uint64_t cpuBranchCnt;
-  uint64_t bbCnt;
-  uint64_t newBBCnt;
-  uint64_t softCntPc;
-  uint64_t softCntEdge;
-  uint64_t softCntCmp;
-
+    uint64_t cpuInstrCnt;
+    uint64_t cpuBranchCnt;
+    uint64_t bbCnt;
+    uint64_t newBBCnt;
+    uint64_t softCntPc;
+    uint64_t softCntEdge;
+    uint64_t softCntCmp;
 } hwcnt_t;
 
 typedef enum {
-
-  _HF_STATE_UNSET = 0,
-  _HF_STATE_STATIC,
-  _HF_STATE_DYNAMIC_DRY_RUN,
-  _HF_STATE_DYNAMIC_MAIN,
-  _HF_STATE_DYNAMIC_MINIMIZE,
-
+    _HF_STATE_UNSET = 0,
+    _HF_STATE_STATIC,
+    _HF_STATE_DYNAMIC_DRY_RUN,
+    _HF_STATE_DYNAMIC_MAIN,
+    _HF_STATE_DYNAMIC_MINIMIZE,
 } fuzzState_t;
 
 typedef enum {
-
-  HF_MAYBE = -1,
-  HF_NO = 0,
-  HF_YES = 1,
-
+    HF_MAYBE = -1,
+    HF_NO    = 0,
+    HF_YES   = 1,
 } tristate_t;
 
 struct _dynfile_t {
-
-  size_t             size;
-  uint64_t           cov[4];
-  size_t             idx;
-  int                fd;
-  uint64_t           timeExecUSecs;
-  char               path[PATH_MAX];
-  struct _dynfile_t *src;
-  uint32_t           refs;
-  uint8_t *          data;
-  TAILQ_ENTRY(_dynfile_t) pointers;
-
+    size_t             size;
+    uint64_t           cov[4];
+    size_t             idx;
+    int                fd;
+    uint64_t           timeExecUSecs;
+    char               path[PATH_MAX];
+    struct _dynfile_t* src;
+    uint32_t           refs;
+    uint8_t*           data;
+    TAILQ_ENTRY(_dynfile_t) pointers;
 };
 
 typedef struct _dynfile_t dynfile_t;
 
 struct strings_t {
-
-  size_t len;
-  TAILQ_ENTRY(strings_t) pointers;
-  char s[];
-
+    size_t len;
+    TAILQ_ENTRY(strings_t) pointers;
+    char s[];
 };
 
 typedef struct {
-
-  uint8_t  pcGuardMap[_HF_PC_GUARD_MAX];
-  uint8_t  bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
-  uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
-  uint64_t pidNewPC[_HF_THREAD_MAX];
-  uint64_t pidNewEdge[_HF_THREAD_MAX];
-  uint64_t pidNewCmp[_HF_THREAD_MAX];
-  uint64_t guardNb;
-  uint64_t pidTotalPC[_HF_THREAD_MAX];
-  uint64_t pidTotalEdge[_HF_THREAD_MAX];
-  uint64_t pidTotalCmp[_HF_THREAD_MAX];
-
+    uint8_t  pcGuardMap[_HF_PC_GUARD_MAX];
+    uint8_t  bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
+    uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
+    uint64_t pidNewPC[_HF_THREAD_MAX];
+    uint64_t pidNewEdge[_HF_THREAD_MAX];
+    uint64_t pidNewCmp[_HF_THREAD_MAX];
+    uint64_t guardNb;
+    uint64_t pidTotalPC[_HF_THREAD_MAX];
+    uint64_t pidTotalEdge[_HF_THREAD_MAX];
+    uint64_t pidTotalCmp[_HF_THREAD_MAX];
 } feedback_t;
 
 typedef struct {
-
-  uint32_t cnt;
-  struct {
-
-    uint8_t  val[32];
-    uint32_t len;
-
-  } valArr[1024 * 16];
-
+    uint32_t cnt;
+    struct {
+        uint8_t  val[32];
+        uint32_t len;
+    } valArr[1024 * 16];
 } cmpfeedback_t;
 
 typedef struct {
-
-  struct {
-
-    size_t    threadsMax;
-    size_t    threadsFinished;
-    uint32_t  threadsActiveCnt;
-    pthread_t mainThread;
-    pid_t     mainPid;
-    pthread_t threads[_HF_THREAD_MAX];
-
-  } threads;
-
-  struct {
-
-    const char *inputDir;
-    const char *outputDir;
-    DIR *       inputDirPtr;
-    size_t      fileCnt;
-    size_t      testedFileCnt;
-    const char *fileExtn;
-    size_t      maxFileSz;
-    size_t      newUnitsAdded;
-    char        workDir[PATH_MAX];
-    const char *crashDir;
-    const char *covDirNew;
-    bool        saveUnique;
-    size_t      dynfileqMaxSz;
-    size_t      dynfileqCnt;
-    dynfile_t * dynfileqCurrent;
-    dynfile_t * dynfileq2Current;
-    TAILQ_HEAD(dyns_t, _dynfile_t) dynfileq;
-    bool exportFeedback;
-
-  } io;
-
-  struct {
-
-    int                argc;
-    const char *const *cmdline;
-    bool               nullifyStdio;
-    bool               fuzzStdin;
-    const char *       externalCommand;
-    const char *       postExternalCommand;
-    const char *       feedbackMutateCommand;
-    bool               netDriver;
-    bool               persistent;
-    uint64_t           asLimit;
-    uint64_t           rssLimit;
-    uint64_t           dataLimit;
-    uint64_t           coreLimit;
-    uint64_t           stackLimit;
-    bool               clearEnv;
-    char *             env_ptrs[128];
-    char               env_vals[128][4096];
-    sigset_t           waitSigSet;
-
-  } exe;
-
-  struct {
-
-    time_t  timeStart;
-    time_t  runEndTime;
-    time_t  tmOut;
-    time_t  lastCovUpdate;
-    int64_t timeOfLongestUnitUSecs;
-    bool    tmoutVTALRM;
-
-  } timing;
-
-  struct {
-
     struct {
-
-      uint8_t val[256];
-      size_t  len;
-
-    } dictionary[1024];
-
-    size_t      dictionaryCnt;
-    const char *dictionaryFile;
-    size_t      mutationsMax;
-    unsigned    mutationsPerRun;
-    size_t      maxInputSz;
-
-  } mutate;
-
-  struct {
-
-    bool    useScreen;
-    char    cmdline_txt[65];
-    int64_t lastDisplayUSecs;
-
-  } display;
-
-  struct {
-
-    bool        useVerifier;
-    bool        exitUponCrash;
-    const char *reportFile;
-    size_t      dynFileIterExpire;
-    bool        only_printable;
-    bool        minimize;
-    bool        switchingToFDM;
-
-  } cfg;
-
-  struct {
-
-    bool enable;
-    bool del_report;
-
-  } sanitizer;
-
-  struct {
-
-    fuzzState_t     state;
-    feedback_t *    covFeedbackMap;
-    int             covFeedbackFd;
-    cmpfeedback_t * cmpFeedbackMap;
-    int             cmpFeedbackFd;
-    bool            cmpFeedback;
-    const char *    blacklistFile;
-    uint64_t *      blacklist;
-    size_t          blacklistCnt;
-    bool            skipFeedbackOnTimeout;
-    uint64_t        maxCov[4];
-    dynFileMethod_t dynFileMethod;
-    hwcnt_t         hwCnts;
-
-  } feedback;
-
-  struct {
-
-    size_t mutationsCnt;
-    size_t crashesCnt;
-    size_t uniqueCrashesCnt;
-    size_t verifiedCrashesCnt;
-    size_t blCrashesCnt;
-    size_t timeoutedCnt;
-
-  } cnts;
-
-  struct {
-
-    bool enabled;
-    int  serverSocket;
-    int  clientSocket;
-
-  } socketFuzzer;
-
-  struct {
-
-    pthread_rwlock_t dynfileq;
-    pthread_mutex_t  feedback;
-    pthread_mutex_t  report;
-    pthread_mutex_t  state;
-    pthread_mutex_t  input;
-    pthread_mutex_t  timing;
-
-  } mutex;
-
-  /* For the Linux code */
-  struct {
-
-    int         exeFd;
-    uint64_t    dynamicCutOffAddr;
-    bool        disableRandomization;
-    void *      ignoreAddr;
-    const char *symsBlFile;
-    char **     symsBl;
-    size_t      symsBlCnt;
-    const char *symsWlFile;
-    char **     symsWl;
-    size_t      symsWlCnt;
-    uintptr_t   cloneFlags;
-    tristate_t  useNetNs;
-    bool        kernelOnly;
-    bool        useClone;
-
-  } arch_linux;
-
-  /* For the NetBSD code */
-  struct {
-
-    void *      ignoreAddr;
-    const char *symsBlFile;
-    char **     symsBl;
-    size_t      symsBlCnt;
-    const char *symsWlFile;
-    char **     symsWl;
-    size_t      symsWlCnt;
-
-  } arch_netbsd;
-
+        size_t    threadsMax;
+        size_t    threadsFinished;
+        uint32_t  threadsActiveCnt;
+        pthread_t mainThread;
+        pid_t     mainPid;
+        pthread_t threads[_HF_THREAD_MAX];
+    } threads;
+    struct {
+        const char* inputDir;
+        const char* outputDir;
+        DIR*        inputDirPtr;
+        size_t      fileCnt;
+        size_t      testedFileCnt;
+        const char* fileExtn;
+        size_t      maxFileSz;
+        size_t      newUnitsAdded;
+        char        workDir[PATH_MAX];
+        const char* crashDir;
+        const char* covDirNew;
+        bool        saveUnique;
+        size_t      dynfileqMaxSz;
+        size_t      dynfileqCnt;
+        dynfile_t*  dynfileqCurrent;
+        dynfile_t*  dynfileq2Current;
+        TAILQ_HEAD(dyns_t, _dynfile_t) dynfileq;
+        bool exportFeedback;
+    } io;
+    struct {
+        int                argc;
+        const char* const* cmdline;
+        bool               nullifyStdio;
+        bool               fuzzStdin;
+        const char*        externalCommand;
+        const char*        postExternalCommand;
+        const char*        feedbackMutateCommand;
+        bool               netDriver;
+        bool               persistent;
+        uint64_t           asLimit;
+        uint64_t           rssLimit;
+        uint64_t           dataLimit;
+        uint64_t           coreLimit;
+        uint64_t           stackLimit;
+        bool               clearEnv;
+        char*              env_ptrs[128];
+        char               env_vals[128][4096];
+        sigset_t           waitSigSet;
+    } exe;
+    struct {
+        time_t  timeStart;
+        time_t  runEndTime;
+        time_t  tmOut;
+        time_t  lastCovUpdate;
+        int64_t timeOfLongestUnitUSecs;
+        bool    tmoutVTALRM;
+    } timing;
+    struct {
+        struct {
+            uint8_t val[256];
+            size_t  len;
+        } dictionary[1024];
+        size_t      dictionaryCnt;
+        const char* dictionaryFile;
+        size_t      mutationsMax;
+        unsigned    mutationsPerRun;
+        size_t      maxInputSz;
+    } mutate;
+    struct {
+        bool    useScreen;
+        char    cmdline_txt[65];
+        int64_t lastDisplayUSecs;
+    } display;
+    struct {
+        bool        useVerifier;
+        bool        exitUponCrash;
+        const char* reportFile;
+        size_t      dynFileIterExpire;
+        bool        only_printable;
+        bool        minimize;
+        bool        switchingToFDM;
+    } cfg;
+    struct {
+        bool enable;
+        bool del_report;
+    } sanitizer;
+    struct {
+        fuzzState_t     state;
+        feedback_t*     covFeedbackMap;
+        int             covFeedbackFd;
+        cmpfeedback_t*  cmpFeedbackMap;
+        int             cmpFeedbackFd;
+        bool            cmpFeedback;
+        const char*     blacklistFile;
+        uint64_t*       blacklist;
+        size_t          blacklistCnt;
+        bool            skipFeedbackOnTimeout;
+        uint64_t        maxCov[4];
+        dynFileMethod_t dynFileMethod;
+        hwcnt_t         hwCnts;
+    } feedback;
+    struct {
+        size_t mutationsCnt;
+        size_t crashesCnt;
+        size_t uniqueCrashesCnt;
+        size_t verifiedCrashesCnt;
+        size_t blCrashesCnt;
+        size_t timeoutedCnt;
+    } cnts;
+    struct {
+        bool enabled;
+        int  serverSocket;
+        int  clientSocket;
+    } socketFuzzer;
+    struct {
+        pthread_rwlock_t dynfileq;
+        pthread_mutex_t  feedback;
+        pthread_mutex_t  report;
+        pthread_mutex_t  state;
+        pthread_mutex_t  input;
+        pthread_mutex_t  timing;
+    } mutex;
+
+    /* For the Linux code */
+    struct {
+        int         exeFd;
+        uint64_t    dynamicCutOffAddr;
+        bool        disableRandomization;
+        void*       ignoreAddr;
+        const char* symsBlFile;
+        char**      symsBl;
+        size_t      symsBlCnt;
+        const char* symsWlFile;
+        char**      symsWl;
+        size_t      symsWlCnt;
+        uintptr_t   cloneFlags;
+        tristate_t  useNetNs;
+        bool        kernelOnly;
+        bool        useClone;
+    } arch_linux;
+    /* For the NetBSD code */
+    struct {
+        void*       ignoreAddr;
+        const char* symsBlFile;
+        char**      symsBl;
+        size_t      symsBlCnt;
+        const char* symsWlFile;
+        char**      symsWl;
+        size_t      symsWlCnt;
+    } arch_netbsd;
 } honggfuzz_t;
 
 typedef enum {
-
-  _HF_RS_UNKNOWN = 0,
-  _HF_RS_WAITING_FOR_INITIAL_READY = 1,
-  _HF_RS_WAITING_FOR_READY = 2,
-  _HF_RS_SEND_DATA = 3,
-
+    _HF_RS_UNKNOWN                   = 0,
+    _HF_RS_WAITING_FOR_INITIAL_READY = 1,
+    _HF_RS_WAITING_FOR_READY         = 2,
+    _HF_RS_SEND_DATA                 = 3,
 } runState_t;
 
 typedef struct {
-
-  honggfuzz_t *global;
-  pid_t        pid;
-  int64_t      timeStartedUSecs;
-  char         crashFileName[PATH_MAX];
-  uint64_t     pc;
-  uint64_t     backtrace;
-  uint64_t     access;
-  int          exception;
-  char         report[_HF_REPORT_SIZE];
-  bool         mainWorker;
-  unsigned     mutationsPerRun;
-  dynfile_t *  dynfile;
-  bool         staticFileTryMore;
-  uint32_t     fuzzNo;
-  int          persistentSock;
-  runState_t   runState;
-  bool         tmOutSignaled;
-  char *       args[_HF_ARGS_MAX + 1];
-  int          perThreadCovFeedbackFd;
-  unsigned     triesLeft;
-  dynfile_t *  current;
+    honggfuzz_t* global;
+    pid_t        pid;
+    int64_t      timeStartedUSecs;
+    char         crashFileName[PATH_MAX];
+    uint64_t     pc;
+    uint64_t     backtrace;
+    uint64_t     access;
+    int          exception;
+    char         report[_HF_REPORT_SIZE];
+    bool         mainWorker;
+    unsigned     mutationsPerRun;
+    dynfile_t*   dynfile;
+    bool         staticFileTryMore;
+    uint32_t     fuzzNo;
+    int          persistentSock;
+    runState_t   runState;
+    bool         tmOutSignaled;
+    char*        args[_HF_ARGS_MAX + 1];
+    int          perThreadCovFeedbackFd;
+    unsigned     triesLeft;
+    dynfile_t*   current;
 #if !defined(_HF_ARCH_DARWIN)
-  timer_t timerId;
-#endif  // !defined(_HF_ARCH_DARWIN)
-  hwcnt_t hwCnts;
-
-  struct {
-
-    /* For Linux code */
-    uint8_t *perfMmapBuf;
-    uint8_t *perfMmapAux;
-    int      cpuInstrFd;
-    int      cpuBranchFd;
-    int      cpuIptBtsFd;
-
-  } arch_linux;
+    timer_t timerId;
+#endif    // !defined(_HF_ARCH_DARWIN)
+    hwcnt_t hwCnts;
 
+    struct {
+        /* For Linux code */
+        uint8_t* perfMmapBuf;
+        uint8_t* perfMmapAux;
+        int      cpuInstrFd;
+        int      cpuBranchFd;
+        int      cpuIptBtsFd;
+    } arch_linux;
 } run_t;
 
 #endif
-
diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c
index 05e0dcfa..c2988319 100644
--- a/custom_mutators/honggfuzz/mangle.c
+++ b/custom_mutators/honggfuzz/mangle.c
@@ -51,7 +51,7 @@ static inline size_t mangle_LenLeft(run_t *run, size_t off) {
 
 }
 
-/* Get a random value between <1:max> with x^2 distribution */
+/* Get a random value <1:max>, but prefer smaller ones - up to 4KiB */
 static inline size_t mangle_getLen(size_t max) {
 
   if (max > _HF_INPUT_MAX_SIZE) {
@@ -64,27 +64,25 @@ static inline size_t mangle_getLen(size_t max) {
   if (max == 0) { LOG_F("max == 0"); }
   if (max == 1) { return 1; }
 
-  const uint64_t max2 = (uint64_t)max * max;
-  const uint64_t max3 = (uint64_t)max * max * max;
-  const uint64_t rnd = util_rndGet(1, max2 - 1);
+  /* Give 50% chance the the uniform distribution */
+  switch (util_rndGet(0, 9)) {
 
-  uint64_t ret = rnd * rnd;
-  ret /= max3;
-  ret += 1;
-
-  if (ret < 1) {
-
-    LOG_F("ret (%" PRIu64 ") < 1, max:%zu, rnd:%" PRIu64, ret, max, rnd);
-
-  }
-
-  if (ret > max) {
-
-    LOG_F("ret (%" PRIu64 ") > max (%zu), rnd:%" PRIu64, ret, max, rnd);
+    case 0:
+      return (size_t)util_rndGet(1, HF_MIN(16, max));
+    case 1:
+      return (size_t)util_rndGet(1, HF_MIN(64, max));
+    case 2:
+      return (size_t)util_rndGet(1, HF_MIN(256, max));
+    case 3:
+      return (size_t)util_rndGet(1, HF_MIN(1024, max));
+    case 4:
+      return (size_t)util_rndGet(1, HF_MIN(4096, max));
+    default:
+      break;
 
   }
 
-  return (size_t)ret;
+  return (size_t)util_rndGet(1, max);
 
 }
 
diff --git a/custom_mutators/honggfuzz/mangle.h b/custom_mutators/honggfuzz/mangle.h
index 1b6a4943..f8f3988c 100644
--- a/custom_mutators/honggfuzz/mangle.h
+++ b/custom_mutators/honggfuzz/mangle.h
@@ -26,7 +26,6 @@
 
 #include "honggfuzz.h"
 
-extern void mangle_mangleContent(run_t *run, int speed_factor);
+extern void mangle_mangleContent(run_t* run, int speed_factor);
 
 #endif
-
diff --git a/docs/Changelog.md b/docs/Changelog.md
index ae7377f2..edcdac58 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -22,8 +22,16 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
      - fixed a bug in redqueen for strings
   - llvm_mode:
      - now supports llvm 12!
+     - support for AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST (previous
+       AFL_LLVM_WHITELIST and AFL_LLVM_INSTRUMENT_FILE are deprecated and
+       are matched to AFL_LLVM_ALLOWLIST). The format is compatible to llvm
+       sancov, and also supports function matching!
+     - added neverzero counting to trace-pc/pcgard
      - fixes for laf-intel float splitting (thanks to mark-griffin for
        reporting)
+     - LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR
+            for a fixed map address (eg. 0x10000)
+     - LTO: skipping ctors and ifuncs in fix map address instrumentation
      - LTO: autodictionary mode is a default
      - LTO: instrim instrumentation disabled, only classic support used
             as it is always better
@@ -33,6 +41,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
      - LTO: AFL_LLVM_SKIP_NEVERZERO behaviour was inversed, fixed
      - setting AFL_LLVM_LAF_SPLIT_FLOATS now activates
        AFL_LLVM_LAF_SPLIT_COMPARES
+     - support for -E and -shared compilation runs
   - added honggfuzz mangle as a custom mutator in custom_mutators/honggfuzz
   - added afl-frida gum solution to examples/afl_frida (mostly imported
     from https://github.com/meme/hotwax/)
diff --git a/docs/FAQ.md b/docs/FAQ.md
index c15cd484..e690635a 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -112,12 +112,13 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation!
         on start, check to which memory address the edge ID value is written
         and set a write breakpoint to that address (`watch 0x.....`).
 
-  3. Third step: create a text file with the filenames
+  3. Third step: create a text file with the filenames/functions
 
      Identify which source code files contain the functions that you need to
-     remove from instrumentation.
+     remove from instrumentation, or just specify the functions you want to
+     skip instrumenting. Note that optimization might inline functions!
 
-     Simply follow this document on how to do this: [llvm_mode/README.instrument_file.md](llvm_mode/README.instrument_file.md)
+     Simply follow this document on how to do this: [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md)
      If PCGUARD is used, then you need to follow this guide (needs llvm 12+!):
      [http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation](http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation)
 
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 811c5658..f0ae0b6c 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -202,14 +202,15 @@ Then there are a few specific features that are only available in llvm_mode:
 
     See llvm_mode/README.laf-intel.md for more information.
 
-### INSTRUMENT_FILE
+### INSTRUMENT LIST (selectively instrument files and functions)
 
     This feature allows selectively instrumentation of the source
 
-    - Setting AFL_LLVM_INSTRUMENT_FILE with a filename will only instrument those
-      files that match the names listed in this file.
+    - Setting AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST with a filenames and/or
+      function will only instrument (or skip) those files that match the names
+      listed in the specified file.
 
-    See llvm_mode/README.instrument_file.md for more information.
+    See llvm_mode/README.instrument_list.md for more information.
 
 ### NOT_ZERO
 
@@ -241,7 +242,7 @@ Then there are a few specific features that are only available in the gcc_plugin
     - Setting AFL_GCC_INSTRUMENT_FILE with a filename will only instrument those
       files that match the names listed in this file (one filename per line).
 
-    See gcc_plugin/README.instrument_file.md for more information.
+    See gcc_plugin/README.instrument_list.md for more information.
 
 ## 3) Settings for afl-fuzz
 
diff --git a/docs/perf_tips.md b/docs/perf_tips.md
index 7a690b77..731dc238 100644
--- a/docs/perf_tips.md
+++ b/docs/perf_tips.md
@@ -67,7 +67,7 @@ to get to the important parts in the code.
 
 If you are only interested in specific parts of the code being fuzzed, you can
 instrument_files the files that are actually relevant. This improves the speed and
-accuracy of afl. See llvm_mode/README.instrument_file.md
+accuracy of afl. See llvm_mode/README.instrument_list.md
 
 Also use the InsTrim mode on larger binaries, this improves performance and
 coverage a lot.
diff --git a/dynamic_list.txt b/dynamic_list.txt
new file mode 100644
index 00000000..3c0b054f
--- /dev/null
+++ b/dynamic_list.txt
@@ -0,0 +1,10 @@
+{
+  "__afl_area_ptr";
+  "__afl_manual_init";
+  "__afl_persistent_loop";
+  "__afl_auto_init";
+  "__afl_area_initial";
+  "__afl_prev_loc";
+  "__sanitizer_cov_trace_pc_guard";
+  "__sanitizer_cov_trace_pc_guard_init";
+};
diff --git a/examples/aflpp_driver/aflpp_driver.c b/examples/aflpp_driver/aflpp_driver.c
index 86c7a69f..7d388799 100644
--- a/examples/aflpp_driver/aflpp_driver.c
+++ b/examples/aflpp_driver/aflpp_driver.c
@@ -56,13 +56,21 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both.
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <sys/mman.h>
 
 #include "config.h"
+#include "cmplog.h"
 
 #ifdef _DEBUG
   #include "hash.h"
 #endif
 
+#ifndef MAP_FIXED_NOREPLACE
+  #define MAP_FIXED_NOREPLACE 0x100000
+#endif
+
+#define MAX_DUMMY_SIZE 256000
+
 // Platform detection. Copied from FuzzerInternal.h
 #ifdef __linux__
   #define LIBFUZZER_LINUX 1
@@ -101,6 +109,8 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both.
 int                   __afl_sharedmem_fuzzing = 1;
 extern unsigned int * __afl_fuzz_len;
 extern unsigned char *__afl_fuzz_ptr;
+extern unsigned char *__afl_area_ptr;
+// extern struct cmp_map *__afl_cmp_map;
 
 // libFuzzer interface is thin, so we don't include any libFuzzer headers.
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
@@ -238,26 +248,50 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
 
 }
 
+__attribute__((constructor(1))) void __afl_protect(void) {
+
+  setenv("__AFL_DEFER_FORKSRV", "1", 1);
+  __afl_area_ptr = (unsigned char *)mmap(
+      (void *)0x10000, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE,
+      MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  if ((uint64_t)__afl_area_ptr == -1)
+    __afl_area_ptr = (unsigned char *)mmap((void *)0x10000, MAX_DUMMY_SIZE,
+                                           PROT_READ | PROT_WRITE,
+                                           MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  if ((uint64_t)__afl_area_ptr == -1)
+    __afl_area_ptr =
+        (unsigned char *)mmap(NULL, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE,
+                              MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  // __afl_cmp_map = (struct cmp_map *)__afl_area_ptr;
+
+}
+
 int main(int argc, char **argv) {
 
+  fprintf(stderr, "dummy map is at %p\n", __afl_area_ptr);
+
   printf(
       "======================= INFO =========================\n"
-      "This binary is built for AFL-fuzz.\n"
+      "This binary is built for afl++.\n"
       "To run the target function on individual input(s) execute this:\n"
-      "  %s < INPUT_FILE\n"
-      "or\n"
       "  %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
       "To fuzz with afl-fuzz execute this:\n"
-      "  afl-fuzz [afl-flags] %s [-N]\n"
-      "afl-fuzz will run N iterations before "
-      "re-spawning the process (default: 1000)\n"
+      "  afl-fuzz [afl-flags] -- %s [-N]\n"
+      "afl-fuzz will run N iterations before re-spawning the process (default: "
+      "1000)\n"
       "======================================================\n",
-      argv[0], argv[0], argv[0]);
+      argv[0], argv[0]);
 
   output_file = stderr;
   maybe_duplicate_stderr();
   maybe_close_fd_mask();
-  if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv);
+  if (LLVMFuzzerInitialize) {
+
+    fprintf(stderr, "Running LLVMFuzzerInitialize ...\n");
+    LLVMFuzzerInitialize(&argc, &argv);
+    fprintf(stderr, "continue...\n");
+
+  }
 
   // Do any other expensive one-time initialization here.
 
@@ -272,19 +306,19 @@ int main(int argc, char **argv) {
     printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
   else if (argc > 1) {
 
-    //    if (!getenv("AFL_DRIVER_DONT_DEFER")) {
-
     __afl_sharedmem_fuzzing = 0;
+    munmap(__afl_area_ptr, MAX_DUMMY_SIZE);  // we need to free 0x10000
+    __afl_area_ptr = NULL;
     __afl_manual_init();
-    //    }
     return ExecuteFilesOnyByOne(argc, argv);
-    exit(0);
 
   }
 
   assert(N > 0);
 
   //  if (!getenv("AFL_DRIVER_DONT_DEFER"))
+  munmap(__afl_area_ptr, MAX_DUMMY_SIZE);
+  __afl_area_ptr = NULL;
   __afl_manual_init();
 
   // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
diff --git a/gcc_plugin/GNUmakefile b/gcc_plugin/GNUmakefile
index 4a4f0dcd..f10a6c1d 100644
--- a/gcc_plugin/GNUmakefile
+++ b/gcc_plugin/GNUmakefile
@@ -163,7 +163,7 @@ install: all
 	install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
 	install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
 	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
-	install -m 644 -T README.instrument_file.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md
+	install -m 644 -T README.instrument_list.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md
 
 clean:
 	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile
index f720112f..c088b61c 100644
--- a/gcc_plugin/Makefile
+++ b/gcc_plugin/Makefile
@@ -152,7 +152,7 @@ install: all
 	install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
 	install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
 	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
-	install -m 644 -T README.instrument_file.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md
+	install -m 644 -T README.instrument_list.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md
 
 clean:
 	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
diff --git a/gcc_plugin/README.instrument_file.md b/gcc_plugin/README.instrument_list.md
index d0eaf6ff..d0eaf6ff 100644
--- a/gcc_plugin/README.instrument_file.md
+++ b/gcc_plugin/README.instrument_list.md
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index b82ddb4a..51ab0e85 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -656,6 +656,7 @@ typedef struct afl_state {
 struct custom_mutator {
 
   const char *name;
+  char *      name_short;
   void *      dh;
   u8 *        post_process_buf;
   size_t      post_process_size;
@@ -986,6 +987,8 @@ uint64_t rand_next(afl_state_t *afl);
 
 static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
+  if (limit <= 1) return 0;
+
   /* The boundary not being necessarily a power of 2,
      we need to ensure the result uniformity. */
   if (unlikely(!afl->rand_cnt--) && likely(!afl->fixed_seed)) {
@@ -1001,6 +1004,32 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
 }
 
+/* we prefer lower range values here */
+/* this is only called with normal havoc, not MOpt, to have an equalizer for
+   expand havoc mode */
+static inline u32 rand_below_datalen(afl_state_t *afl, u32 limit) {
+
+  if (limit <= 1) return 0;
+
+  switch (rand_below(afl, 3)) {
+
+    case 2:
+      return (rand_below(afl, limit) % (1 + rand_below(afl, limit - 1))) %
+             (1 + rand_below(afl, limit - 1));
+      break;
+    case 1:
+      return rand_below(afl, limit) % (1 + rand_below(afl, limit - 1));
+      break;
+    case 0:
+      return rand_below(afl, limit);
+      break;
+
+  }
+
+  return 1;  // cannot be reached
+
+}
+
 static inline s64 rand_get_seed(afl_state_t *afl) {
 
   if (unlikely(afl->fixed_seed)) { return afl->init_seed; }
diff --git a/include/debug.h b/include/debug.h
index d1bd971b..f9ebce58 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -28,11 +28,6 @@
 #include "types.h"
 #include "config.h"
 
-/* __FUNCTION__ is non-iso */
-#ifdef __func__
-  #define __FUNCTION__ __func__
-#endif
-
 /*******************
  * Terminal colors *
  *******************/
@@ -223,43 +218,43 @@
 
 /* Die with a verbose non-OS fatal error message. */
 
-#define FATAL(x...)                                                          \
-  do {                                                                       \
-                                                                             \
-    SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                                \
-         "\n[-] PROGRAM ABORT : " cRST   x);                                   \
-    SAYF(cLRD "\n         Location : " cRST "%s(), %s:%u\n\n", __FUNCTION__, \
-         __FILE__, __LINE__);                                                \
-    exit(1);                                                                 \
-                                                                             \
+#define FATAL(x...)                                                      \
+  do {                                                                   \
+                                                                         \
+    SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                            \
+         "\n[-] PROGRAM ABORT : " cRST   x);                               \
+    SAYF(cLRD "\n         Location : " cRST "%s(), %s:%u\n\n", __func__, \
+         __FILE__, __LINE__);                                            \
+    exit(1);                                                             \
+                                                                         \
   } while (0)
 
 /* Die by calling abort() to provide a core dump. */
 
-#define ABORT(x...)                                                          \
-  do {                                                                       \
-                                                                             \
-    SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                                \
-         "\n[-] PROGRAM ABORT : " cRST   x);                                   \
-    SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n\n", __FUNCTION__, \
-         __FILE__, __LINE__);                                                \
-    abort();                                                                 \
-                                                                             \
+#define ABORT(x...)                                                      \
+  do {                                                                   \
+                                                                         \
+    SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                            \
+         "\n[-] PROGRAM ABORT : " cRST   x);                               \
+    SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
+         __FILE__, __LINE__);                                            \
+    abort();                                                             \
+                                                                         \
   } while (0)
 
 /* Die while also including the output of perror(). */
 
-#define PFATAL(x...)                                                       \
-  do {                                                                     \
-                                                                           \
-    fflush(stdout);                                                        \
-    SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                              \
-         "\n[-]  SYSTEM ERROR : " cRST   x);                                 \
-    SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n", __FUNCTION__, \
-         __FILE__, __LINE__);                                              \
-    SAYF(cLRD "       OS message : " cRST "%s\n", strerror(errno));        \
-    exit(1);                                                               \
-                                                                           \
+#define PFATAL(x...)                                                   \
+  do {                                                                 \
+                                                                       \
+    fflush(stdout);                                                    \
+    SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                          \
+         "\n[-]  SYSTEM ERROR : " cRST   x);                             \
+    SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n", __func__, \
+         __FILE__, __LINE__);                                          \
+    SAYF(cLRD "       OS message : " cRST "%s\n", strerror(errno));    \
+    exit(1);                                                           \
+                                                                       \
   } while (0)
 
 /* Die with FATAL() or PFATAL() depending on the value of res (used to
@@ -281,7 +276,7 @@
 #define ck_write(fd, buf, len, fn)                            \
   do {                                                        \
                                                               \
-    u32 _len = (len);                                         \
+    s32 _len = (s32)(len);                                    \
     s32 _res = write(fd, buf, _len);                          \
     if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \
                                                               \
@@ -290,7 +285,7 @@
 #define ck_read(fd, buf, len, fn)                              \
   do {                                                         \
                                                                \
-    u32 _len = (len);                                          \
+    s32 _len = (s32)(len);                                     \
     s32 _res = read(fd, buf, _len);                            \
     if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \
                                                                \
diff --git a/include/envs.h b/include/envs.h
index 7153ed47..96ae91ba 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -62,6 +62,9 @@ static char *afl_environment_variables[] = {
     "AFL_REAL_LD",
     "AFL_LD_PRELOAD",
     "AFL_LD_VERBOSE",
+    "AFL_LLVM_ALLOWLIST",
+    "AFL_LLVM_DENYLIST",
+    "AFL_LLVM_BLOCKLIST",
     "AFL_LLVM_CMPLOG",
     "AFL_LLVM_INSTRIM",
     "AFL_LLVM_CTX",
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile
index a030b910..0fa9b12e 100644
--- a/llvm_mode/GNUmakefile
+++ b/llvm_mode/GNUmakefile
@@ -387,20 +387,20 @@ endif
 	$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
 
 document:
-	$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o
-	@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
-	@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+	$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o
+	@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+	@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 ../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
-	$(CLANG_BIN) $(CFLAGS_SAFE) -O3 -Wno-unused-result -fPIC -c $< -o $@
+	$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -fPIC -c $< -o $@
 
 ../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
 	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
-	@$(CLANG_BIN) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+	@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 ../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps
 	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
-	@$(CLANG_BIN) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+	@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 test_build: $(PROGS)
 	@echo "[*] Testing the CC wrapper and instrumentation output..."
@@ -427,6 +427,7 @@ install: all
 	if [ -f ../split-compares-pass.so ]; then set -e; install -m 755 ../split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi
 	if [ -f ../split-switches-pass.so ]; then set -e; install -m 755 ../split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi
 	if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); fi
+	set -e; install -m 644 ../dynamic_list.txt $${DESTDIR}$(HELPER_PATH)
 	set -e; if [ -f ../afl-clang-fast ] ; then ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
 	install -m 644 README.*.md $${DESTDIR}$(DOC_PATH)/
 	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md
diff --git a/llvm_mode/README.instrument_file.md b/llvm_mode/README.instrument_file.md
deleted file mode 100644
index 46e45ba2..00000000
--- a/llvm_mode/README.instrument_file.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Using afl++ with partial instrumentation
-
-  This file describes how you can selectively instrument only the source files
-  that are interesting to you using the LLVM instrumentation provided by
-  afl++
-
-  Originally developed by Christian Holler (:decoder) <choller@mozilla.com>.
-
-## 1) Description and purpose
-
-When building and testing complex programs where only a part of the program is
-the fuzzing target, it often helps to only instrument the necessary parts of
-the program, leaving the rest uninstrumented. This helps to focus the fuzzer
-on the important parts of the program, avoiding undesired noise and
-disturbance by uninteresting code being exercised.
-
-For this purpose, I have added a "partial instrumentation" support to the LLVM
-mode of AFLFuzz that allows you to specify on a source file level which files
-should be compiled with or without instrumentation.
-
-Note: When using PCGUARD mode - and have llvm 12+ - you can use this instead:
-https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
-
-## 2) Building the LLVM module
-
-The new code is part of the existing afl++ LLVM module in the llvm_mode/
-subdirectory. There is nothing specifically to do :)
-
-
-## 3) How to use the partial instrumentation mode
-
-In order to build with partial instrumentation, you need to build with
-afl-clang-fast and afl-clang-fast++ respectively. The only required change is
-that you need to set the environment variable AFL_LLVM_INSTRUMENT_FILE when calling
-the compiler.
-
-The environment variable must point to a file containing all the filenames
-that should be instrumented. For matching, the filename that is being compiled
-must end in the filename entry contained in this the instrument file list (to avoid breaking
-the matching when absolute paths are used during compilation).
-
-For example if your source tree looks like this:
-
-```
-project/
-project/feature_a/a1.cpp
-project/feature_a/a2.cpp
-project/feature_b/b1.cpp
-project/feature_b/b2.cpp
-```
-
-and you only want to test feature_a, then create a the instrument file list file containing:
-
-```
-feature_a/a1.cpp
-feature_a/a2.cpp
-```
-
-However if the instrument file list file contains only this, it works as well:
-
-```
-a1.cpp
-a2.cpp
-```
-
-but it might lead to files being unwantedly instrumented if the same filename
-exists somewhere else in the project directories.
-
-The created the instrument file list file is then set to AFL_LLVM_INSTRUMENT_FILE when you compile
-your program. For each file that didn't match the the instrument file list, the compiler will
-issue a warning at the end stating that no blocks were instrumented. If you
-didn't intend to instrument that file, then you can safely ignore that warning.
-
-For old LLVM versions this feature might require to be compiled with debug
-information (-g), however at least from llvm version 6.0 onwards this is not
-required anymore (and might hurt performance and crash detection, so better not
-use -g).
-
-## 4) UNIX-style filename pattern matching
-You can add UNIX-style pattern matching in the the instrument file list entries. See `man
-fnmatch` for the syntax. We do not set any of the `fnmatch` flags.
diff --git a/llvm_mode/README.instrument_list.md b/llvm_mode/README.instrument_list.md
new file mode 100644
index 00000000..d4739dda
--- /dev/null
+++ b/llvm_mode/README.instrument_list.md
@@ -0,0 +1,86 @@
+# Using afl++ with partial instrumentation
+
+  This file describes how you can selectively instrument only the source files
+  or functions that are interesting to you using the LLVM instrumentation
+  provided by afl++
+
+## 1) Description and purpose
+
+When building and testing complex programs where only a part of the program is
+the fuzzing target, it often helps to only instrument the necessary parts of
+the program, leaving the rest uninstrumented. This helps to focus the fuzzer
+on the important parts of the program, avoiding undesired noise and
+disturbance by uninteresting code being exercised.
+
+For this purpose, a "partial instrumentation" support en par with llvm sancov
+is provided by afl++ that allows you to specify on a source file and function
+level which should be compiled with or without instrumentation.
+
+Note: When using PCGUARD mode - and have llvm 12+ - you can use this instead:
+https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
+
+the llvm sancov list format is fully supported by afl++, however afl++ has
+more flexbility.
+
+## 2) Building the LLVM module
+
+The new code is part of the existing afl++ LLVM module in the llvm_mode/
+subdirectory. There is nothing specifically to do :)
+
+## 3) How to use the partial instrumentation mode
+
+In order to build with partial instrumentation, you need to build with
+afl-clang-fast/afl-clang-fast++ or afl-clang-lto/afl-clang-lto++.
+The only required change is that you need to set either the environment variable
+AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST set with a filename.
+
+That file then contains the filenames or functions that should be instrumented
+(AFL_LLVM_ALLOWLIST) or should specifically NOT instrumentd (AFL_LLVM_DENYLIST).
+
+For matching, the function/filename that is being compiled must end in the
+function/filename entry contained in this the instrument file list (to avoid
+breaking the matching when absolute paths are used during compilation).
+
+**NOTE:** In optimization functions might be inlined and then not match!
+
+For example if your source tree looks like this:
+```
+project/
+project/feature_a/a1.cpp
+project/feature_a/a2.cpp
+project/feature_b/b1.cpp
+project/feature_b/b2.cpp
+```
+
+and you only want to test feature_a, then create a the instrument file list file containing:
+```
+feature_a/a1.cpp
+feature_a/a2.cpp
+```
+
+However if the instrument file list file contains only this, it works as well:
+```
+a1.cpp
+a2.cpp
+```
+but it might lead to files being unwantedly instrumented if the same filename
+exists somewhere else in the project directories.
+
+You can also specify function names. Note that for C++ the function names
+must be mangled to match!
+
+afl++ is intelligent to identify if an entry is a filename or a function.
+However if you want to be sure (and compliant to the sancov allow/blocklist
+format), you can specify source file entries like this:
+```
+src: *malloc.c
+```
+and function entries like this:
+```
+fun: MallocFoo
+```
+Note that whitespace is ignored and comments (`# foo`) supported.
+
+## 4) UNIX-style pattern matching
+You can add UNIX-style pattern matching in the the instrument file list entries.
+See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags.
diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md
index e521ac82..9046c5a8 100644
--- a/llvm_mode/README.lto.md
+++ b/llvm_mode/README.lto.md
@@ -17,9 +17,6 @@ This version requires a current llvm 11+ compiled from the github master.
 5. If any problems arise be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`.
    Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`.
 
-6. If a target uses _init functions or early constructors then additionally
-   set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise!
-
 ## Introduction and problem description
 
 A big issue with how afl/afl++ works is that the basic block IDs that are
@@ -108,15 +105,12 @@ make install
 
 Just use afl-clang-lto like you did with afl-clang-fast or afl-gcc.
 
-Also the instrument file listing (AFL_LLVM_INSTRUMENT_FILE -> [README.instrument_file.md](README.instrument_file.md)) and
+Also the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST -> [README.instrument_list.md](README.instrument_list.md)) and
 laf-intel/compcov (AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work.
-InsTrim (control flow graph instrumentation) is supported and recommended!
-  (set `AFL_LLVM_INSTRUMENT=CFG`)
 
 Example:
 ```
 CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar ./configure
-export AFL_LLVM_INSTRUMENT=CFG
 make
 ```
 
@@ -131,14 +125,14 @@ on start. This improves coverage statistically by 5-10% :)
 
 ## Fixed memory map
 
-To speed up fuzzing, the shared memory map is hard set to a specific address,
-by default 0x10000. In most cases this will work without any problems.
+To speed up fuzzing, it is possible to set a fixed shared memory map.
+Recommened is the value 0x10000.
+In most cases this will work without any problems. However if a target uses
+early constructors, ifuncs or a deferred forkserver this can crash the target.
 On unusual operating systems/processors/kernels or weird libraries this might
 fail so to change the fixed address at compile time set
 AFL_LLVM_MAP_ADDR with a better value (a value of 0 or empty sets the map address
 to be dynamic - the original afl way, which is slower).
-AFL_LLVM_MAP_DYNAMIC can be set so the shared memory address is dynamic (which
-is safer but also slower).
 
 ## Document edge IDs
 
@@ -265,15 +259,6 @@ If this succeeeds then there is an issue with afl-clang-lto. Please report at
 Even some targets where clang-12 fails can be build if the fail is just in
 `./configure`, see `Solving difficult targets` above.
 
-### Target crashes immediately
-
-If the target is using early constructors (priority values smaller than 6)
-or have their own _init/.init functions and these are instrumented then the
-target will likely crash when started. This can be avoided by compiling with
-`AFL_LLVM_MAP_DYNAMIC=1` .
-
-This can e.g. happen with OpenSSL.
-
 ## History
 
 This was originally envisioned by hexcoder- in Summer 2019, however we saw no
diff --git a/llvm_mode/README.md b/llvm_mode/README.md
index 22088dfd..f23d7150 100644
--- a/llvm_mode/README.md
+++ b/llvm_mode/README.md
@@ -109,7 +109,7 @@ Several options are present to make llvm_mode faster or help it rearrange
 the code to make afl-fuzz path discovery easier.
 
 If you need just to instrument specific parts of the code, you can the instrument file list
-which C/C++ files to actually instrument. See [README.instrument_file](README.instrument_file.md)
+which C/C++ files to actually instrument. See [README.instrument_list](README.instrument_list.md)
 
 For splitting memcmp, strncmp, etc. please see [README.laf-intel](README.laf-intel.md)
 
diff --git a/llvm_mode/README.persistent_mode.md b/llvm_mode/README.persistent_mode.md
index 4f0bcb2e..7d2fd93b 100644
--- a/llvm_mode/README.persistent_mode.md
+++ b/llvm_mode/README.persistent_mode.md
@@ -115,6 +115,33 @@ will keep working normally when compiled with a tool other than afl-clang-fast.
 Finally, recompile the program with afl-clang-fast (afl-gcc or afl-clang will
 *not* generate a deferred-initialization binary) - and you should be all set!
 
+*NOTE:* In the code between `main` and `__AFL_INIT()` should not be any code
+run that is instrumented - otherwise a crash might occure.
+In case this is useful (e.g. for expensive one time initialization) you can
+try to do the following:
+
+Add after the includes:
+```
+extern unsigned char *__afl_area_ptr;
+#define MAX_DUMMY_SIZE 256000
+
+__attribute__((constructor(1))) void __afl_protect(void) {
+#ifdef MAP_FIXED_NOREPLACE
+  __afl_area_ptr = (unsigned char*) mmap((void *)0x10000, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  if ((uint64_t)__afl_area_ptr == -1)
+#endif
+    __afl_area_ptr = (unsigned char*) mmap((void *)0x10000, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  if ((uint64_t)__afl_area_ptr == -1)
+    __afl_area_ptr = (unsigned char*) mmap(NULL, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+```
+and just before `__AFL_INIT()`:
+```
+  munmap(__afl_area_ptr, MAX_DUMMY_SIZE);
+  __afl_area_ptr = NULL;
+```
+
 ## 4) persistent mode
 
 Some libraries provide APIs that are stateless, or whose state can be reset in
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index ef99e3f3..efaba122 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -161,7 +161,8 @@ static void find_obj(u8 *argv0) {
 
 static void edit_params(u32 argc, char **argv, char **envp) {
 
-  u8  fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0;
+  u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
+     preprocessor_only = 0;
   u8  have_pic = 0;
   u8 *name;
 
@@ -229,7 +230,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   if (lto_mode) {
 
     if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-        getenv("AFL_LLVM_WHITELIST")) {
+        getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+        getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
 
       cc_params[cc_par_cnt++] = "-Xclang";
       cc_params[cc_par_cnt++] = "-load";
@@ -399,6 +401,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
     if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
 
+    if (!strcmp(cur, "-E")) preprocessor_only = 1;
+    if (!strcmp(cur, "-shared")) shared_linking = 1;
+
     cc_params[cc_par_cnt++] = cur;
 
   }
@@ -563,6 +568,18 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
   }
 
+  if (preprocessor_only) {
+
+    /* In the preprocessor_only case (-E), we are not actually compiling at
+       all but requesting the compiler to output preprocessed sources only.
+       We must not add the runtime in this case because the compiler will
+       simply output its binary content back on stdout, breaking any build
+       systems that rely on a separate source preprocessing step. */
+    cc_params[cc_par_cnt] = NULL;
+    return;
+
+  }
+
 #ifndef __ANDROID__
   switch (bit_mode) {
 
@@ -605,6 +622,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
   }
 
+  if (!shared_linking)
+    cc_params[cc_par_cnt++] =
+        alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
+
 #endif
 
   cc_params[cc_par_cnt] = NULL;
@@ -637,9 +658,13 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
-  if ((getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) &&
+  if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
+       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) &&
       getenv("AFL_DONT_OPTIMIZE"))
-    FATAL("AFL_LLVM_INSTRUMENT_FILE and AFL_DONT_OPTIMIZE cannot be combined");
+    WARNF(
+        "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
+        "for file matching, only function matching!");
 
   if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
       getenv("INSTRIM_LIB")) {
@@ -787,15 +812,17 @@ int main(int argc, char **argv, char **envp) {
 #if LLVM_VERSION_MAJOR <= 6
     instrument_mode = INSTRUMENT_AFL;
 #else
-    if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) {
+    if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
+        getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+        getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
 
       instrument_mode = INSTRUMENT_AFL;
       WARNF(
           "switching to classic instrumentation because "
-          "AFL_LLVM_INSTRUMENT_FILE does not work with PCGUARD. Use "
-          "-fsanitize-coverage-allowlist=allowlist.txt if you want to use "
-          "PCGUARD. Requires llvm 12+. See "
-          "https://clang.llvm.org/docs/"
+          "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use "
+          "-fsanitize-coverage-allowlist=allowlist.txt or "
+          "-fsanitize-coverage-blocklist=denylist.txt if you want to use "
+          "PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ "
           "SanitizerCoverage.html#partially-disabling-instrumentation");
 
     } else
@@ -846,11 +873,14 @@ int main(int argc, char **argv, char **envp) {
         "together");
 
   if (instrument_mode == INSTRUMENT_PCGUARD &&
-      (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")))
+      (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
+       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
     FATAL(
         "Instrumentation type PCGUARD does not support "
-        "AFL_LLVM_INSTRUMENT_FILE! Use "
-        "-fsanitize-coverage-allowlist=allowlist.txt instead (requires llvm "
+        "AFL_LLVM_ALLOWLIST/DENYLIST! Use "
+        "-fsanitize-coverage-allowlist=allowlist.txt or "
+        "-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm "
         "12+), see "
         "https://clang.llvm.org/docs/"
         "SanitizerCoverage.html#partially-disabling-instrumentation");
diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc
index 9a884ded..0b50c547 100644
--- a/llvm_mode/afl-llvm-common.cc
+++ b/llvm_mode/afl-llvm-common.cc
@@ -20,7 +20,10 @@
 
 using namespace llvm;
 
-static std::list<std::string> myInstrumentList;
+static std::list<std::string> allowListFiles;
+static std::list<std::string> allowListFunctions;
+static std::list<std::string> denyListFiles;
+static std::list<std::string> denyListFunctions;
 
 char *getBBName(const llvm::BasicBlock *BB) {
 
@@ -57,7 +60,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
       "asan.",
       "llvm.",
       "sancov.",
-      "__ubsan_handle_",
+      "__ubsan_",
       "ign.",
       "__afl_",
       "_fini",
@@ -87,30 +90,166 @@ bool isIgnoreFunction(const llvm::Function *F) {
 
 void initInstrumentList() {
 
-  char *instrumentListFilename = getenv("AFL_LLVM_INSTRUMENT_FILE");
-  if (!instrumentListFilename)
-    instrumentListFilename = getenv("AFL_LLVM_WHITELIST");
+  char *allowlist = getenv("AFL_LLVM_ALLOWLIST");
+  if (!allowlist) allowlist = getenv("AFL_LLVM_INSTRUMENT_FILE");
+  if (!allowlist) allowlist = getenv("AFL_LLVM_WHITELIST");
+  char *denylist = getenv("AFL_LLVM_DENYLIST");
+  if (!denylist) denylist = getenv("AFL_LLVM_BLOCKLIST");
 
-  if (instrumentListFilename) {
+  if (allowlist && denylist)
+    FATAL(
+        "You can only specify either AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST "
+        "but not both!");
+
+  if (allowlist) {
 
     std::string   line;
     std::ifstream fileStream;
-    fileStream.open(instrumentListFilename);
-    if (!fileStream)
-      report_fatal_error("Unable to open AFL_LLVM_INSTRUMENT_FILE");
+    fileStream.open(allowlist);
+    if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_ALLOWLIST");
     getline(fileStream, line);
+
     while (fileStream) {
 
-      myInstrumentList.push_back(line);
-      getline(fileStream, line);
+      int         is_file = -1;
+      std::size_t npos;
+      std::string original_line = line;
+
+      line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
+                 line.end());
+
+      // remove # and following
+      if ((npos = line.find("#")) != std::string::npos)
+        line = line.substr(0, npos);
+
+      if (line.compare(0, 4, "fun:") == 0) {
+
+        is_file = 0;
+        line = line.substr(4);
+
+      } else if (line.compare(0, 9, "function:") == 0) {
+
+        is_file = 0;
+        line = line.substr(9);
+
+      } else if (line.compare(0, 4, "src:") == 0) {
+
+        is_file = 1;
+        line = line.substr(4);
+
+      } else if (line.compare(0, 7, "source:") == 0) {
+
+        is_file = 1;
+        line = line.substr(7);
+
+      }
+
+      if (line.find(":") != std::string::npos) {
+
+        FATAL("invalid line in AFL_LLVM_ALLOWLIST: %s", original_line.c_str());
+
+      }
+
+      if (line.length() > 0) {
+
+        // if the entry contains / or . it must be a file
+        if (is_file == -1)
+          if (line.find("/") != std::string::npos ||
+              line.find(".") != std::string::npos)
+            is_file = 1;
+        // otherwise it is a function
+
+        if (is_file == 1)
+          allowListFiles.push_back(line);
+        else
+          allowListFunctions.push_back(line);
+        getline(fileStream, line);
+
+      }
 
     }
 
+    if (debug)
+      SAYF(cMGN "[D] " cRST
+                "loaded allowlist with %zu file and %zu function entries\n",
+           allowListFiles.size(), allowListFunctions.size());
+
   }
 
-  if (debug)
-    SAYF(cMGN "[D] " cRST "loaded instrument list with %zu entries\n",
-         myInstrumentList.size());
+  if (denylist) {
+
+    std::string   line;
+    std::ifstream fileStream;
+    fileStream.open(denylist);
+    if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_DENYLIST");
+    getline(fileStream, line);
+
+    while (fileStream) {
+
+      int         is_file = -1;
+      std::size_t npos;
+      std::string original_line = line;
+
+      line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
+                 line.end());
+
+      // remove # and following
+      if ((npos = line.find("#")) != std::string::npos)
+        line = line.substr(0, npos);
+
+      if (line.compare(0, 4, "fun:") == 0) {
+
+        is_file = 0;
+        line = line.substr(4);
+
+      } else if (line.compare(0, 9, "function:") == 0) {
+
+        is_file = 0;
+        line = line.substr(9);
+
+      } else if (line.compare(0, 4, "src:") == 0) {
+
+        is_file = 1;
+        line = line.substr(4);
+
+      } else if (line.compare(0, 7, "source:") == 0) {
+
+        is_file = 1;
+        line = line.substr(7);
+
+      }
+
+      if (line.find(":") != std::string::npos) {
+
+        FATAL("invalid line in AFL_LLVM_DENYLIST: %s", original_line.c_str());
+
+      }
+
+      if (line.length() > 0) {
+
+        // if the entry contains / or . it must be a file
+        if (is_file == -1)
+          if (line.find("/") != std::string::npos ||
+              line.find(".") != std::string::npos)
+            is_file = 1;
+        // otherwise it is a function
+
+        if (is_file == 1)
+          denyListFiles.push_back(line);
+        else
+          denyListFunctions.push_back(line);
+        getline(fileStream, line);
+
+      }
+
+    }
+
+    if (debug)
+      SAYF(cMGN "[D] " cRST
+                "loaded denylist with %zu file and %zu function entries\n",
+           denyListFiles.size(), denyListFunctions.size());
+
+  }
 
 }
 
@@ -121,42 +260,173 @@ bool isInInstrumentList(llvm::Function *F) {
   if (!F->size() || isIgnoreFunction(F)) return false;
 
   // if we do not have a the instrument file list return true
-  if (myInstrumentList.empty()) return true;
+  if (!allowListFiles.empty() || !allowListFunctions.empty()) {
+
+    if (!allowListFunctions.empty()) {
+
+      std::string instFunction = F->getName().str();
+
+      for (std::list<std::string>::iterator it = allowListFunctions.begin();
+           it != allowListFunctions.end(); ++it) {
+
+        /* We don't check for filename equality here because
+         * filenames might actually be full paths. Instead we
+         * check that the actual filename ends in the filename
+         * specified in the list. We also allow UNIX-style pattern
+         * matching */
 
-  // let's try to get the filename for the function
-  auto                 bb = &F->getEntryBlock();
-  BasicBlock::iterator IP = bb->getFirstInsertionPt();
-  IRBuilder<>          IRB(&(*IP));
-  DebugLoc             Loc = IP->getDebugLoc();
+        if (instFunction.length() >= it->length()) {
+
+          if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
+
+            if (debug)
+              SAYF(cMGN "[D] " cRST
+                        "Function %s is in the allow function list, "
+                        "instrumenting ... \n",
+                   instFunction.c_str());
+            return true;
+
+          }
+
+        }
+
+      }
+
+    }
+
+    if (!allowListFiles.empty()) {
+
+      // let's try to get the filename for the function
+      auto                 bb = &F->getEntryBlock();
+      BasicBlock::iterator IP = bb->getFirstInsertionPt();
+      IRBuilder<>          IRB(&(*IP));
+      DebugLoc             Loc = IP->getDebugLoc();
 
 #if LLVM_VERSION_MAJOR >= 4 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
-  if (Loc) {
+      if (Loc) {
+
+        DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+
+        unsigned int instLine = cDILoc->getLine();
+        StringRef    instFilename = cDILoc->getFilename();
 
-    DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+        if (instFilename.str().empty()) {
 
-    unsigned int instLine = cDILoc->getLine();
-    StringRef    instFilename = cDILoc->getFilename();
+          /* If the original location is empty, try using the inlined location
+           */
+          DILocation *oDILoc = cDILoc->getInlinedAt();
+          if (oDILoc) {
+
+            instFilename = oDILoc->getFilename();
+            instLine = oDILoc->getLine();
+
+          }
+
+        }
 
-    if (instFilename.str().empty()) {
+        /* Continue only if we know where we actually are */
+        if (!instFilename.str().empty()) {
 
-      /* If the original location is empty, try using the inlined location
-       */
-      DILocation *oDILoc = cDILoc->getInlinedAt();
-      if (oDILoc) {
+          for (std::list<std::string>::iterator it = allowListFiles.begin();
+               it != allowListFiles.end(); ++it) {
 
-        instFilename = oDILoc->getFilename();
-        instLine = oDILoc->getLine();
+            /* We don't check for filename equality here because
+             * filenames might actually be full paths. Instead we
+             * check that the actual filename ends in the filename
+             * specified in the list. We also allow UNIX-style pattern
+             * matching */
+
+            if (instFilename.str().length() >= it->length()) {
+
+              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
+                  0) {
+
+                if (debug)
+                  SAYF(cMGN "[D] " cRST
+                            "Function %s is in the allowlist (%s), "
+                            "instrumenting ... \n",
+                       F->getName().str().c_str(), instFilename.str().c_str());
+                return true;
+
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+#else
+      if (!Loc.isUnknown()) {
+
+        DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+
+        unsigned int instLine = cDILoc.getLineNumber();
+        StringRef    instFilename = cDILoc.getFilename();
+
+        (void)instLine;
+        /* Continue only if we know where we actually are */
+        if (!instFilename.str().empty()) {
+
+          for (std::list<std::string>::iterator it = allowListFiles.begin();
+               it != allowListFiles.end(); ++it) {
+
+            /* We don't check for filename equality here because
+             * filenames might actually be full paths. Instead we
+             * check that the actual filename ends in the filename
+             * specified in the list. We also allow UNIX-style pattern
+             * matching */
+
+            if (instFilename.str().length() >= it->length()) {
+
+              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
+                  0) {
+
+                return true;
+
+              }
+
+            }
+
+          }
+
+        }
 
       }
 
     }
 
-    /* Continue only if we know where we actually are */
-    if (!instFilename.str().empty()) {
+#endif
+    else {
+
+      // we could not find out the location. in this case we say it is not
+      // in the the instrument file list
+      if (!be_quiet)
+        WARNF(
+            "No debug information found for function %s, will not be "
+            "instrumented (recompile with -g -O[1-3]).",
+            F->getName().str().c_str());
+      return false;
+
+    }
+
+    return false;
+
+  }
+
+  if (!denyListFiles.empty() || !denyListFunctions.empty()) {
+
+    if (!denyListFunctions.empty()) {
 
-      for (std::list<std::string>::iterator it = myInstrumentList.begin();
-           it != myInstrumentList.end(); ++it) {
+      std::string instFunction = F->getName().str();
+
+      for (std::list<std::string>::iterator it = denyListFunctions.begin();
+           it != denyListFunctions.end(); ++it) {
 
         /* We don't check for filename equality here because
          * filenames might actually be full paths. Instead we
@@ -164,16 +434,16 @@ bool isInInstrumentList(llvm::Function *F) {
          * specified in the list. We also allow UNIX-style pattern
          * matching */
 
-        if (instFilename.str().length() >= it->length()) {
+        if (instFunction.length() >= it->length()) {
 
-          if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-              0) {
+          if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
 
             if (debug)
               SAYF(cMGN "[D] " cRST
-                        "Function %s is in the list (%s), instrumenting ... \n",
-                   F->getName().str().c_str(), instFilename.str().c_str());
-            return true;
+                        "Function %s is in the deny function list, "
+                        "not instrumenting ... \n",
+                   instFunction.c_str());
+            return false;
 
           }
 
@@ -183,35 +453,64 @@ bool isInInstrumentList(llvm::Function *F) {
 
     }
 
-  }
+    if (!denyListFiles.empty()) {
 
-#else
-  if (!Loc.isUnknown()) {
+      // let's try to get the filename for the function
+      auto                 bb = &F->getEntryBlock();
+      BasicBlock::iterator IP = bb->getFirstInsertionPt();
+      IRBuilder<>          IRB(&(*IP));
+      DebugLoc             Loc = IP->getDebugLoc();
 
-    DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
+      if (Loc) {
 
-    unsigned int instLine = cDILoc.getLineNumber();
-    StringRef    instFilename = cDILoc.getFilename();
+        DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
 
-    (void)instLine;
-    /* Continue only if we know where we actually are */
-    if (!instFilename.str().empty()) {
+        unsigned int instLine = cDILoc->getLine();
+        StringRef    instFilename = cDILoc->getFilename();
 
-      for (std::list<std::string>::iterator it = myInstrumentList.begin();
-           it != myInstrumentList.end(); ++it) {
+        if (instFilename.str().empty()) {
 
-        /* We don't check for filename equality here because
-         * filenames might actually be full paths. Instead we
-         * check that the actual filename ends in the filename
-         * specified in the list. We also allow UNIX-style pattern
-         * matching */
+          /* If the original location is empty, try using the inlined location
+           */
+          DILocation *oDILoc = cDILoc->getInlinedAt();
+          if (oDILoc) {
 
-        if (instFilename.str().length() >= it->length()) {
+            instFilename = oDILoc->getFilename();
+            instLine = oDILoc->getLine();
 
-          if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-              0) {
+          }
 
-            return true;
+        }
+
+        /* Continue only if we know where we actually are */
+        if (!instFilename.str().empty()) {
+
+          for (std::list<std::string>::iterator it = denyListFiles.begin();
+               it != denyListFiles.end(); ++it) {
+
+            /* We don't check for filename equality here because
+             * filenames might actually be full paths. Instead we
+             * check that the actual filename ends in the filename
+             * specified in the list. We also allow UNIX-style pattern
+             * matching */
+
+            if (instFilename.str().length() >= it->length()) {
+
+              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
+                  0) {
+
+                if (debug)
+                  SAYF(cMGN "[D] " cRST
+                            "Function %s is in the denylist (%s), not "
+                            "instrumenting ... \n",
+                       F->getName().str().c_str(), instFilename.str().c_str());
+                return false;
+
+              }
+
+            }
 
           }
 
@@ -221,23 +520,65 @@ bool isInInstrumentList(llvm::Function *F) {
 
     }
 
-  }
+#else
+      if (!Loc.isUnknown()) {
+
+        DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+
+        unsigned int instLine = cDILoc.getLineNumber();
+        StringRef instFilename = cDILoc.getFilename();
+
+        (void)instLine;
+        /* Continue only if we know where we actually are */
+        if (!instFilename.str().empty()) {
+
+          for (std::list<std::string>::iterator it = denyListFiles.begin();
+               it != denyListFiles.end(); ++it) {
+
+            /* We don't check for filename equality here because
+             * filenames might actually be full paths. Instead we
+             * check that the actual filename ends in the filename
+             * specified in the list. We also allow UNIX-style pattern
+             * matching */
+
+            if (instFilename.str().length() >= it->length()) {
+
+              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
+                  0) {
+
+                return false;
+
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
 
 #endif
-  else {
-
-    // we could not find out the location. in this case we say it is not
-    // in the the instrument file list
-    if (!be_quiet)
-      WARNF(
-          "No debug information found for function %s, will not be "
-          "instrumented (recompile with -g -O[1-3]).",
-          F->getName().str().c_str());
-    return false;
+    else {
+
+      // we could not find out the location. in this case we say it is not
+      // in the the instrument file list
+      if (!be_quiet)
+        WARNF(
+            "No debug information found for function %s, will be "
+            "instrumented (recompile with -g -O[1-3]).",
+            F->getName().str().c_str());
+      return true;
+
+    }
+
+    return true;
 
   }
 
-  return false;
+  return true;  // not reached
 
 }
 
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index 38c3f202..fd8e48a7 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -49,6 +49,7 @@
 #include "llvm/Analysis/MemorySSAUpdater.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/Pass.h"
+#include "llvm/IR/Constants.h"
 
 #include "afl-llvm-common.h"
 
@@ -135,7 +136,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   if (getenv("AFL_LLVM_LTO_AUTODICTIONARY")) autodictionary = 1;
 
-  if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
+  // we make this the default as the fixed map has problems with
+  // defered forkserver, early constructors, ifuncs and maybe more
+  /*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
+  map_addr = 0;
 
   if (getenv("AFL_LLVM_SKIPSINGLEBLOCK")) function_minimum_size = 2;
 
@@ -196,7 +200,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
   ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
   ConstantInt *One = ConstantInt::get(Int8Ty, 1);
 
-  /* This dumps all inialized global strings - might be useful in the future
+  // This dumps all inialized global strings - might be useful in the future
+  /*
   for (auto G=M.getGlobalList().begin(); G!=M.getGlobalList().end(); G++) {
 
     GlobalVariable &GV=*G;
@@ -212,7 +217,79 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   }
 
-  */
+    */
+
+  std::vector<std::string> module_block_list;
+
+  if (map_addr) {
+
+    for (GlobalIFunc &IF : M.ifuncs()) {
+
+      StringRef ifunc_name = IF.getName();
+      Constant *r = IF.getResolver();
+      StringRef r_name = cast<Function>(r->getOperand(0))->getName();
+      if (!be_quiet)
+        fprintf(stderr,
+                "Warning: Found an ifunc with name %s that points to resolver "
+                "function %s, we cannot instrument this, putting it into a "
+                "block list.\n",
+                ifunc_name.str().c_str(), r_name.str().c_str());
+      module_block_list.push_back(r_name.str());
+
+    }
+
+    GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors");
+    if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) {
+
+      ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
+
+      if (InitList) {
+
+        for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+
+          if (ConstantStruct *CS =
+                  dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
+
+            if (CS->getNumOperands() >= 2) {
+
+              if (CS->getOperand(1)->isNullValue())
+                break;  // Found a null terminator, stop here.
+
+              ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
+              int          Priority = CI ? CI->getSExtValue() : 0;
+
+              Constant *FP = CS->getOperand(1);
+              if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
+                if (CE->isCast()) FP = CE->getOperand(0);
+              if (Function *F = dyn_cast<Function>(FP)) {
+
+                if (!F->isDeclaration() &&
+                    strncmp(F->getName().str().c_str(), "__afl", 5) != 0 &&
+                    Priority <= 5) {
+
+                  if (!be_quiet)
+                    fprintf(stderr,
+                            "Warning: Found constructor function %s with prio "
+                            "%u, we cannot instrument this, putting it into a "
+                            "block list.\n",
+                            F->getName().str().c_str(), Priority);
+                  module_block_list.push_back(F->getName().str());
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
 
   /* Instrument all the things! */
 
@@ -220,12 +297,36 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   for (auto &F : M) {
 
-    // fprintf(stderr, "DEBUG: Module %s Function %s\n",
-    // M.getName().str().c_str(), F.getName().str().c_str());
+    /*For debugging
+    AttributeSet X = F.getAttributes().getFnAttributes();
+    fprintf(stderr, "DEBUG: Module %s Function %s attributes %u\n",
+      M.getName().str().c_str(), F.getName().str().c_str(),
+      X.getNumAttributes());
+    */
 
     if (F.size() < function_minimum_size) continue;
     if (isIgnoreFunction(&F)) continue;
 
+    if (module_block_list.size()) {
+
+      for (auto bname : module_block_list) {
+
+        std::string fname = F.getName().str();
+
+        if (fname.compare(bname) == 0) {
+
+          if (!be_quiet)
+            WARNF(
+                "Skipping instrumentation of dangerous early running function "
+                "%s",
+                fname.c_str());
+
+        }
+
+      }
+
+    }
+
     // the instrument file list check
     AttributeList Attrs = F.getAttributes();
     if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
diff --git a/llvm_mode/afl-llvm-lto-instrumentlist.so.cc b/llvm_mode/afl-llvm-lto-instrumentlist.so.cc
index ab7c0c58..a7331444 100644
--- a/llvm_mode/afl-llvm-lto-instrumentlist.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentlist.so.cc
@@ -59,39 +59,9 @@ class AFLcheckIfInstrument : public ModulePass {
   static char ID;
   AFLcheckIfInstrument() : ModulePass(ID) {
 
-    int entries = 0;
-
     if (getenv("AFL_DEBUG")) debug = 1;
 
-    char *instrumentListFilename = getenv("AFL_LLVM_INSTRUMENT_FILE");
-    if (!instrumentListFilename)
-      instrumentListFilename = getenv("AFL_LLVM_WHITELIST");
-    if (instrumentListFilename) {
-
-      std::string   line;
-      std::ifstream fileStream;
-      fileStream.open(instrumentListFilename);
-      if (!fileStream)
-        report_fatal_error("Unable to open AFL_LLVM_INSTRUMENT_FILE");
-      getline(fileStream, line);
-      while (fileStream) {
-
-        myInstrumentList.push_back(line);
-        getline(fileStream, line);
-        entries++;
-
-      }
-
-    } else
-
-      PFATAL(
-          "afl-llvm-lto-instrumentlist.so loaded without "
-          "AFL_LLVM_INSTRUMENT_FILE?!");
-
-    if (debug)
-      SAYF(cMGN "[D] " cRST
-                "loaded the instrument file list %s with %d entries\n",
-           instrumentListFilename, entries);
+    initInstrumentList();
 
   }
 
@@ -129,120 +99,28 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
   for (auto &F : M) {
 
     if (F.size() < 1) continue;
-    // fprintf(stderr, "F:%s\n", F.getName().str().c_str());
-    if (isIgnoreFunction(&F)) continue;
-
-    BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
-    IRBuilder<>          IRB(&(*IP));
-
-    if (!myInstrumentList.empty()) {
-
-      bool instrumentFunction = false;
-
-      /* Get the current location using debug information.
-       * For now, just instrument the block if we are not able
-       * to determine our location. */
-      DebugLoc Loc = IP->getDebugLoc();
-      if (Loc) {
-
-        DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
-
-        unsigned int instLine = cDILoc->getLine();
-        StringRef    instFilename = cDILoc->getFilename();
-
-        if (instFilename.str().empty()) {
-
-          /* If the original location is empty, try using the inlined location
-           */
-          DILocation *oDILoc = cDILoc->getInlinedAt();
-          if (oDILoc) {
-
-            instFilename = oDILoc->getFilename();
-            instLine = oDILoc->getLine();
-
-          }
-
-          if (instFilename.str().empty()) {
 
-            if (!be_quiet)
-              WARNF(
-                  "Function %s has no source file name information and will "
-                  "not be instrumented.",
-                  F.getName().str().c_str());
-            continue;
-
-          }
-
-        }
-
-        //(void)instLine;
-
-        fprintf(stderr, "xxx %s %s\n", F.getName().str().c_str(),
-                instFilename.str().c_str());
-        if (debug)
-          SAYF(cMGN "[D] " cRST "function %s is in file %s\n",
-               F.getName().str().c_str(), instFilename.str().c_str());
-
-        for (std::list<std::string>::iterator it = myInstrumentList.begin();
-             it != myInstrumentList.end(); ++it) {
-
-          /* We don't check for filename equality here because
-           * filenames might actually be full paths. Instead we
-           * check that the actual filename ends in the filename
-           * specified in the list. */
-          if (instFilename.str().length() >= it->length()) {
-
-            if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-                0) {
-
-              instrumentFunction = true;
-              break;
-
-            }
-
-          }
-
-        }
-
-      } else {
-
-        if (!be_quiet)
-          WARNF(
-              "No debug information found for function %s, recompile with -g "
-              "-O[1-3]",
-              F.getName().str().c_str());
-        continue;
-
-      }
-
-      /* Either we couldn't figure out our location or the location is
-       * not the instrument file listed, so we skip instrumentation.
-       * We do this by renaming the function. */
-      if (instrumentFunction == true) {
-
-        if (debug)
-          SAYF(cMGN "[D] " cRST "function %s is in the instrument file list\n",
-               F.getName().str().c_str());
-
-      } else {
-
-        if (debug)
-          SAYF(cMGN "[D] " cRST
-                    "function %s is NOT in the instrument file list\n",
-               F.getName().str().c_str());
+    // fprintf(stderr, "F:%s\n", F.getName().str().c_str());
 
-        auto &        Ctx = F.getContext();
-        AttributeList Attrs = F.getAttributes();
-        AttrBuilder   NewAttrs;
-        NewAttrs.addAttribute("skipinstrument");
-        F.setAttributes(
-            Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
+    if (isInInstrumentList(&F)) {
 
-      }
+      if (debug)
+        SAYF(cMGN "[D] " cRST "function %s is in the instrument file list\n",
+             F.getName().str().c_str());
 
     } else {
 
-      PFATAL("InstrumentList is empty");
+      if (debug)
+        SAYF(cMGN "[D] " cRST
+                  "function %s is NOT in the instrument file list\n",
+             F.getName().str().c_str());
+
+      auto &        Ctx = F.getContext();
+      AttributeList Attrs = F.getAttributes();
+      AttrBuilder   NewAttrs;
+      NewAttrs.addAttribute("skipinstrument");
+      F.setAttributes(
+          Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
 
     }
 
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
index fcacc675..a567593e 100644
--- a/llvm_mode/afl-llvm-rt.o.c
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -42,6 +42,8 @@
 #include <sys/wait.h>
 #include <sys/types.h>
 
+#include "llvm/Config/llvm-config.h"
+
 #ifdef __linux__
   #include "snapshot-inl.h"
 #endif
@@ -183,6 +185,9 @@ static void __afl_map_shm_fuzz() {
 
 static void __afl_map_shm(void) {
 
+  // we we are not running in afl ensure the map exists
+  if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+
   char *id_str = getenv(SHM_ENV_VAR);
 
   if (__afl_final_loc) {
@@ -324,10 +329,13 @@ static void __afl_map_shm(void) {
 
   id_str = getenv(CMPLOG_SHM_ENV_VAR);
 
-  if (getenv("AFL_DEBUG"))
+  if (getenv("AFL_DEBUG")) {
+
     fprintf(stderr, "DEBUG: cmplog id_str %s\n",
             id_str == NULL ? "<null>" : id_str);
 
+  }
+
   if (id_str) {
 
 #ifdef USEMMAP
@@ -399,9 +407,12 @@ static void __afl_start_snapshots(void) {
 
     if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
 
-    if (getenv("AFL_DEBUG"))
+    if (getenv("AFL_DEBUG")) {
+
       fprintf(stderr, "target forkserver recv: %08x\n", was_killed);
 
+    }
+
     if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
         (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
 
@@ -608,9 +619,12 @@ static void __afl_start_forkserver(void) {
 
     if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
 
-    if (getenv("AFL_DEBUG"))
+    if (getenv("AFL_DEBUG")) {
+
       fprintf(stderr, "target forkserver recv: %08x\n", was_killed);
 
+    }
+
     if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
         (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
 
@@ -892,8 +906,16 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
 
   */
 
+#if (LLVM_VERSION_MAJOR < 9)
+
   __afl_area_ptr[*guard]++;
 
+#else
+
+  __afl_area_ptr[*guard] = __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0);
+
+#endif
+
 }
 
 /* Init callback. Populates instrumentation IDs. Note that we're using
@@ -905,6 +927,13 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
   u32   inst_ratio = 100;
   char *x;
 
+  if (getenv("AFL_DEBUG")) {
+
+    fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n",
+            start, stop);
+
+  }
+
   if (start == stop || *start) return;
 
   x = getenv("AFL_INST_RATIO");
@@ -940,7 +969,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
 
 void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -963,7 +992,7 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
 
 void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -984,7 +1013,7 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
 
 void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -1005,7 +1034,7 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
 
 void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -1056,6 +1085,8 @@ void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2)
 
 void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
 
+  if (unlikely(!__afl_cmp_map)) return;
+
   for (uint64_t i = 0; i < cases[0]; i++) {
 
     uintptr_t k = (uintptr_t)__builtin_return_address(0) + i;
@@ -1093,7 +1124,7 @@ static int area_is_mapped(void *ptr, size_t len) {
 
 void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;
 
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index a7bfe20d..30ac158f 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -176,6 +176,7 @@ echo Building for CPU target $CPU_TARGET
 echo "[*] Applying patches..."
 
 patch -p1 <../patches/elfload.diff || exit 1
+patch -p1 <../patches/mips-fpu.diff || exit 1
 patch -p1 <../patches/bsd-elfload.diff || exit 1
 patch -p1 <../patches/cpu-exec.diff || exit 1
 patch -p1 <../patches/syscall.diff || exit 1
diff --git a/qemu_mode/patches/mips-fpu.diff b/qemu_mode/patches/mips-fpu.diff
new file mode 100644
index 00000000..646d167e
--- /dev/null
+++ b/qemu_mode/patches/mips-fpu.diff
@@ -0,0 +1,15 @@
+--- a/linux-user/elfload.c	2020-07-13 20:10:37.776374566 -0700
++++ b/linux-user/elfload.c	2020-07-13 20:11:51.794957015 -0700
+@@ -2667,6 +2667,11 @@
+     char *elf_interpreter = NULL;
+     char *scratch;
+ 
++    memset(&interp_info, 0, sizeof(interp_info));
++#ifdef TARGET_MIPS
++    interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
++#endif
++
+     info->start_mmap = (abi_ulong)ELF_START_MMAP;
+ 
+     load_elf_image(bprm->filename, bprm->fd, info,
+
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index e6dd0fca..7c1c269a 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -384,7 +384,7 @@ static void show_legend(void) {
 
 /* Interpret and report a pattern in the input file. */
 
-static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
+static void dump_hex(u32 len, u8 *b_data) {
 
   u32 i;
 
@@ -678,7 +678,7 @@ static void analyze(char **argv) {
 
   }
 
-  dump_hex(in_data, in_len, b_data);
+  dump_hex(in_len, b_data);
 
   SAYF("\n");
 
@@ -700,6 +700,7 @@ static void analyze(char **argv) {
 
 static void handle_stop_sig(int sig) {
 
+  (void)sig;
   stop_soon = 1;
 
   if (child_pid > 0) { kill(child_pid, SIGKILL); }
diff --git a/src/afl-as.c b/src/afl-as.c
index f16d6060..0ed47d8c 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -136,7 +136,7 @@ static void edit_params(int argc, char **argv) {
 
   as_params[argc] = 0;
 
-  for (i = 1; i < argc - 1; i++) {
+  for (i = 1; (s32)i < argc - 1; i++) {
 
     if (!strcmp(argv[i], "--64")) {
 
@@ -407,7 +407,7 @@ static void add_instrumentation(void) {
 
     if (line[0] == '\t') {
 
-      if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) {
+      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));
@@ -449,7 +449,7 @@ static void add_instrumentation(void) {
         /* Apple: L<num> / LBB<num> */
 
         if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3))) &&
-            R(100) < inst_ratio) {
+            R(100) < (long)inst_ratio) {
 
 #else
 
@@ -457,7 +457,7 @@ static void add_instrumentation(void) {
 
         if ((isdigit(line[2]) ||
              (clang_mode && !strncmp(line + 1, "LBB", 3))) &&
-            R(100) < inst_ratio) {
+            R(100) < (long)inst_ratio) {
 
 #endif                                                         /* __APPLE__ */
 
@@ -591,7 +591,7 @@ int main(int argc, char **argv) {
 
   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; i < argc; i++)
+  for (i = 1; (s32)i < argc; i++)
     for (j = 0; j < strlen(argv[i]); j++)
       rand_seed += argv[i][j];
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 47493eba..6819fc8a 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -122,7 +122,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   Returns the time passed to read.
   If the wait times out, returns timeout_ms + 1;
   Returns 0 if an error occurred (fd closed, signal, ...); */
-static u32 read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms,
+static u32 __attribute__ ((hot)) read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms,
                           volatile u8 *stop_soon_p) {
 
   fd_set readfds;
@@ -145,6 +145,13 @@ restart_select:
   if (likely(sret > 0)) {
 
   restart_read:
+    if (*stop_soon_p) {
+
+      // Early return - the user wants to quit.
+      return 0;
+
+    }
+
     len_read = read(fd, (u8 *)buf, 4);
 
     if (likely(len_read == 4)) {  // for speed we put this first
@@ -286,8 +293,8 @@ static void report_error_and_exit(int error) {
       FATAL(
           "the fuzzing target reports that hardcoded map address might be the "
           "reason the mmap of the shared memory failed. Solution: recompile "
-          "the target with either afl-clang-lto and the environment variable "
-          "AFL_LLVM_MAP_DYNAMIC set or recompile with afl-clang-fast.");
+          "the target with either afl-clang-lto and do not set "
+          "AFL_LLVM_MAP_ADDR or recompile with afl-clang-fast.");
       break;
     case FS_ERROR_SHM_OPEN:
       FATAL("the fuzzing target reports that the shm_open() call failed.");
@@ -315,7 +322,7 @@ static void report_error_and_exit(int error) {
    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 */
 
-void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
+void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
                     volatile u8 *stop_soon_p, u8 debug_child_output) {
 
   int st_pipe[2], ctl_pipe[2];
@@ -691,7 +698,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
         }
 
         offset = 0;
-        while (offset < status && (u8)dict[offset] + offset < status) {
+        while (offset < (u32)status &&
+               (u8)dict[offset] + offset < (u32)status) {
 
           fsrv->function_ptr(fsrv->function_opt, dict + offset + 1,
                              (u8)dict[offset]);
@@ -820,8 +828,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
     SAYF("\n" cLRD "[-] " cRST
          "Hmm, looks like the target binary terminated before we could"
          " complete a handshake with the injected code.\n"
-         "If the target was compiled with afl-clang-lto then recompiling with"
-         " AFL_LLVM_MAP_DYNAMIC might solve your problem.\n"
+         "If the target was compiled with afl-clang-lto and AFL_LLVM_MAP_ADDR"
+         " then recompiling without this parameter.\n"
          "Otherwise there is a horrible bug in the fuzzer.\n"
          "Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
 
@@ -852,9 +860,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
         "    - the target was compiled with afl-clang-lto and a constructor "
         "was\n"
-        "      instrumented, recompiling with AFL_LLVM_MAP_DYNAMIC might solve "
-        "your\n"
-        "      problem\n\n"
+        "      instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
+        "your problem\n\n"
 
         "    - Less likely, there is a horrible bug in the fuzzer. If other "
         "options\n"
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index aa8d5a18..f6389c06 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -57,7 +57,7 @@ void write_bitmap(afl_state_t *afl) {
    This function is called after every exec() on a fairly large buffer, so
    it needs to be fast. We do this in 32-bit and 64-bit flavors. */
 
-u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
+u8 __attribute__ ((hot)) has_new_bits(afl_state_t *afl, u8 *virgin_map) {
 
 #ifdef WORD_SIZE_64
 
@@ -347,7 +347,7 @@ void init_count_class16(void) {
 
 #ifdef WORD_SIZE_64
 
-void classify_counts(afl_forkserver_t *fsrv) {
+void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) {
 
   u64 *mem = (u64 *)fsrv->trace_bits;
 
@@ -376,7 +376,7 @@ void classify_counts(afl_forkserver_t *fsrv) {
 
 #else
 
-void classify_counts(afl_forkserver_t *fsrv) {
+void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) {
 
   u32 *mem = (u32 *)fsrv->trace_bits;
 
@@ -534,7 +534,7 @@ static void write_crash_readme(afl_state_t *afl) {
    save or queue the input test case for further analysis if so. Returns 1 if
    entry is saved, 0 otherwise. */
 
-u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
+u8 __attribute__ ((hot)) save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   if (unlikely(len == 0)) { return 0; }
 
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index faf4dcb7..8ffc6e1b 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -29,10 +29,6 @@
 #include "afl-fuzz.h"
 #include "cmplog.h"
 
-typedef struct cmplog_data {
-
-} cmplog_data_t;
-
 void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
 
   setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 12771cd7..097871c8 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -115,7 +115,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
     if (*lptr == '@') {
 
       ++lptr;
-      if (atoi(lptr) > dict_level) { continue; }
+      if (atoi(lptr) > (s32)dict_level) { continue; }
       while (isdigit(*lptr)) {
 
         ++lptr;
@@ -402,7 +402,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
 
     while (i--) {
 
-      if (*((u32 *)mem) == interesting_32[i] ||
+      if (*((u32 *)mem) == (u32)interesting_32[i] ||
           *((u32 *)mem) == SWAP32(interesting_32[i])) {
 
         return;
@@ -480,7 +480,7 @@ sort_a_extras:
 
   /* Then, sort the top USE_AUTO_EXTRAS entries by size. */
 
-  qsort(afl->a_extras, MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt),
+  qsort(afl->a_extras, MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt),
         sizeof(struct extra_data), compare_extras_len);
 
 }
@@ -494,7 +494,7 @@ void save_auto(afl_state_t *afl) {
   if (!afl->auto_changed) { return; }
   afl->auto_changed = 0;
 
-  for (i = 0; i < MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
+  for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
 
     u8 *fn =
         alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 2c17ffbb..350a8599 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -110,7 +110,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
   u8  cpu_used[4096] = {0};
   u8  lockfile[PATH_MAX] = "";
-  u32 i;
+  s32 i;
 
   if (afl->afl_env.afl_no_affinity) {
 
@@ -509,7 +509,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
       afl->stage_cur = 0;
       afl->stage_max = 0;
 
-      for (i = 0; i < nl_cnt; ++i) {
+      for (i = 0; i < (u32)nl_cnt; ++i) {
 
         struct stat st;
 
@@ -667,7 +667,7 @@ void read_testcases(afl_state_t *afl) {
 
   }
 
-  for (i = 0; i < nl_cnt; ++i) {
+  for (i = 0; i < (u32)nl_cnt; ++i) {
 
     struct stat st;
 
@@ -762,7 +762,7 @@ void perform_dry_run(afl_state_t *afl) {
 
     use_mem = ck_alloc_nozero(q->len);
 
-    if (read(fd, use_mem, q->len) != q->len) {
+    if (read(fd, use_mem, q->len) != (ssize_t)q->len) {
 
       FATAL("Short read from '%s'", q->fname);
 
@@ -2147,7 +2147,7 @@ void get_core_count(afl_state_t *afl) {
 
         WARNF("System under apparent load, performance may be spotty.");
 
-      } else if (cur_runnable + 1 <= afl->cpu_core_count) {
+      } else if ((s64)cur_runnable + 1 <= (s64)afl->cpu_core_count) {
 
         OKF("Try parallel jobs - see %s/parallel_fuzzing.md.", doc_path);
 
@@ -2201,6 +2201,7 @@ void fix_up_sync(afl_state_t *afl) {
 
 static void handle_resize(int sig) {
 
+  (void)sig;
   afl_states_clear_screen();
 
 }
@@ -2252,6 +2253,7 @@ void check_asan_opts(void) {
 
 static void handle_stop_sig(int sig) {
 
+  (void)sig;
   afl_states_stop();
 
 }
@@ -2260,6 +2262,7 @@ static void handle_stop_sig(int sig) {
 
 static void handle_skipreq(int sig) {
 
+  (void)sig;
   afl_states_request_skip();
 
 }
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index b30106a0..0fa646f9 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -142,6 +142,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
   struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
 
   mutator->name = fn;
+  mutator->name_short = strrchr(fn, '/') + 1;
   ACTF("Loading custom mutator library from '%s'...", fn);
 
   dh = dlopen(fn, RTLD_NOW);
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 1f0bf30e..452c5298 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -77,7 +77,7 @@ static int select_algorithm(afl_state_t *afl) {
 static u32 choose_block_len(afl_state_t *afl, u32 limit) {
 
   u32 min_value, max_value;
-  u32 rlim = MIN(afl->queue_cycle, 3);
+  u32 rlim = MIN(afl->queue_cycle, (u32)3);
 
   if (unlikely(!afl->run_over10m)) { rlim = 1; }
 
@@ -292,7 +292,7 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) {
 
   /* See if two-byte insertions over old_val could give us new_val. */
 
-  for (i = 0; i < blen - 1; ++i) {
+  for (i = 0; (s32)i < blen - 1; ++i) {
 
     for (j = 0; j < sizeof(interesting_16) / 2; ++j) {
 
@@ -372,7 +372,9 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) {
 
 u8 fuzz_one_original(afl_state_t *afl) {
 
-  s32 len, fd, temp_len, i, j;
+  s32 len, fd, temp_len;
+  u32 j;
+  u32 i;
   u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
   u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum;
   u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1;
@@ -862,7 +864,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
      whole thing as worth fuzzing, since we wouldn't be saving much time
      anyway. */
 
-  if (eff_cnt != EFF_ALEN(len) &&
+  if (eff_cnt != (u32)EFF_ALEN(len) &&
       eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) {
 
     memset(eff_map, 1, EFF_ALEN(len));
@@ -893,7 +895,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 1; ++i) {
+  for (i = 0; (s32)i < len - 1; ++i) {
 
     /* Let's consult the effector map... */
 
@@ -931,7 +933,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 3; ++i) {
+  for (i = 0; (s32)i < len - 3; ++i) {
 
     /* Let's consult the effector map... */
     if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
@@ -977,7 +979,7 @@ skip_bitflip:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u8 orig = out_buf[i];
 
@@ -1051,7 +1053,7 @@ skip_bitflip:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 1; ++i) {
+  for (i = 0; i < (u32)len - 1; ++i) {
 
     u16 orig = *(u16 *)(out_buf + i);
 
@@ -1161,7 +1163,7 @@ skip_bitflip:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 3; ++i) {
+  for (i = 0; i < (u32)len - 3; ++i) {
 
     u32 orig = *(u32 *)(out_buf + i);
 
@@ -1202,7 +1204,7 @@ skip_bitflip:
 
       }
 
-      if ((orig & 0xffff) < j && !could_be_bitflip(r2)) {
+      if ((orig & 0xffff) < (u32)j && !could_be_bitflip(r2)) {
 
         afl->stage_cur_val = -j;
         *(u32 *)(out_buf + i) = orig - j;
@@ -1234,7 +1236,7 @@ skip_bitflip:
 
       }
 
-      if ((SWAP32(orig) & 0xffff) < j && !could_be_bitflip(r4)) {
+      if ((SWAP32(orig) & 0xffff) < (u32)j && !could_be_bitflip(r4)) {
 
         afl->stage_cur_val = -j;
         *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) - j);
@@ -1276,7 +1278,7 @@ skip_arith:
 
   /* Setting 8-bit integers. */
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u8 orig = out_buf[i];
 
@@ -1291,7 +1293,7 @@ skip_arith:
 
     afl->stage_cur_byte = i;
 
-    for (j = 0; j < sizeof(interesting_8); ++j) {
+    for (j = 0; j < (u32)sizeof(interesting_8); ++j) {
 
       /* Skip if the value could be a product of bitflips or arithmetics. */
 
@@ -1331,7 +1333,7 @@ skip_arith:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 1; ++i) {
+  for (i = 0; (s32)i < len - 1; ++i) {
 
     u16 orig = *(u16 *)(out_buf + i);
 
@@ -1409,7 +1411,7 @@ skip_arith:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 3; i++) {
+  for (i = 0; (s32)i < len - 3; i++) {
 
     u32 orig = *(u32 *)(out_buf + i);
 
@@ -1496,7 +1498,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u32 last_len = 0;
 
@@ -1556,7 +1558,7 @@ skip_interest:
 
   ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
-  for (i = 0; i <= len; ++i) {
+  for (i = 0; i <= (u32)len; ++i) {
 
     afl->stage_cur_byte = i;
 
@@ -1602,19 +1604,20 @@ skip_user_extras:
   afl->stage_name = "auto extras (over)";
   afl->stage_short = "ext_AO";
   afl->stage_cur = 0;
-  afl->stage_max = MIN(afl->a_extras_cnt, USE_AUTO_EXTRAS) * len;
+  afl->stage_max = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS) * len;
 
   afl->stage_val_type = STAGE_VAL_NONE;
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u32 last_len = 0;
 
     afl->stage_cur_byte = i;
 
-    for (j = 0; j < MIN(afl->a_extras_cnt, USE_AUTO_EXTRAS); ++j) {
+    u32 min_extra_len = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS);
+    for (j = 0; j < min_extra_len; ++j) {
 
       /* See the comment in the earlier code; extras are sorted by size. */
 
@@ -1680,6 +1683,8 @@ custom_mutator_stage:
 
       has_custom_fuzz = true;
 
+      afl->stage_short = el->name_short;
+
       for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
            ++afl->stage_cur) {
 
@@ -2231,7 +2236,7 @@ havoc_stage:
                 u32 extra_len = afl->a_extras[use_extra].len;
                 u32 insert_at;
 
-                if (extra_len > temp_len) { break; }
+                if ((s32)extra_len > temp_len) { break; }
 
                 insert_at = rand_below(afl, temp_len - extra_len + 1);
                 memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
@@ -2245,7 +2250,7 @@ havoc_stage:
                 u32 extra_len = afl->extras[use_extra].len;
                 u32 insert_at;
 
-                if (extra_len > temp_len) { break; }
+                if ((s32)extra_len > temp_len) { break; }
 
                 insert_at = rand_below(afl, temp_len - extra_len + 1);
                 memcpy(out_buf + insert_at, afl->extras[use_extra].data,
@@ -2360,7 +2365,7 @@ havoc_stage:
               u32 copy_from, copy_to, copy_len;
 
               copy_len = choose_block_len(afl, new_len - 1);
-              if (copy_len > temp_len) copy_len = temp_len;
+              if ((s32)copy_len > temp_len) copy_len = temp_len;
 
               copy_from = rand_below(afl, new_len - copy_len + 1);
               copy_to = rand_below(afl, temp_len - copy_len + 1);
@@ -2517,7 +2522,7 @@ retry_splicing:
        the last differing byte. Bail out if the difference is just a single
        byte or so. */
 
-    locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff);
+    locate_diffs(in_buf, new_buf, MIN(len, (s64)target->len), &f_diff, &l_diff);
 
     if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; }
 
@@ -2587,7 +2592,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
   }
 
-  s32 len, fd, temp_len, i, j;
+  s32 len, fd, temp_len;
+  u32 i;
+  u32 j;
   u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
   u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, cur_ms_lv, prev_cksum;
   u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1;
@@ -2761,9 +2768,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
   cur_ms_lv = get_cur_time();
   if (!(afl->key_puppet == 0 &&
-        ((cur_ms_lv - afl->last_path_time < afl->limit_time_puppet) ||
+        ((cur_ms_lv - afl->last_path_time < (u32)afl->limit_time_puppet) ||
          (afl->last_crash_time != 0 &&
-          cur_ms_lv - afl->last_crash_time < afl->limit_time_puppet) ||
+          cur_ms_lv - afl->last_crash_time < (u32)afl->limit_time_puppet) ||
          afl->last_path_time == 0))) {
 
     afl->key_puppet = 1;
@@ -3058,7 +3065,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
      whole thing as worth fuzzing, since we wouldn't be saving much time
      anyway. */
 
-  if (eff_cnt != EFF_ALEN(len) &&
+  if (eff_cnt != (u32)EFF_ALEN(len) &&
       eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) {
 
     memset(eff_map, 1, EFF_ALEN(len));
@@ -3089,7 +3096,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 1; ++i) {
+  for (i = 0; (s32)i < len - 1; ++i) {
 
     /* Let's consult the effector map... */
 
@@ -3127,7 +3134,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 3; ++i) {
+  for (i = 0; (s32)i < len - 3; ++i) {
 
     /* Let's consult the effector map... */
     if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
@@ -3173,7 +3180,7 @@ skip_bitflip:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u8 orig = out_buf[i];
 
@@ -3247,7 +3254,7 @@ skip_bitflip:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 1; ++i) {
+  for (i = 0; (s32)i < len - 1; ++i) {
 
     u16 orig = *(u16 *)(out_buf + i);
 
@@ -3357,7 +3364,7 @@ skip_bitflip:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 3; ++i) {
+  for (i = 0; (s32)i < len - 3; ++i) {
 
     u32 orig = *(u32 *)(out_buf + i);
 
@@ -3472,7 +3479,7 @@ skip_arith:
 
   /* Setting 8-bit integers. */
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u8 orig = out_buf[i];
 
@@ -3527,7 +3534,7 @@ skip_arith:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 1; ++i) {
+  for (i = 0; (s32)i < len - 1; ++i) {
 
     u16 orig = *(u16 *)(out_buf + i);
 
@@ -3605,7 +3612,7 @@ skip_arith:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len - 3; ++i) {
+  for (i = 0; (s32)i < len - 3; ++i) {
 
     u32 orig = *(u32 *)(out_buf + i);
 
@@ -3692,7 +3699,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u32 last_len = 0;
 
@@ -3752,7 +3759,7 @@ skip_interest:
 
   ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
-  for (i = 0; i <= len; ++i) {
+  for (i = 0; i <= (u32)len; ++i) {
 
     afl->stage_cur_byte = i;
 
@@ -3798,23 +3805,23 @@ skip_user_extras:
   afl->stage_name = "auto extras (over)";
   afl->stage_short = "ext_AO";
   afl->stage_cur = 0;
-  afl->stage_max = MIN(afl->a_extras_cnt, USE_AUTO_EXTRAS) * len;
+  afl->stage_max = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS) * len;
 
   afl->stage_val_type = STAGE_VAL_NONE;
 
   orig_hit_cnt = new_hit_cnt;
 
-  for (i = 0; i < len; ++i) {
+  for (i = 0; i < (u32)len; ++i) {
 
     u32 last_len = 0;
 
     afl->stage_cur_byte = i;
 
-    for (j = 0; j < MIN(afl->a_extras_cnt, USE_AUTO_EXTRAS); ++j) {
+    for (j = 0; j < MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS); ++j) {
 
       /* See the comment in the earlier code; extras are sorted by size. */
 
-      if (afl->a_extras[j].len > len - i ||
+      if ((s32)(afl->a_extras[j].len) > (s32)(len - i) ||
           !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
                   EFF_SPAN_ALEN(i, afl->a_extras[j].len))) {
@@ -4276,7 +4283,7 @@ pacemaker_fuzzing:
                 u32 use_extra = rand_below(afl, afl->a_extras_cnt);
                 u32 extra_len = afl->a_extras[use_extra].len;
 
-                if (extra_len > temp_len) break;
+                if (extra_len > (u32)temp_len) break;
 
                 u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
                 memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
@@ -4289,7 +4296,7 @@ pacemaker_fuzzing:
                 u32 use_extra = rand_below(afl, afl->extras_cnt);
                 u32 extra_len = afl->extras[use_extra].len;
 
-                if (extra_len > temp_len) break;
+                if (extra_len > (u32)temp_len) break;
 
                 u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
                 memcpy(out_buf + insert_at, afl->extras[use_extra].data,
@@ -4449,7 +4456,8 @@ pacemaker_fuzzing:
 
     retry_splicing_puppet:
 
-      if (afl->use_splicing && splice_cycle++ < afl->SPLICE_CYCLES_puppet &&
+      if (afl->use_splicing &&
+          splice_cycle++ < (u32)afl->SPLICE_CYCLES_puppet &&
           afl->queued_paths > 1 && afl->queue_cur->len > 1) {
 
         struct queue_entry *target;
@@ -4519,7 +4527,8 @@ pacemaker_fuzzing:
            the last differing byte. Bail out if the difference is just a single
            byte or so. */
 
-        locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff);
+        locate_diffs(in_buf, new_buf, MIN(len, (s32)target->len), &f_diff,
+                     &l_diff);
 
         if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
 
@@ -4551,7 +4560,7 @@ pacemaker_fuzzing:
     abandon_entry:
     abandon_entry_puppet:
 
-      if (splice_cycle >= afl->SPLICE_CYCLES_puppet) {
+      if ((s64)splice_cycle >= afl->SPLICE_CYCLES_puppet) {
 
         afl->SPLICE_CYCLES_puppet =
             (rand_below(
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 2044c97d..a077469e 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -30,6 +30,9 @@
 
 static void *unsupported(afl_state_t *afl, unsigned int seed) {
 
+  (void)afl;
+  (void)seed;
+
   FATAL("Python Mutator cannot be called twice yet");
   return NULL;
 
@@ -111,6 +114,8 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
 
 static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
+  (void)afl;
+
   if (!module_name) { return NULL; }
 
   py_mutator_t *py = calloc(1, sizeof(py_mutator_t));
@@ -247,6 +252,8 @@ void finalize_py_module(void *py_mutator) {
 static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
                     unsigned int seed) {
 
+  (void)afl;
+
   PyObject *py_args, *py_value;
 
   /* Provide the init function a seed for the Python RNG */
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 71874283..f35df914 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -112,8 +112,10 @@ static u8 check_if_text(struct queue_entry *q) {
   u8  buf[MAX_FILE];
   s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp;
 
+  if (len >= MAX_FILE) len = MAX_FILE - 1;
   if ((fd = open(q->fname, O_RDONLY)) < 0) return 0;
   if ((comp = read(fd, buf, len)) != len) return 0;
+  buf[len] = 0;
   close(fd);
 
   while (offset < len) {
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index cb4c78df..9716be95 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -352,7 +352,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   }
 
-  if (use_num && num == pattern) {
+  if (use_num && (u64)num == pattern) {
 
     size_t old_len = endptr - buf_8;
     size_t num_len = snprintf(NULL, 0, "%lld", num);
@@ -659,12 +659,12 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
 
 }
 
-static u8 rtn_extend_encoding(afl_state_t *afl, struct cmp_header *h,
-                              u8 *pattern, u8 *repl, u8 *o_pattern, u32 idx,
-                              u8 *orig_buf, u8 *buf, u32 len, u8 *status) {
+static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
+                              u8 *o_pattern, u32 idx, u8 *orig_buf, u8 *buf,
+                              u32 len, u8 *status) {
 
   u32 i;
-  u32 its_len = MIN(32, len - idx);
+  u32 its_len = MIN((u32)32, len - idx);
 
   u8 save[32];
   memcpy(save, &buf[idx], its_len);
@@ -728,7 +728,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
 
     for (idx = 0; idx < len && fails < 8; ++idx) {
 
-      if (unlikely(rtn_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
+      if (unlikely(rtn_extend_encoding(afl, o->v0, o->v1, orig_o->v0, idx,
                                        orig_buf, buf, len, &status))) {
 
         return 1;
@@ -745,7 +745,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
 
       }
 
-      if (unlikely(rtn_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
+      if (unlikely(rtn_extend_encoding(afl, o->v1, o->v0, orig_o->v1, idx,
                                        orig_buf, buf, len, &status))) {
 
         return 1;
@@ -853,12 +853,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
 
     if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
 
-      afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
+      afl->stage_max +=
+          MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H);
 
     } else {
 
       afl->stage_max +=
-          MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
+          MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H);
 
     }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 44d3c522..97fcb3c8 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -38,7 +38,7 @@ u64 time_spent_working = 0;
 /* Execute target application, monitoring for timeouts. Return status
    information. The called program will update afl->fsrv->trace_bits. */
 
-fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
+fsrv_run_result_t __attribute__ ((hot)) fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
                                   u32 timeout) {
 
 #ifdef PROFILING
@@ -72,7 +72,7 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
    old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is
    rewound and truncated. */
 
-void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
+void __attribute__ ((hot)) write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
   s32  doc_fd;
@@ -138,7 +138,7 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
 
 /* The same, but with an adjustable gap. Used for trimming. */
 
-static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at,
+static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
                            u32 skip_len) {
 
   s32 fd = afl->fsrv.out_fd;
@@ -733,12 +733,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   len_p2 = next_pow2(q->len);
 
-  remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES);
+  remove_len = MAX(len_p2 / TRIM_START_STEPS, (u32)TRIM_MIN_BYTES);
 
   /* Continue until the number of steps gets too high or the stepover
      gets too small. */
 
-  while (remove_len >= MAX(len_p2 / TRIM_END_STEPS, TRIM_MIN_BYTES)) {
+  while (remove_len >= MAX(len_p2 / TRIM_END_STEPS, (u32)TRIM_MIN_BYTES)) {
 
     u32 remove_pos = remove_len;
 
@@ -819,16 +819,27 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
       fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
+      if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
+
+      u32 written = 0;
+      while (written < q->len) {
+
+        ssize_t result = write(fd, in_buf, q->len - written);
+        if (result > 0) written += result;
+
+      }
+
     } else {
 
       unlink(q->fname);                                    /* ignore errors */
       fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
 
-    }
+      if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
 
-    if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
+      ck_write(fd, in_buf, q->len, q->fname);
+
+    }
 
-    ck_write(fd, in_buf, q->len, q->fname);
     close(fd);
 
     memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size);
@@ -847,7 +858,7 @@ abort_trimming:
    error conditions, returning 1 if it's time to bail out. This is
    a helper function for fuzz_one(). */
 
-u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
+u8 __attribute__ ((hot)) common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   u8 fault;
 
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 7b30b5ea..aeb290bd 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -890,12 +890,12 @@ void show_stats(afl_state_t *afl) {
     if (afl->cpu_aff >= 0) {
 
       SAYF("%s" cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, spacing,
-           MIN(afl->cpu_aff, 999), cpu_color, MIN(cur_utilization, 999));
+           MIN(afl->cpu_aff, 999), cpu_color, MIN(cur_utilization, (u32)999));
 
     } else {
 
       SAYF("%s" cGRA "   [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color,
-           MIN(cur_utilization, 999));
+           MIN(cur_utilization, (u32)999));
 
     }
 
@@ -1081,7 +1081,7 @@ void show_init_stats(afl_state_t *afl) {
 
   if (afl->non_instrumented_mode && !(afl->afl_env.afl_hang_tmout)) {
 
-    afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
+    afl->hang_tmout = MIN((u32)EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
 
   }
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index da30797c..5dd092f2 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -79,7 +79,7 @@ static void at_exit() {
 
 /* Display usage hints. */
 
-static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
+static void usage(u8 *argv0, int more_help) {
 
   SAYF(
       "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
@@ -115,8 +115,8 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
       "                  if using QEMU, just use -c 0.\n\n"
 
       "Fuzzing behavior settings:\n"
-      "  -N            - do not unlink the fuzzing input file (only for "
-      "devices etc.!)\n"
+      "  -N            - do not unlink the fuzzing input file (for devices "
+      "etc.)\n"
       "  -d            - quick & dirty mode (skips deterministic steps)\n"
       "  -n            - fuzz without instrumentation (non-instrumented mode)\n"
       "  -x dict_file  - optional fuzzer dictionary (see README.md, its really "
@@ -289,9 +289,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
         if (afl->cpu_to_bind != -1) FATAL("Multiple -b options not supported");
 
-        if (sscanf(optarg, "%u", &afl->cpu_to_bind) < 0 || optarg[0] == '-')
+        if (sscanf(optarg, "%d", &afl->cpu_to_bind) < 0) {
+
           FATAL("Bad syntax used for -b");
 
+        }
+
         break;
 
       }
@@ -677,7 +680,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
         u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
 
-        if (limit_time_puppet2 < afl->limit_time_puppet) {
+        if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
 
           FATAL("limit_time overflow");
 
@@ -811,7 +814,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
 
-    usage(afl, argv[0], show_help);
+    usage(argv[0], show_help);
 
   }
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 71e975a1..0aa116e5 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -256,8 +256,8 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
 
 /* Execute target application. */
 
-static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv,
-                                          u8 *mem, u32 len) {
+static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
+                                          u32 len) {
 
   afl_fsrv_write_to_testcase(fsrv, mem, len);
 
@@ -444,6 +444,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
 
 static void handle_stop_sig(int sig) {
 
+  (void)sig;
   stop_soon = 1;
   afl_fsrv_killall();
 
@@ -1016,7 +1017,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
         }
 
-        showmap_run_target_forkserver(fsrv, use_argv, in_data, in_len);
+        showmap_run_target_forkserver(fsrv, in_data, in_len);
         ck_free(in_data);
         tcnt = write_results_to_file(fsrv, outfile);
 
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 68fcdd14..b50d8597 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -250,7 +250,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
 /* Execute target application. Returns 0 if the changes are a dud, or
    1 if they should be kept. */
 
-static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
+static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
                           u8 first_run) {
 
   afl_fsrv_write_to_testcase(fsrv, mem, len);
@@ -342,7 +342,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
 
 /* Actually minimize! */
 
-static void minimize(afl_forkserver_t *fsrv, char **argv) {
+static void minimize(afl_forkserver_t *fsrv) {
 
   static u32 alpha_map[256];
 
@@ -380,7 +380,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
       memset(tmp_buf + set_pos, '0', use_len);
 
       u8 res;
-      res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
+      res = tmin_run_target(fsrv, tmp_buf, in_len, 0);
 
       if (res) {
 
@@ -453,7 +453,7 @@ next_del_blksize:
     /* Tail */
     memcpy(tmp_buf + del_pos, in_data + del_pos + del_len, tail_len);
 
-    res = tmin_run_target(fsrv, argv, tmp_buf, del_pos + tail_len, 0);
+    res = tmin_run_target(fsrv, tmp_buf, del_pos + tail_len, 0);
 
     if (res) {
 
@@ -524,7 +524,7 @@ next_del_blksize:
 
     }
 
-    res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
+    res = tmin_run_target(fsrv, tmp_buf, in_len, 0);
 
     if (res) {
 
@@ -560,7 +560,7 @@ next_del_blksize:
     if (orig == '0') { continue; }
     tmp_buf[i] = '0';
 
-    res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
+    res = tmin_run_target(fsrv, tmp_buf, in_len, 0);
 
     if (res) {
 
@@ -623,6 +623,7 @@ finalize_all:
 
 static void handle_stop_sig(int sig) {
 
+  (void)sig;
   stop_soon = 1;
   afl_fsrv_killall();
 
@@ -1131,7 +1132,7 @@ int main(int argc, char **argv_orig, char **envp) {
   ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
        fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : "");
 
-  tmin_run_target(fsrv, use_argv, in_data, in_len, 1);
+  tmin_run_target(fsrv, in_data, in_len, 1);
 
   if (hang_mode && !fsrv->last_run_timed_out) {
 
@@ -1169,7 +1170,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  minimize(fsrv, use_argv);
+  minimize(fsrv);
 
   ACTF("Writing output to '%s'...", output_file);
 
diff --git a/test/test-all.sh b/test/test-all.sh
new file mode 100755
index 00000000..8df4bef9
--- /dev/null
+++ b/test/test-all.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+. ./test-basic.sh
+
+. ./test-llvm.sh
+
+. ./test-llvm-lto.sh
+
+. ./test-gcc-plugin.sh
+
+. ./test-libextensions.sh
+
+. ./test-qemu-mode.sh
+
+. ./test-unicorn-mode.sh
+
+. ./test-custom-mutators.sh
+
+. ./test-unittests.sh
+
+. ./test-post.sh
diff --git a/test/test-basic.sh b/test/test-basic.sh
new file mode 100755
index 00000000..9e4b03c3
--- /dev/null
+++ b/test/test-basic.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$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} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
+  AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
+  test -e test-instr.plain && {
+    $ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded"
+    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&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"
+        CODE=1
+      } || {
+        $ECHO "$GREEN[+] ${AFL_GCC} instrumentation present and working correctly"
+      }
+    } || {
+      $ECHO "$RED[!] ${AFL_GCC} instrumentation failed"
+      CODE=1
+    }
+    rm -f test-instr.plain.0 test-instr.plain.1
+    TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
+    test "$TUPLES" -gt 3 -a "$TUPLES" -lt 11 && {
+      $ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine"
+    } || {
+      $ECHO "$RED[!] ${AFL_GCC} instrumentation produces weird numbers: $TUPLES"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] ${AFL_GCC} failed"
+    echo CUT------------------------------------------------------------------CUT
+    uname -a
+    ../${AFL_GCC} -o test-instr.plain ../test-instr.c
+    echo CUT------------------------------------------------------------------CUT
+    CODE=1
+  }
+  test -e test-compcov.harden && {
+    grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
+      $ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working"
+    } || {
+      $ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened"
+      CODE=1
+    }
+    rm -f test-compcov.harden
+  } || {
+    $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
+    CODE=1
+  }
+  # now we want to be sure that afl-fuzz is working
+  # make sure core_pattern is set to core on linux
+  (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
+    $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
+    true
+  }) ||
+  # make sure crash reporter is disabled on Mac OS X
+  (test "$(uname -s)" = "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
+    $ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds"
+    {
+      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
+    } >>errors 2>&1
+    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+      $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}"
+    } || {
+      echo CUT------------------------------------------------------------------CUT
+      cat errors
+      echo CUT------------------------------------------------------------------CUT
+      $ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}"
+      CODE=1
+    }
+    echo 000000000000000000000000 > in/in2
+    echo 111 > in/in3
+    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" ;;
+      *)  $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" ;;
+        *)  $ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
+            CODE=1
+            ;;
+        esac
+    } else {
+      $ECHO "$YELLOW[-] no bash available, cannot test afl-cmin.bash"
+      INCOMPLETE=1
+    }
+    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 is not compiled, cannot test"
+  INCOMPLETE=1
+ }
+} || {
+ $ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
+ #this is not incomplete as this feature doesnt exist, so all good
+}
+
+. ./test-post.sh
diff --git a/test/test-custom-mutators.sh b/test/test-custom-mutators.sh
new file mode 100755
index 00000000..4d73739f
--- /dev/null
+++ b/test/test-custom-mutators.sh
@@ -0,0 +1,125 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Testing: custom mutator"
+test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
+  # normalize path
+  CUSTOM_MUTATOR_PATH=$(cd $(pwd)/../examples/custom_mutators;pwd)
+  test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
+    unset AFL_CC
+    # Compile the vulnerable program for single mutator
+    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
+      }
+    }
+    # 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
+      }
+    }
+    # Compile the custom mutator
+    cc -D_FIXED_CHAR=0x41 -g -fPIC -shared -I../include ../examples/custom_mutators/simple_example.c -o libexamplemutator.so > /dev/null 2>&1
+    cc -D_FIXED_CHAR=0x42 -g -fPIC -shared -I../include ../examples/custom_mutators/simple_example.c -o libexamplemutator2.so > /dev/null 2>&1
+    test -e test-custom-mutator -a -e ./libexamplemutator.so && {
+      # Create input directory
+      mkdir -p in
+      echo "00000" > in/in
+
+      # Run afl-fuzz w/ the C mutator
+      $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 5 seconds"
+      {
+        AFL_CUSTOM_MUTATOR_LIBRARY=./libexamplemutator.so AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V1 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
+      } >>errors 2>&1
+
+      # Check results
+      test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
+        $ECHO "$GREEN[+] afl-fuzz is working correctly with the C mutator"
+      } || {
+        echo CUT------------------------------------------------------------------CUT
+        cat errors
+        echo CUT------------------------------------------------------------------CUT
+        $ECHO "$RED[!] afl-fuzz is not working correctly with the C mutator"
+        CODE=1
+      }
+
+      # Clean
+      rm -rf out errors core.*
+
+      # Run afl-fuzz w/ multiple C mutators
+      $ECHO "$GREY[*] running afl-fuzz with multiple custom C mutators, this will take approx 5 seconds"
+      {
+        AFL_CUSTOM_MUTATOR_LIBRARY="./libexamplemutator.so;./libexamplemutator2.so" AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V1 -m ${MEM_LIMIT} -i in -o out -- ./test-multiple-mutators >>errors 2>&1
+      } >>errors 2>&1
+
+      test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
+        $ECHO "$GREEN[+] afl-fuzz is working correctly with multiple C mutators"
+      } || {
+        echo CUT------------------------------------------------------------------CUT
+        cat errors
+        echo CUT------------------------------------------------------------------CUT
+        $ECHO "$RED[!] afl-fuzz is not working correctly with multiple C mutators"
+        CODE=1
+      }
+
+      # Clean
+      rm -rf out errors core.*
+
+      # Run afl-fuzz w/ the Python mutator
+      $ECHO "$GREY[*] running afl-fuzz for the Python mutator, this will take approx 5 seconds"
+      {
+        export PYTHONPATH=${CUSTOM_MUTATOR_PATH}
+        export AFL_PYTHON_MODULE=example
+        AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V5 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
+        unset PYTHONPATH
+        unset AFL_PYTHON_MODULE
+      } >>errors 2>&1
+
+      # Check results
+      test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
+        $ECHO "$GREEN[+] afl-fuzz is working correctly with the Python mutator"
+      } || {
+        echo CUT------------------------------------------------------------------CUT
+        cat errors
+        echo CUT------------------------------------------------------------------CUT
+        $ECHO "$RED[!] afl-fuzz is not working correctly with the Python mutator"
+        CODE=1
+      }
+
+      # Clean
+      rm -rf in out errors core.*
+      rm -rf ${CUSTOM_MUTATOR_PATH}/__pycache__/
+      rm -f test-multiple-mutators test-custom-mutator libexamplemutator.so libexamplemutator2.so
+    } || {
+      ls .
+      ls ${CUSTOM_MUTATOR_PATH}
+      $ECHO "$RED[!] cannot compile the test program or the custom mutator"
+      CODE=1
+    }
+
+    #test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; }
+
+    make -C ../examples/custom_mutators clean > /dev/null 2>&1
+    rm -f test-custom-mutator
+    rm -f test-custom-mutators
+  } || {
+    $ECHO "$YELLOW[-] no custom mutators in $CUSTOM_MUTATOR_PATH, cannot test"
+    INCOMPLETE=1
+  }
+  unset CUSTOM_MUTATOR_PATH
+} || {
+  $ECHO "$YELLOW[-] no python support in afl-fuzz, cannot test"
+  INCOMPLETE=1
+}
+
+. ./test-post.sh
diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh
new file mode 100755
index 00000000..2ed10a72
--- /dev/null
+++ b/test/test-gcc-plugin.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Testing: gcc_plugin"
+test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
+  SAVE_AFL_CC=${AFL_CC}
+  export AFL_CC=`command -v gcc`
+  ../afl-gcc-fast -o test-instr.plain.gccpi ../test-instr.c > /dev/null 2>&1
+  AFL_HARDEN=1 ../afl-gcc-fast -o test-compcov.harden.gccpi test-compcov.c > /dev/null 2>&1
+  test -e test-instr.plain.gccpi && {
+    $ECHO "$GREEN[+] gcc_plugin compilation succeeded"
+    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain.gccpi > /dev/null 2>&1
+    ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain.gccpi < /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[!] gcc_plugin instrumentation should be different on different input but is not"
+        CODE=1
+      } || {
+        $ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly"
+        TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'`
+        test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
+          $ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine"
+        } || {
+          $ECHO "$RED[!] gcc_plugin instrumentation produces a weird numbers: $TUPLES"
+          $ECHO "$YELLOW[-] this is a known issue in gcc, not afl++. It is not flagged as an error because travis builds would all fail otherwise :-("
+          #CODE=1
+        }
+      }
+    } || {
+      $ECHO "$RED[!] gcc_plugin instrumentation failed"
+      CODE=1
+    }
+    rm -f test-instr.plain.0 test-instr.plain.1
+  } || {
+    $ECHO "$RED[!] gcc_plugin failed"
+    CODE=1
+  }
+
+  test -e test-compcov.harden.gccpi && test_compcov_binary_functionality ./test-compcov.harden.gccpi && {
+    grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden.gccpi > /dev/null 2>&1 && {
+      $ECHO "$GREEN[+] gcc_plugin hardened mode succeeded and is working"
+    } || {
+      $ECHO "$RED[!] gcc_plugin hardened mode is not hardened"
+      CODE=1
+    }
+    rm -f test-compcov.harden.gccpi
+  } || {
+    $ECHO "$RED[!] gcc_plugin hardened mode compilation failed"
+    CODE=1
+  }
+  # now we want to be sure that afl-fuzz is working
+  (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
+    $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
+    true
+  }) ||
+  # make sure crash reporter is disabled on Mac OS X
+  (test "$(uname -s)" = "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"
+    CODE=1
+    true
+  }) || {
+    mkdir -p in
+    echo 0 > in/in
+    $ECHO "$GREY[*] running afl-fuzz for gcc_plugin, this will take approx 10 seconds"
+    {
+      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain.gccpi >>errors 2>&1
+    } >>errors 2>&1
+    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+      $ECHO "$GREEN[+] afl-fuzz is working correctly with gcc_plugin"
+    } || {
+      echo CUT------------------------------------------------------------------CUT
+      cat errors
+      echo CUT------------------------------------------------------------------CUT
+      $ECHO "$RED[!] afl-fuzz is not working correctly with gcc_plugin"
+      CODE=1
+    }
+    rm -rf in out errors
+  }
+  rm -f test-instr.plain.gccpi
+
+  # 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
+  test -e test-compcov && test_compcov_binary_functionality ./test-compcov && {
+    echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && {
+      $ECHO "$GREEN[+] gcc_plugin instrumentlist feature works correctly"
+    } || {
+      $ECHO "$RED[!] gcc_plugin instrumentlist feature failed"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] gcc_plugin instrumentlist feature compilation failed"
+    CODE=1
+  }
+  rm -f test-compcov test.out instrumentlist.txt
+  ../afl-gcc-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
+  test -e test-persistent && {
+    echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
+      $ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly"
+    } || {
+      $ECHO "$RED[!] gcc_plugin persistent mode feature failed to work"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] gcc_plugin persistent mode feature compilation failed"
+    CODE=1
+  }
+  rm -f test-persistent
+  export AFL_CC=${SAVE_AFL_CC}
+} || {
+  $ECHO "$YELLOW[-] gcc_plugin not compiled, cannot test"
+  INCOMPLETE=1
+}
+
+. ./test-post.sh
diff --git a/test/test-libextensions.sh b/test/test-libextensions.sh
new file mode 100755
index 00000000..905a4cbc
--- /dev/null
+++ b/test/test-libextensions.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+test -z "$AFL_CC" && unset AFL_CC
+
+$ECHO "$BLUE[*] Testing: shared library extensions"
+cc $CFLAGS -o test-compcov test-compcov.c > /dev/null 2>&1
+test -e ../libtokencap.so && {
+  AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1
+  grep -q BUGMENOT token.out > /dev/null 2>&1 && {
+    $ECHO "$GREEN[+] libtokencap did successfully capture tokens"
+  } || {
+    $ECHO "$RED[!] libtokencap did not capture tokens"
+    CODE=1
+  }
+  rm -f token.out
+} || {
+  $ECHO "$YELLOW[-] libtokencap is not compiled, cannot test"
+  INCOMPLETE=1
+}
+test -e ../libdislocator.so && {
+  {
+    ulimit -c 1
+    # DYLD_INSERT_LIBRARIES and DYLD_FORCE_FLAT_NAMESPACE is used on Darwin/MacOSX
+    LD_PRELOAD=../libdislocator.so DYLD_INSERT_LIBRARIES=../libdislocator.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov BUFFEROVERFLOW > test.out 2>/dev/null
+  } > /dev/null 2>&1
+  grep -q BUFFEROVERFLOW test.out > /dev/null 2>&1 && {
+    $ECHO "$RED[!] libdislocator did not detect the memory corruption"
+    CODE=1
+  } || {
+    $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
+  }
+  rm -f test.out core test-compcov.core core.test-compcov
+} || {
+  $ECHO "$YELLOW[-] libdislocator is not compiled, cannot test"
+  INCOMPLETE=1
+}
+rm -f test-compcov
+
+test -z "$AFL_CC" && {
+  if type gcc >/dev/null; then
+    export AFL_CC=gcc
+  else
+    if type clang >/dev/null; then
+      export AFL_CC=clang
+    fi
+  fi
+}
+
+. ./test-post.sh
diff --git a/test/test-llvm-lto.sh b/test/test-llvm-lto.sh
new file mode 100755
index 00000000..6b327633
--- /dev/null
+++ b/test/test-llvm-lto.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Testing: LTO llvm_mode"
+test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
+  # on FreeBSD need to set AFL_CC
+  test `uname -s` = 'FreeBSD' && {
+    if type clang >/dev/null; then
+      export AFL_CC=`command -v clang`
+    else
+      export AFL_CC=`$LLVM_CONFIG --bindir`/clang
+    fi
+  }
+
+  ../afl-clang-lto -o test-instr.plain ../test-instr.c > /dev/null 2>&1
+  test -e test-instr.plain && {
+    $ECHO "$GREEN[+] llvm_mode LTO compilation succeeded"
+    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&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 -q test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
+        $ECHO "$RED[!] llvm_mode LTO instrumentation should be different on different input but is not"
+        CODE=1
+      } || {
+        $ECHO "$GREEN[+] llvm_mode LTO instrumentation present and working correctly"
+        TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
+        test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
+          $ECHO "$GREEN[+] llvm_mode LTO run reported $TUPLES instrumented locations which is fine"
+        } || {
+          $ECHO "$RED[!] llvm_mode LTO instrumentation produces weird numbers: $TUPLES"
+          CODE=1
+        }
+      }
+    } || {
+      $ECHO "$RED[!] llvm_mode LTO instrumentation failed"
+      CODE=1
+    }
+    rm -f test-instr.plain.0 test-instr.plain.1
+  } || {
+    $ECHO "$RED[!] LTO llvm_mode failed"
+    CODE=1
+  }
+  rm -f test-instr.plain
+
+  echo foobar.c > instrumentlist.txt
+  AFL_DEBUG=1 AFL_LLVM_INSTRUMENT_FILE=instrumentlist.txt ../afl-clang-lto -o test-compcov test-compcov.c > test.out 2>&1
+  test -e test-compcov && {
+    grep -q "No instrumentation targets found" test.out && {
+      $ECHO "$GREEN[+] llvm_mode LTO instrumentlist feature works correctly"
+    } || {
+      $ECHO "$RED[!] llvm_mode LTO instrumentlist feature failed"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] llvm_mode LTO instrumentlist feature compilation failed"
+    CODE=1
+  }
+  rm -f test-compcov test.out instrumentlist.txt
+  ../afl-clang-lto -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
+  test -e test-persistent && {
+    echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && {
+      $ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly"
+    } || {
+      $ECHO "$RED[!] llvm_mode LTO persistent mode feature failed to work"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] llvm_mode LTO persistent mode feature compilation failed"
+    CODE=1
+  }
+  rm -f test-persistent
+} || {
+  $ECHO "$YELLOW[-] LTO llvm_mode not compiled, cannot test"
+  INCOMPLETE=1
+}
+
+. ./test-post.sh
diff --git a/test/test-llvm.sh b/test/test-llvm.sh
new file mode 100755
index 00000000..feeb3992
--- /dev/null
+++ b/test/test-llvm.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Testing: llvm_mode, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
+test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
+  # on FreeBSD need to set AFL_CC
+  test `uname -s` = 'FreeBSD' && {
+    if type clang >/dev/null; then
+      export AFL_CC=`command -v clang`
+    else
+      export AFL_CC=`$LLVM_CONFIG --bindir`/clang
+    fi
+  }
+  ../afl-clang-fast -o test-instr.plain ../test-instr.c > /dev/null 2>&1
+  AFL_HARDEN=1 ../afl-clang-fast -o test-compcov.harden test-compcov.c > /dev/null 2>&1
+  test -e test-instr.plain && {
+    $ECHO "$GREEN[+] llvm_mode compilation succeeded"
+    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&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[!] llvm_mode instrumentation should be different on different input but is not"
+        CODE=1
+      } || {
+        $ECHO "$GREEN[+] llvm_mode instrumentation present and working correctly"
+        TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
+        test "$TUPLES" -gt 3 -a "$TUPLES" -lt 8 && {
+          $ECHO "$GREEN[+] llvm_mode run reported $TUPLES instrumented locations which is fine"
+        } || {
+          $ECHO "$RED[!] llvm_mode instrumentation produces weird numbers: $TUPLES"
+          CODE=1
+        }
+      }
+    } || {
+      $ECHO "$RED[!] llvm_mode instrumentation failed"
+      CODE=1
+    }
+    rm -f test-instr.plain.0 test-instr.plain.1
+  } || {
+    $ECHO "$RED[!] llvm_mode failed"
+    CODE=1
+  }
+  test -e test-compcov.harden && test_compcov_binary_functionality ./test-compcov.harden && {
+    grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
+      $ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working"
+    } || {
+      $ECHO "$RED[!] llvm_mode hardened mode is not hardened"
+      CODE=1
+    }
+    rm -f test-compcov.harden
+  } || {
+    $ECHO "$RED[!] llvm_mode hardened mode compilation failed"
+    CODE=1
+  }
+  # now we want to be sure that afl-fuzz is working
+  (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
+    $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
+    true
+  }) ||
+  # make sure crash reporter is disabled on Mac OS X
+  (test "$(uname -s)" = "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"
+    CODE=1
+    true
+  }) || {
+    mkdir -p in
+    echo 0 > in/in
+    $ECHO "$GREY[*] running afl-fuzz for llvm_mode, this will take approx 10 seconds"
+    {
+      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
+    } >>errors 2>&1
+    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+      $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode"
+    } || {
+      echo CUT------------------------------------------------------------------CUT
+      cat errors
+      echo CUT------------------------------------------------------------------CUT
+      $ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode"
+      CODE=1
+    }
+    test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" || {
+      echo 000000000000000000000000 > in/in2
+      echo 111 > in/in3
+      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" ;;
+        *)  $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 type 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" ;;
+          *)  $ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
+              CODE=1
+              ;;
+          esac
+      } else {
+        $ECHO "$YELLOW[-] no bash available, cannot test afl-cmin.bash"
+        INCOMPLETE=1
+      }
+      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 in2
+    }
+    rm -rf in out errors
+  }
+  rm -f test-instr.plain
+
+  # now for the special llvm_mode things
+  test -e ../libLLVMInsTrim.so && {
+    AFL_LLVM_INSTRUMENT=CFG AFL_LLVM_INSTRIM_LOOPHEAD=1 ../afl-clang-fast -o test-instr.instrim ../test-instr.c > /dev/null 2>test.out
+    test -e test-instr.instrim && {
+      TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.instrim 2>&1 | grep Captur | awk '{print$3}'`
+      test "$TUPLES" -gt 2 -a "$TUPLES" -lt 5 && {
+        $ECHO "$GREEN[+] llvm_mode InsTrim reported $TUPLES instrumented locations which is fine"
+      } || {
+        $ECHO "$RED[!] llvm_mode InsTrim instrumentation produces weird numbers: $TUPLES"
+        CODE=1
+      }
+      rm -f test-instr.instrim test.out
+    } || {
+      $ECHO "$RED[!] llvm_mode InsTrim compilation failed"
+      CODE=1
+    }
+  } || {
+    $ECHO "$YELLOW[-] llvm_mode InsTrim not compiled, cannot test"
+    INCOMPLETE=1
+  }
+  AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > test.out 2>&1
+  test -e test-compcov.compcov && test_compcov_binary_functionality ./test-compcov.compcov && {
+    grep --binary-files=text -Eq " [ 123][0-9][0-9] location| [3-9][0-9] location" test.out && {
+      $ECHO "$GREEN[+] llvm_mode laf-intel/compcov feature works correctly"
+    } || {
+      $ECHO "$RED[!] llvm_mode laf-intel/compcov feature failed"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] llvm_mode laf-intel/compcov feature compilation failed"
+    CODE=1
+  }
+  rm -f test-compcov.compcov test.out
+  AFL_LLVM_INSTRUMENT=AFL AFL_LLVM_LAF_SPLIT_FLOATS=1 ../afl-clang-fast -o test-floatingpoint test-floatingpoint.c >errors 2>&1
+  test -e test-floatingpoint && {
+    mkdir -p in
+    echo ZZZZ > in/in
+    $ECHO "$GREY[*] running afl-fuzz with floating point splitting, this will take max. 30 seconds"
+    {
+      AFL_BENCH_UNTIL_CRASH=1 AFL_NO_UI=1 ../afl-fuzz -s 1 -V30 -m ${MEM_LIMIT} -i in -o out -- ./test-floatingpoint >>errors 2>&1
+    } >>errors 2>&1
+    test -n "$( ls out/crashes/id:* 2>/dev/null )" && {
+      $ECHO "$GREEN[+] llvm_mode laf-intel floatingpoint splitting feature works correctly"
+    } || {
+      cat errors
+      $ECHO "$RED[!] llvm_mode laf-intel floatingpoint splitting feature failed"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] llvm_mode laf-intel floatingpoint splitting feature compilation failed"
+    CODE=1
+  }
+  rm -f test-floatingpoint test.out in/in errors core.*
+  echo foobar.c > instrumentlist.txt
+  AFL_DEBUG=1 AFL_LLVM_INSTRUMENT_FILE=instrumentlist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1
+  test -e test-compcov && test_compcov_binary_functionality ./test-compcov && {
+    grep -q "No instrumentation targets found" test.out && {
+      $ECHO "$GREEN[+] llvm_mode instrumentlist feature works correctly"
+    } || {
+      $ECHO "$RED[!] llvm_mode instrumentlist feature failed"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] llvm_mode instrumentlist feature compilation failed"
+    CODE=1
+  }
+  rm -f test-compcov test.out instrumentlist.txt
+  AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
+  test -e test-cmplog && {
+    $ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
+    {
+      mkdir -p in
+      echo 0000000000000000000000000 > in/in
+      AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V60 -i in -o out -c./test-cmplog -- ./test-cmplog >>errors 2>&1
+    } >>errors 2>&1
+    test -n "$( ls out/crashes/id:000000* out/hangs/id:000000* 2>/dev/null )" & {
+      $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
+    } || {
+      echo CUT------------------------------------------------------------------CUT
+      cat errors
+      echo CUT------------------------------------------------------------------CUT
+      $ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode cmplog"
+      CODE=1
+    }
+  } || {
+    $ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
+    INCOMPLETE=1
+  }
+  rm -rf errors test-cmplog in core.*
+  ../afl-clang-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
+  test -e test-persistent && {
+    echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
+      $ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly"
+    } || {
+      $ECHO "$RED[!] llvm_mode persistent mode feature failed to work"
+      CODE=1
+    }
+  } || {
+    $ECHO "$RED[!] llvm_mode persistent mode feature compilation failed"
+    CODE=1
+  }
+  rm -f test-persistent
+} || {
+  $ECHO "$YELLOW[-] llvm_mode not compiled, cannot test"
+  INCOMPLETE=1
+}
+
+. ./test-post.sh
diff --git a/test/test-post.sh b/test/test-post.sh
new file mode 100755
index 00000000..c1e22498
--- /dev/null
+++ b/test/test-post.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+AFL_TEST_DEPTH=$((AFL_TEST_DEPTH-1))
+
+if [ $AFL_TEST_DEPTH = 0 ]; then
+# All runs done :)
+
+$ECHO "$GREY[*] all test cases completed.$RESET"
+test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed"
+test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed"
+test "$CODE" = "0" && $ECHO "$GREEN[+] all tests were successful :-)$RESET"
+test "$CODE" = "0" || $ECHO "$RED[!] failure in tests :-($RESET"
+exit $CODE
+
+fi
diff --git a/test/test-pre.sh b/test/test-pre.sh
new file mode 100755
index 00000000..3e2d475d
--- /dev/null
+++ b/test/test-pre.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+
+# All tests should start with sourcing test-pre.sh and finish with sourcing test-post.sh
+# They may set an error code with $CODE=1
+# If tests are incomplete, they may set $INCOMPLETE=1
+
+AFL_TEST_DEPTH=$((AFL_TEST_DEPTH+1))
+
+if [ $AFL_TEST_DEPTH = 1 ]; then
+# First run :)
+
+#
+# Ensure we have: test, type, diff, grep -qE
+#
+test -z "" 2>/dev/null || { echo Error: test command not found ; exit 1 ; }
+GREP=`type grep > /dev/null 2>&1 && echo OK`
+test "$GREP" = OK || { echo Error: grep command not found ; exit 1 ; }
+echo foobar | grep -qE 'asd|oob' 2>/dev/null || { echo Error: grep command does not support -q and/or -E option ; exit 1 ; }
+test -e ./test-all.sh || cd $(dirname $0) || exit 1
+test -e ./test-all.sh || { echo Error: you must be in the test/ directory ; exit 1 ; }
+export AFL_PATH=`pwd`/..
+export AFL_NO_AFFINITY=1 # workaround for travis that fails for no avail cores 
+
+echo 1 > test.1
+echo 1 > test.2
+OK=OK
+diff test.1 test.2 >/dev/null 2>&1 || OK=
+rm -f test.1 test.2
+test -z "$OK" && { echo Error: diff is not working ; exit 1 ; }
+test -z "$LLVM_CONFIG" && LLVM_CONFIG=llvm-config
+
+# check for '-a' option of grep
+if grep -a test test-all.sh >/dev/null 2>&1; then
+  GREPAOPTION=' -a'
+else
+  GREPAOPTION=
+fi
+
+test_compcov_binary_functionality() {
+  RUN="../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- $1"
+  $RUN 'LIBTOKENCAP' | grep 'your string was LIBTOKENCAP' \
+    && $RUN 'BUGMENOT' | grep 'your string was BUGMENOT' \
+    && $RUN 'BANANA' | grep 'your string started with BAN' \
+    && $RUN 'APRI' | grep 'your string was APRI' \
+    && $RUN 'kiWI' | grep 'your string was Kiwi' \
+    && $RUN 'Avocado' | grep 'your string was avocado' \
+    && $RUN 'GRAX' 3 | grep 'your string was a prefix of Grapes' \
+    && $RUN 'LOCALVARIABLE' | grep 'local var memcmp works!' \
+    && $RUN 'abc' | grep 'short local var memcmp works!' \
+    && $RUN 'GLOBALVARIABLE' | grep 'global var memcmp works!'
+} > /dev/null
+
+ECHO="printf %b\\n"
+$ECHO \\101 2>&1 | grep -qE '^A' || {
+  ECHO=
+  test -e /bin/printf && {
+    ECHO="/bin/printf %b\\n"
+    $ECHO "\\101" 2>&1 | grep -qE '^A' || ECHO=
+  }
+}
+test -z "$ECHO" && { printf Error: printf command does not support octal character codes ; exit 1 ; }
+
+export AFL_EXIT_WHEN_DONE=1
+export AFL_SKIP_CPUFREQ=1
+export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
+unset AFL_NO_X86
+unset AFL_QUIET
+unset AFL_DEBUG
+unset AFL_HARDEN
+unset AFL_USE_ASAN
+unset AFL_USE_MSAN
+unset AFL_USE_UBSAN
+unset AFL_TMPDIR
+unset AFL_CC
+unset AFL_PRELOAD
+unset AFL_GCC_INSTRUMENT_FILE
+unset AFL_LLVM_INSTRUMENT_FILE
+unset AFL_LLVM_INSTRIM
+unset AFL_LLVM_LAF_SPLIT_SWITCHES
+unset AFL_LLVM_LAF_TRANSFORM_COMPARES
+unset AFL_LLVM_LAF_SPLIT_COMPARES
+unset AFL_QEMU_PERSISTENT_ADDR
+unset AFL_QEMU_PERSISTENT_RETADDR_OFFSET
+unset AFL_QEMU_PERSISTENT_GPR
+unset AFL_QEMU_PERSISTENT_RET
+unset AFL_QEMU_PERSISTENT_HOOK
+unset AFL_QEMU_PERSISTENT_CNT
+unset AFL_CUSTOM_MUTATOR_LIBRARY
+unset AFL_PYTHON_MODULE
+unset AFL_PRELOAD
+unset LD_PRELOAD
+
+rm -rf in in2 out
+
+export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1:symbolize=0
+export AFL_LLVM_INSTRUMENT=AFL
+
+# on OpenBSD we need to work with llvm from /usr/local/bin
+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
+} || {
+  AFL_GCC=afl-gcc
+}
+command -v gcc >/dev/null 2>&1 || AFL_GCC=afl-clang
+
+SYS=`uname -m`
+
+GREY="\\033[1;90m"
+BLUE="\\033[1;94m"
+GREEN="\\033[0;32m"
+RED="\\033[0;31m"
+YELLOW="\\033[1;93m"
+RESET="\\033[0m"
+
+MEM_LIMIT=none
+
+export PATH="${PATH}:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
+
+$ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
+
+test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
+
+CODE=0
+INCOMPLETE=0
+
+fi
\ No newline at end of file
diff --git a/test/test-qemu-mode.sh b/test/test-qemu-mode.sh
new file mode 100755
index 00000000..85a0b8b5
--- /dev/null
+++ b/test/test-qemu-mode.sh
@@ -0,0 +1,217 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Testing: qemu_mode"
+test -e ../afl-qemu-trace && {
+  cc -pie -fPIE -o test-instr ../test-instr.c
+  cc -o test-compcov test-compcov.c
+  test -e test-instr -a -e test-compcov && {
+    {
+      mkdir -p in
+      echo 00000 > in/in
+      $ECHO "$GREY[*] running afl-fuzz for qemu_mode, this will take approx 10 seconds"
+      {
+        ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1
+      } >>errors 2>&1
+      test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+        $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode"
+        RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
+      } || {
+        echo CUT------------------------------------------------------------------CUT
+        cat errors
+        echo CUT------------------------------------------------------------------CUT
+        $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode"
+        CODE=1
+      }
+      rm -f errors
+
+      $ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds"
+      {
+        {
+          if file test-instr | grep -q "32-bit"; then
+            # for 32-bit reduce 8 nibbles to the lower 7 nibbles
+	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
+          else
+            # for 64-bit reduce 16 nibbles to the lower 9 nibbles
+	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
+          fi
+          export AFL_ENTRYPOINT=`expr 0x4${ADDR_LOWER_PART}`
+          $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr)
+          ../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr
+          unset AFL_ENTRYPOINT
+        } >>errors 2>&1
+      } >>errors 2>&1
+      test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
+        $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode AFL_ENTRYPOINT"
+        RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
+      } || {
+        echo CUT------------------------------------------------------------------CUT
+        cat errors
+        echo CUT------------------------------------------------------------------CUT
+        $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode AFL_ENTRYPOINT"
+        CODE=1
+      }
+      rm -f errors
+
+      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
+        test -e ../libcompcov.so && {
+          $ECHO "$GREY[*] running afl-fuzz for qemu_mode compcov, this will take approx 10 seconds"
+          {
+            export AFL_PRELOAD=../libcompcov.so
+            export AFL_COMPCOV_LEVEL=2
+            ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1
+            unset AFL_PRELOAD
+            unset AFL_COMPCOV_LEVEL
+          } >>errors 2>&1
+          test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
+            $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode compcov"
+          } || {
+            echo CUT------------------------------------------------------------------CUT
+            cat errors
+            echo CUT------------------------------------------------------------------CUT
+            $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode compcov"
+            CODE=1
+          }
+        } || {
+          $ECHO "$YELLOW[-] we cannot test qemu_mode compcov because it is not present"
+          INCOMPLETE=1
+        }
+        rm -f errors
+      } || {
+       $ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode compcov"
+      }
+      
+      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
+        $ECHO "$GREY[*] running afl-fuzz for qemu_mode cmplog, this will take approx 10 seconds"
+        {
+          ../afl-fuzz -m none -V10 -Q -c 0 -i in -o out -- ./test-compcov >>errors 2>&1
+        } >>errors 2>&1
+        test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
+          $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode cmplog"
+        } || {
+          echo CUT------------------------------------------------------------------CUT
+          cat errors
+          echo CUT------------------------------------------------------------------CUT
+          $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode cmplog"
+          CODE=1
+        }
+        rm -f errors
+      } || {
+       $ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode cmplog"
+      }
+
+      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
+        $ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
+        {
+          if file test-instr | grep -q "32-bit"; then
+            # for 32-bit reduce 8 nibbles to the lower 7 nibbles
+	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
+          else
+            # for 64-bit reduce 16 nibbles to the lower 9 nibbles
+	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
+          fi
+          export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4${ADDR_LOWER_PART}`
+          export AFL_QEMU_PERSISTENT_GPR=1
+          $ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')"
+          env|grep AFL_|sort
+          file test-instr
+          ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr
+          unset AFL_QEMU_PERSISTENT_ADDR
+        } >>errors 2>&1
+        test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+          $ECHO "$GREEN[+] afl-fuzz is working correctly with persistent qemu_mode"
+          RUNTIMEP=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
+          test -n "$RUNTIME" -a -n "$RUNTIMEP" && {
+            DIFF=`expr $RUNTIMEP / $RUNTIME`
+            test "$DIFF" -gt 1 && { # must be at least twice as fast
+              $ECHO "$GREEN[+] persistent qemu_mode was noticeable faster than standard qemu_mode"
+            } || {
+              $ECHO "$YELLOW[-] persistent qemu_mode was not noticeable faster than standard qemu_mode"
+            }
+          } || {
+            $ECHO "$YELLOW[-] we got no data on executions performed? weird!"
+          }
+        } || {
+          echo CUT------------------------------------------------------------------CUT
+          cat errors
+          echo CUT------------------------------------------------------------------CUT
+          $ECHO "$RED[!] afl-fuzz is not working correctly with persistent qemu_mode"
+          CODE=1
+        }
+        rm -rf in out errors
+      } || {
+       $ECHO "$YELLOW[-] not an intel or arm platform, cannot test persistent qemu_mode"
+      }
+
+      test -e ../qemu_mode/unsigaction/unsigaction32.so && {
+        ${AFL_CC} -o test-unsigaction32 -m32 test-unsigaction.c >> errors 2>&1 && {
+	  ./test-unsigaction32
+          RETVAL_NORMAL32=$?
+	  LD_PRELOAD=../qemu_mode/unsigaction/unsigaction32.so ./test-unsigaction32
+          RETVAL_LIBUNSIGACTION32=$?
+	  test $RETVAL_NORMAL32 = "2" -a $RETVAL_LIBUNSIGACTION32 = "0" && {
+            $ECHO "$GREEN[+] qemu_mode unsigaction library (32 bit) ignores signals"
+	  } || {
+	    test $RETVAL_NORMAL32 != "2" && {
+	      $ECHO "$RED[!] cannot trigger signal in test program (32 bit)"
+	    }
+	    test $RETVAL_LIBUNSIGACTION32 != "0" && {
+	      $ECHO "$RED[!] signal in test program (32 bit) is not ignored with unsigaction"
+	    }
+            CODE=1
+          }
+        } || {
+          echo CUT------------------------------------------------------------------CUT
+          cat errors
+          echo CUT------------------------------------------------------------------CUT
+	  $ECHO "$RED[!] cannot compile test program (32 bit) for unsigaction library"
+          CODE=1
+        }
+      } || {
+        $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (32 bit) because it is not present"
+        INCOMPLETE=1
+      }
+      test -e ../qemu_mode/unsigaction/unsigaction64.so && {
+        ${AFL_CC} -o test-unsigaction64 -m64 test-unsigaction.c >> errors 2>&1 && {
+	  ./test-unsigaction64
+          RETVAL_NORMAL64=$?
+	  LD_PRELOAD=../qemu_mode/unsigaction/unsigaction64.so ./test-unsigaction64
+          RETVAL_LIBUNSIGACTION64=$?
+	  test $RETVAL_NORMAL64 = "2" -a $RETVAL_LIBUNSIGACTION64 = "0" && {
+            $ECHO "$GREEN[+] qemu_mode unsigaction library (64 bit) ignores signals"
+	  } || {
+	    test $RETVAL_NORMAL64 != "2" && {
+	      $ECHO "$RED[!] cannot trigger signal in test program (64 bit)"
+	    }
+	    test $RETVAL_LIBUNSIGACTION64 != "0" && {
+	      $ECHO "$RED[!] signal in test program (64 bit) is not ignored with unsigaction"
+	    }
+            CODE=1
+          }
+          unset LD_PRELOAD
+        } || {
+          echo CUT------------------------------------------------------------------CUT
+          cat errors
+          echo CUT------------------------------------------------------------------CUT
+	  $ECHO "$RED[!] cannot compile test program (64 bit) for unsigaction library"
+          CODE=1
+        }
+      } || {
+        $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (64 bit) because it is not present"
+        INCOMPLETE=1
+      }
+      rm -rf errors test-unsigaction32 test-unsigaction64
+    }
+  } || {
+    $ECHO "$RED[!] gcc compilation of test targets failed - what is going on??"
+    CODE=1
+  }
+
+  rm -f test-instr test-compcov
+} || {
+  $ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
+  INCOMPLETE=1
+}
+
+. ./test-post.sh
diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh
new file mode 100755
index 00000000..eb2ad294
--- /dev/null
+++ b/test/test-unicorn-mode.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Testing: unicorn_mode"
+test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shellcode && {
+  test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
+    {
+      # We want to see python errors etc. in logs, in case something doesn't work
+      export AFL_DEBUG_CHILD_OUTPUT=1
+
+      # some python version should be available now
+      PYTHONS="`command -v python3` `command -v python` `command -v python2`"
+      EASY_INSTALL_FOUND=0
+      for PYTHON in $PYTHONS ; do
+
+        if $PYTHON -c "help('easy_install');" </dev/null | grep -q module ; then
+
+            EASY_INSTALL_FOUND=1
+            PY=$PYTHON
+            break
+
+        fi
+
+      done
+      if [ "0" = $EASY_INSTALL_FOUND ]; then
+
+        echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools'."
+        PREREQ_NOTFOUND=1
+
+      fi
+
+
+      cd ../unicorn_mode/samples/persistent
+      make >>errors 2>&1
+      $ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds"
+      AFL_DEBUG_CHILD_OUTPUT=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
+      test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+        $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)"
+      } || {
+        echo CUT------------------------------------------------------------------CUT
+        cat errors
+        echo CUT------------------------------------------------------------------CUT
+        $ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode (persistent)"
+        CODE=1
+      }
+
+      rm -rf out errors >/dev/null
+      make clean >/dev/null
+      cd ../../../test
+
+      # travis workaround
+      test "$PY" = "/opt/pyenv/shims/python" -a -x /usr/bin/python && PY=/usr/bin/python
+      mkdir -p in
+      echo 0 > in/in
+      $ECHO "$GREY[*] Using python binary $PY"
+      if ! $PY -c 'import unicornafl' 2>/dev/null ; then
+        $ECHO "$YELLOW[-] we cannot test unicorn_mode for python because it is not present"
+        INCOMPLETE=1
+      else
+      {
+        $ECHO "$GREY[*] running afl-fuzz for unicorn_mode in python, this will take approx 25 seconds"
+        {
+          ../afl-fuzz -m ${MEM_LIMIT} -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1
+        } >>errors 2>&1
+        test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
+          $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode"
+        } || {
+          echo CUT------------------------------------------------------------------CUT
+          cat errors
+          echo CUT------------------------------------------------------------------CUT
+          $ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode"
+          CODE=1
+        }
+        rm -f errors
+
+        printf '\x01\x01' > in/in
+        # This seed is close to the first byte of the comparison.
+        # If CompCov works, a new tuple will appear in the map => new input in queue
+        $ECHO "$GREY[*] running afl-fuzz for unicorn_mode compcov, this will take approx 35 seconds"
+        {
+          export AFL_COMPCOV_LEVEL=2
+          ../afl-fuzz -m ${MEM_LIMIT} -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1
+          unset AFL_COMPCOV_LEVEL
+        } >>errors 2>&1
+        test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
+          $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode compcov"
+        } || {
+          echo CUT------------------------------------------------------------------CUT
+          cat errors
+          echo CUT------------------------------------------------------------------CUT
+          $ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode compcov"
+          CODE=1
+        }
+        rm -rf in out errors
+      }
+      fi
+
+      unset AFL_DEBUG_CHILD_OUTPUT
+
+    }
+  } || {
+    $ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??"
+    CODE=1
+  }
+
+} || {
+  $ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
+  INCOMPLETE=1
+}
+
+. ./test-post.sh
diff --git a/test/test-unittests.sh b/test/test-unittests.sh
new file mode 100755
index 00000000..f540b5f8
--- /dev/null
+++ b/test/test-unittests.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+. ./test-pre.sh
+
+$ECHO "$BLUE[*] Execution cmocka Unit-Tests $GREY"
+unset AFL_CC
+make -C .. unit || CODE=1 INCOMPLETE=1 :
+
+. ./test-post.sh
diff --git a/test/test.sh b/test/test.sh
deleted file mode 100755
index 46843d4a..00000000
--- a/test/test.sh
+++ /dev/null
@@ -1,1181 +0,0 @@
-#!/bin/sh
-
-#
-# Ensure we have: test, type, diff, grep -qE
-#
-test -z "" 2>/dev/null || { echo Error: test command not found ; exit 1 ; }
-GREP=`type grep > /dev/null 2>&1 && echo OK`
-test "$GREP" = OK || { echo Error: grep command not found ; exit 1 ; }
-echo foobar | grep -qE 'asd|oob' 2>/dev/null || { echo Error: grep command does not support -q and/or -E option ; exit 1 ; }
-test -e ./test.sh || cd $(dirname $0) || exit 1
-test -e ./test.sh || { echo Error: you must be in the test/ directory ; exit 1 ; }
-export AFL_PATH=`pwd`/..
-
-echo 1 > test.1
-echo 1 > test.2
-OK=OK
-diff test.1 test.2 >/dev/null 2>&1 || OK=
-rm -f test.1 test.2
-test -z "$OK" && { echo Error: diff is not working ; exit 1 ; }
-test -z "$LLVM_CONFIG" && LLVM_CONFIG=llvm-config
-
-# check for '-a' option of grep
-if grep -a test test.sh >/dev/null 2>&1; then
-  GREPAOPTION=' -a'
-else
-  GREPAOPTION=
-fi
-
-test_compcov_binary_functionality() {
-  RUN="../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- $1"
-  $RUN 'LIBTOKENCAP' | grep 'your string was LIBTOKENCAP' \
-    && $RUN 'BUGMENOT' | grep 'your string was BUGMENOT' \
-    && $RUN 'BANANA' | grep 'your string started with BAN' \
-    && $RUN 'APRI' | grep 'your string was APRI' \
-    && $RUN 'kiWI' | grep 'your string was Kiwi' \
-    && $RUN 'Avocado' | grep 'your string was avocado' \
-    && $RUN 'GRAX' 3 | grep 'your string was a prefix of Grapes' \
-    && $RUN 'LOCALVARIABLE' | grep 'local var memcmp works!' \
-    && $RUN 'abc' | grep 'short local var memcmp works!' \
-    && $RUN 'GLOBALVARIABLE' | grep 'global var memcmp works!'
-} > /dev/null
-
-ECHO="printf %b\\n"
-$ECHO \\101 2>&1 | grep -qE '^A' || {
-  ECHO=
-  test -e /bin/printf && {
-    ECHO="/bin/printf %b\\n"
-    $ECHO "\\101" 2>&1 | grep -qE '^A' || ECHO=
-  }
-}
-test -z "$ECHO" && { printf Error: printf command does not support octal character codes ; exit 1 ; }
-
-CODE=0
-INCOMPLETE=0
-
-export AFL_EXIT_WHEN_DONE=1
-export AFL_SKIP_CPUFREQ=1
-export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
-unset AFL_NO_X86
-unset AFL_QUIET
-unset AFL_DEBUG
-unset AFL_HARDEN
-unset AFL_USE_ASAN
-unset AFL_USE_MSAN
-unset AFL_USE_UBSAN
-unset AFL_TMPDIR
-unset AFL_CC
-unset AFL_PRELOAD
-unset AFL_GCC_INSTRUMENT_FILE
-unset AFL_LLVM_INSTRUMENT_FILE
-unset AFL_LLVM_INSTRIM
-unset AFL_LLVM_LAF_SPLIT_SWITCHES
-unset AFL_LLVM_LAF_TRANSFORM_COMPARES
-unset AFL_LLVM_LAF_SPLIT_COMPARES
-unset AFL_QEMU_PERSISTENT_ADDR
-unset AFL_QEMU_PERSISTENT_RETADDR_OFFSET
-unset AFL_QEMU_PERSISTENT_GPR
-unset AFL_QEMU_PERSISTENT_RET
-unset AFL_QEMU_PERSISTENT_HOOK
-unset AFL_QEMU_PERSISTENT_CNT
-unset AFL_CUSTOM_MUTATOR_LIBRARY
-unset AFL_PYTHON_MODULE
-unset AFL_PRELOAD
-unset LD_PRELOAD
-
-rm -rf in in2 out
-
-export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1:symbolize=0
-export AFL_LLVM_INSTRUMENT=AFL
-
-# on OpenBSD we need to work with llvm from /usr/local/bin
-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
-} || {
-  AFL_GCC=afl-gcc
-}
-command -v gcc >/dev/null 2>&1 || AFL_GCC=afl-clang
-
-SYS=`uname -m`
-
-GREY="\\033[1;90m"
-BLUE="\\033[1;94m"
-GREEN="\\033[0;32m"
-RED="\\033[0;31m"
-YELLOW="\\033[1;93m"
-RESET="\\033[0m"
-
-MEM_LIMIT=none
-
-export PATH="${PATH}:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
-
-$ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
-
-test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
-
-$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} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
-  AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
-  test -e test-instr.plain && {
-    $ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded"
-    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&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"
-        CODE=1
-      } || {
-        $ECHO "$GREEN[+] ${AFL_GCC} instrumentation present and working correctly"
-      }
-    } || {
-      $ECHO "$RED[!] ${AFL_GCC} instrumentation failed"
-      CODE=1
-    }
-    rm -f test-instr.plain.0 test-instr.plain.1
-    TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
-    test "$TUPLES" -gt 3 -a "$TUPLES" -lt 11 && {
-      $ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine"
-    } || {
-      $ECHO "$RED[!] ${AFL_GCC} instrumentation produces weird numbers: $TUPLES"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] ${AFL_GCC} failed"
-    echo CUT------------------------------------------------------------------CUT
-    uname -a
-    ../${AFL_GCC} -o test-instr.plain ../test-instr.c
-    echo CUT------------------------------------------------------------------CUT
-    CODE=1
-  }
-  test -e test-compcov.harden && {
-    grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
-      $ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working"
-    } || {
-      $ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened"
-      CODE=1
-    }
-    rm -f test-compcov.harden
-  } || {
-    $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
-    CODE=1
-  }
-  # now we want to be sure that afl-fuzz is working
-  # make sure core_pattern is set to core on linux
-  (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
-    $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
-    true
-  }) ||
-  # make sure crash reporter is disabled on Mac OS X
-  (test "$(uname -s)" = "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
-    $ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds"
-    {
-      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
-    } >>errors 2>&1
-    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-      $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}"
-    } || {
-      echo CUT------------------------------------------------------------------CUT
-      cat errors
-      echo CUT------------------------------------------------------------------CUT
-      $ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}"
-      CODE=1
-    }
-    echo 000000000000000000000000 > in/in2
-    echo 111 > in/in3
-    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" ;;
-      *)  $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" ;;
-        *)  $ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
-            CODE=1
-            ;;
-        esac
-    } else {
-      $ECHO "$YELLOW[-] no bash available, cannot test afl-cmin.bash"
-      INCOMPLETE=1
-    }
-    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 is not compiled, cannot test"
-  INCOMPLETE=1
- }
-} || {
- $ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
-}
-
-$ECHO "$BLUE[*] Testing: llvm_mode, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
-test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
-  # on FreeBSD need to set AFL_CC
-  test `uname -s` = 'FreeBSD' && {
-    if type clang >/dev/null; then
-      export AFL_CC=`command -v clang`
-    else
-      export AFL_CC=`$LLVM_CONFIG --bindir`/clang
-    fi
-  }
-  ../afl-clang-fast -o test-instr.plain ../test-instr.c > /dev/null 2>&1
-  AFL_HARDEN=1 ../afl-clang-fast -o test-compcov.harden test-compcov.c > /dev/null 2>&1
-  test -e test-instr.plain && {
-    $ECHO "$GREEN[+] llvm_mode compilation succeeded"
-    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&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[!] llvm_mode instrumentation should be different on different input but is not"
-        CODE=1
-      } || {
-        $ECHO "$GREEN[+] llvm_mode instrumentation present and working correctly"
-        TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
-        test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
-          $ECHO "$GREEN[+] llvm_mode run reported $TUPLES instrumented locations which is fine"
-        } || {
-          $ECHO "$RED[!] llvm_mode instrumentation produces weird numbers: $TUPLES"
-          CODE=1
-        }
-      }
-    } || {
-      $ECHO "$RED[!] llvm_mode instrumentation failed"
-      CODE=1
-    }
-    rm -f test-instr.plain.0 test-instr.plain.1
-  } || {
-    $ECHO "$RED[!] llvm_mode failed"
-    CODE=1
-  }
-  test -e test-compcov.harden && test_compcov_binary_functionality ./test-compcov.harden && {
-    grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
-      $ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working"
-    } || {
-      $ECHO "$RED[!] llvm_mode hardened mode is not hardened"
-      CODE=1
-    }
-    rm -f test-compcov.harden
-  } || {
-    $ECHO "$RED[!] llvm_mode hardened mode compilation failed"
-    CODE=1
-  }
-  # now we want to be sure that afl-fuzz is working
-  (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
-    $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
-    true
-  }) ||
-  # make sure crash reporter is disabled on Mac OS X
-  (test "$(uname -s)" = "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"
-    CODE=1
-    true
-  }) || {
-    mkdir -p in
-    echo 0 > in/in
-    $ECHO "$GREY[*] running afl-fuzz for llvm_mode, this will take approx 10 seconds"
-    {
-      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
-    } >>errors 2>&1
-    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-      $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode"
-    } || {
-      echo CUT------------------------------------------------------------------CUT
-      cat errors
-      echo CUT------------------------------------------------------------------CUT
-      $ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode"
-      CODE=1
-    }
-    test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" || {
-      echo 000000000000000000000000 > in/in2
-      echo 111 > in/in3
-      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" ;;
-        *)  $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 type 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" ;;
-          *)  $ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
-              CODE=1
-              ;;
-          esac
-      } else {
-        $ECHO "$YELLOW[-] no bash available, cannot test afl-cmin.bash"
-        INCOMPLETE=1
-      }
-      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 in2
-    }
-    rm -rf in out errors
-  }
-  rm -f test-instr.plain
-
-  # now for the special llvm_mode things
-  test -e ../libLLVMInsTrim.so && {
-    AFL_LLVM_INSTRUMENT=CFG AFL_LLVM_INSTRIM_LOOPHEAD=1 ../afl-clang-fast -o test-instr.instrim ../test-instr.c > /dev/null 2>test.out
-    test -e test-instr.instrim && {
-      TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.instrim 2>&1 | grep Captur | awk '{print$3}'`
-      test "$TUPLES" -gt 2 -a "$TUPLES" -lt 5 && {
-        $ECHO "$GREEN[+] llvm_mode InsTrim reported $TUPLES instrumented locations which is fine"
-      } || {
-        $ECHO "$RED[!] llvm_mode InsTrim instrumentation produces weird numbers: $TUPLES"
-        CODE=1
-      }
-      rm -f test-instr.instrim test.out
-    } || {
-      $ECHO "$RED[!] llvm_mode InsTrim compilation failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$YELLOW[-] llvm_mode InsTrim not compiled, cannot test"
-    INCOMPLETE=1
-  }
-  AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > test.out 2>&1
-  test -e test-compcov.compcov && test_compcov_binary_functionality ./test-compcov.compcov && {
-    grep --binary-files=text -Eq " [ 123][0-9][0-9] location| [3-9][0-9] location" test.out && {
-      $ECHO "$GREEN[+] llvm_mode laf-intel/compcov feature works correctly"
-    } || {
-      $ECHO "$RED[!] llvm_mode laf-intel/compcov feature failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] llvm_mode laf-intel/compcov feature compilation failed"
-    CODE=1
-  }
-  rm -f test-compcov.compcov test.out
-  AFL_LLVM_INSTRUMENT=AFL AFL_LLVM_LAF_SPLIT_FLOATS=1 ../afl-clang-fast -o test-floatingpoint test-floatingpoint.c >errors 2>&1
-  test -e test-floatingpoint && {
-    mkdir -p in
-    echo ZZZZ > in/in
-    $ECHO "$GREY[*] running afl-fuzz with floating point splitting, this will take max. 30 seconds"
-    {
-      AFL_BENCH_UNTIL_CRASH=1 AFL_NO_UI=1 ../afl-fuzz -s 1 -V30 -m ${MEM_LIMIT} -i in -o out -- ./test-floatingpoint >>errors 2>&1
-    } >>errors 2>&1
-    test -n "$( ls out/crashes/id:* 2>/dev/null )" && {
-      $ECHO "$GREEN[+] llvm_mode laf-intel floatingpoint splitting feature works correctly"
-    } || {
-      cat errors
-      $ECHO "$RED[!] llvm_mode laf-intel floatingpoint splitting feature failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] llvm_mode laf-intel floatingpoint splitting feature compilation failed"
-    CODE=1
-  }
-  rm -f test-floatingpoint test.out in/in
-  echo foobar.c > instrumentlist.txt
-  AFL_DEBUG=1 AFL_LLVM_INSTRUMENT_FILE=instrumentlist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1
-  test -e test-compcov && test_compcov_binary_functionality ./test-compcov && {
-    grep -q "No instrumentation targets found" test.out && {
-      $ECHO "$GREEN[+] llvm_mode instrumentlist feature works correctly"
-    } || {
-      $ECHO "$RED[!] llvm_mode instrumentlist feature failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] llvm_mode instrumentlist feature compilation failed"
-    CODE=1
-  }
-  rm -f test-compcov test.out instrumentlist.txt
-  AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
-  test -e test-cmplog && {
-    $ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
-    {
-      mkdir -p in
-      echo 0000000000000000000000000 > in/in
-      ../afl-fuzz -m none -V10 -i in -o out -c./test-cmplog -- ./test-cmplog >>errors 2>&1
-    } >>errors 2>&1
-    test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {
-      $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
-    } || {
-      echo CUT------------------------------------------------------------------CUT
-      cat errors
-      echo CUT------------------------------------------------------------------CUT
-      $ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode cmplog"
-      CODE=1
-    }
-  } || {
-    $ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
-    INCOMPLETE=1
-  }
-  rm -rf errors test-cmplog in
-  ../afl-clang-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
-  test -e test-persistent && {
-    echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
-      $ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly"
-    } || {
-      $ECHO "$RED[!] llvm_mode persistent mode feature failed to work"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] llvm_mode persistent mode feature compilation failed"
-    CODE=1
-  }
-  rm -f test-persistent
-} || {
-  $ECHO "$YELLOW[-] llvm_mode not compiled, cannot test"
-  INCOMPLETE=1
-}
-
-$ECHO "$BLUE[*] Testing: LTO llvm_mode"
-test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
-  # on FreeBSD need to set AFL_CC
-  test `uname -s` = 'FreeBSD' && {
-    if type clang >/dev/null; then
-      export AFL_CC=`command -v clang`
-    else
-      export AFL_CC=`$LLVM_CONFIG --bindir`/clang
-    fi
-  }
-
-  ../afl-clang-lto -o test-instr.plain ../test-instr.c > /dev/null 2>&1
-  test -e test-instr.plain && {
-    $ECHO "$GREEN[+] llvm_mode LTO compilation succeeded"
-    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&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 -q test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
-        $ECHO "$RED[!] llvm_mode LTO instrumentation should be different on different input but is not"
-        CODE=1
-      } || {
-        $ECHO "$GREEN[+] llvm_mode LTO instrumentation present and working correctly"
-        TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
-        test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
-          $ECHO "$GREEN[+] llvm_mode LTO run reported $TUPLES instrumented locations which is fine"
-        } || {
-          $ECHO "$RED[!] llvm_mode LTO instrumentation produces weird numbers: $TUPLES"
-          CODE=1
-        }
-      }
-    } || {
-      $ECHO "$RED[!] llvm_mode LTO instrumentation failed"
-      CODE=1
-    }
-    rm -f test-instr.plain.0 test-instr.plain.1
-  } || {
-    $ECHO "$RED[!] LTO llvm_mode failed"
-    CODE=1
-  }
-  rm -f test-instr.plain
-
-  echo foobar.c > instrumentlist.txt
-  AFL_DEBUG=1 AFL_LLVM_INSTRUMENT_FILE=instrumentlist.txt ../afl-clang-lto -o test-compcov test-compcov.c > test.out 2>&1
-  test -e test-compcov && {
-    grep -q "No instrumentation targets found" test.out && {
-      $ECHO "$GREEN[+] llvm_mode LTO instrumentlist feature works correctly"
-    } || {
-      $ECHO "$RED[!] llvm_mode LTO instrumentlist feature failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] llvm_mode LTO instrumentlist feature compilation failed"
-    CODE=1
-  }
-  rm -f test-compcov test.out instrumentlist.txt
-  ../afl-clang-lto -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
-  test -e test-persistent && {
-    echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && {
-      $ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly"
-    } || {
-      $ECHO "$RED[!] llvm_mode LTO persistent mode feature failed to work"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] llvm_mode LTO persistent mode feature compilation failed"
-    CODE=1
-  }
-  rm -f test-persistent
-} || {
-  $ECHO "$YELLOW[-] LTO llvm_mode not compiled, cannot test"
-  INCOMPLETE=1
-}
-
-$ECHO "$BLUE[*] Testing: gcc_plugin"
-test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
-  SAVE_AFL_CC=${AFL_CC}
-  export AFL_CC=`command -v gcc`
-  ../afl-gcc-fast -o test-instr.plain.gccpi ../test-instr.c > /dev/null 2>&1
-  AFL_HARDEN=1 ../afl-gcc-fast -o test-compcov.harden.gccpi test-compcov.c > /dev/null 2>&1
-  test -e test-instr.plain.gccpi && {
-    $ECHO "$GREEN[+] gcc_plugin compilation succeeded"
-    echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain.gccpi > /dev/null 2>&1
-    ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain.gccpi < /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[!] gcc_plugin instrumentation should be different on different input but is not"
-        CODE=1
-      } || {
-        $ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly"
-        TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'`
-        test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
-          $ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine"
-        } || {
-          $ECHO "$RED[!] gcc_plugin instrumentation produces a weird numbers: $TUPLES"
-          $ECHO "$YELLOW[-] this is a known issue in gcc, not afl++. It is not flagged as an error because travis builds would all fail otherwise :-("
-          #CODE=1
-        }
-      }
-    } || {
-      $ECHO "$RED[!] gcc_plugin instrumentation failed"
-      CODE=1
-    }
-    rm -f test-instr.plain.0 test-instr.plain.1
-  } || {
-    $ECHO "$RED[!] gcc_plugin failed"
-    CODE=1
-  }
-
-  test -e test-compcov.harden.gccpi && test_compcov_binary_functionality ./test-compcov.harden.gccpi && {
-    grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden.gccpi > /dev/null 2>&1 && {
-      $ECHO "$GREEN[+] gcc_plugin hardened mode succeeded and is working"
-    } || {
-      $ECHO "$RED[!] gcc_plugin hardened mode is not hardened"
-      CODE=1
-    }
-    rm -f test-compcov.harden.gccpi
-  } || {
-    $ECHO "$RED[!] gcc_plugin hardened mode compilation failed"
-    CODE=1
-  }
-  # now we want to be sure that afl-fuzz is working
-  (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
-    $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
-    true
-  }) ||
-  # make sure crash reporter is disabled on Mac OS X
-  (test "$(uname -s)" = "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"
-    CODE=1
-    true
-  }) || {
-    mkdir -p in
-    echo 0 > in/in
-    $ECHO "$GREY[*] running afl-fuzz for gcc_plugin, this will take approx 10 seconds"
-    {
-      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain.gccpi >>errors 2>&1
-    } >>errors 2>&1
-    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-      $ECHO "$GREEN[+] afl-fuzz is working correctly with gcc_plugin"
-    } || {
-      echo CUT------------------------------------------------------------------CUT
-      cat errors
-      echo CUT------------------------------------------------------------------CUT
-      $ECHO "$RED[!] afl-fuzz is not working correctly with gcc_plugin"
-      CODE=1
-    }
-    rm -rf in out errors
-  }
-  rm -f test-instr.plain.gccpi
-
-  # 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
-  test -e test-compcov && test_compcov_binary_functionality ./test-compcov && {
-    echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && {
-      $ECHO "$GREEN[+] gcc_plugin instrumentlist feature works correctly"
-    } || {
-      $ECHO "$RED[!] gcc_plugin instrumentlist feature failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] gcc_plugin instrumentlist feature compilation failed"
-    CODE=1
-  }
-  rm -f test-compcov test.out instrumentlist.txt
-  ../afl-gcc-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
-  test -e test-persistent && {
-    echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
-      $ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly"
-    } || {
-      $ECHO "$RED[!] gcc_plugin persistent mode feature failed to work"
-      CODE=1
-    }
-  } || {
-    $ECHO "$RED[!] gcc_plugin persistent mode feature compilation failed"
-    CODE=1
-  }
-  rm -f test-persistent
-  export AFL_CC=${SAVE_AFL_CC}
-} || {
-  $ECHO "$YELLOW[-] gcc_plugin not compiled, cannot test"
-  INCOMPLETE=1
-}
-
-test -z "$AFL_CC" && unset AFL_CC
-
-$ECHO "$BLUE[*] Testing: shared library extensions"
-cc $CFLAGS -o test-compcov test-compcov.c > /dev/null 2>&1
-test -e ../libtokencap.so && {
-  AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1
-  grep -q BUGMENOT token.out > /dev/null 2>&1 && {
-    $ECHO "$GREEN[+] libtokencap did successfully capture tokens"
-  } || {
-    $ECHO "$RED[!] libtokencap did not capture tokens"
-    CODE=1
-  }
-  rm -f token.out
-} || {
-  $ECHO "$YELLOW[-] libtokencap is not compiled, cannot test"
-  INCOMPLETE=1
-}
-test -e ../libdislocator.so && {
-  {
-    ulimit -c 1
-    # DYLD_INSERT_LIBRARIES and DYLD_FORCE_FLAT_NAMESPACE is used on Darwin/MacOSX
-    LD_PRELOAD=../libdislocator.so DYLD_INSERT_LIBRARIES=../libdislocator.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov BUFFEROVERFLOW > test.out 2>/dev/null
-  } > /dev/null 2>&1
-  grep -q BUFFEROVERFLOW test.out > /dev/null 2>&1 && {
-    $ECHO "$RED[!] libdislocator did not detect the memory corruption"
-    CODE=1
-  } || {
-    $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
-  }
-  rm -f test.out core test-compcov.core core.test-compcov
-} || {
-  $ECHO "$YELLOW[-] libdislocator is not compiled, cannot test"
-  INCOMPLETE=1
-}
-rm -f test-compcov
-#test -e ../libradamsa.so && {
-#  # on FreeBSD need to set AFL_CC
-#  test `uname -s` = 'FreeBSD' && {
-#    if type clang >/dev/null; then
-#      export AFL_CC=`command -v clang`
-#    else
-#      export AFL_CC=`$LLVM_CONFIG --bindir`/clang
-#    fi
-#  }
-#  test -e test-instr.plain || ../afl-clang-fast -o test-instr.plain ../test-instr.c > /dev/null 2>&1
-#  test -e test-instr.plain || ../afl-gcc-fast -o test-instr.plain ../test-instr.c > /dev/null 2>&1
-#  test -e test-instr.plain || ../${AFL_GCC} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
-#  test -e test-instr.plain && {
-#    mkdir -p in
-#    printf 1 > in/in
-#    $ECHO "$GREY[*] running afl-fuzz with radamsa, this will take approx 10 seconds"
-#    {
-#      ../afl-fuzz -RR -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain
-#    } >>errors 2>&1
-#    test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
-#      $ECHO "$GREEN[+] libradamsa performs good - and very slow - mutations"
-#    } || {
-#      echo CUT------------------------------------------------------------------CUT
-#      cat errors
-#      echo CUT------------------------------------------------------------------CUT
-#      $ECHO "$RED[!] libradamsa failed"
-#      CODE=1
-#    }
-#    rm -rf in out errors test-instr.plain
-#  } || {
-#    $ECHO "$YELLOW[-] compilation of test target failed, cannot test libradamsa"
-#    INCOMPLETE=1
-#  }
-#} || {
-#  $ECHO "$YELLOW[-] libradamsa is not compiled, cannot test"
-#  INCOMPLETE=1
-#}
-
-test -z "$AFL_CC" && {
-  if type gcc >/dev/null; then
-    export AFL_CC=gcc
-  else
-    if type clang >/dev/null; then
-      export AFL_CC=clang
-    fi
-  fi
-}
-
-$ECHO "$BLUE[*] Testing: qemu_mode"
-test -e ../afl-qemu-trace && {
-  cc -pie -fPIE -o test-instr ../test-instr.c
-  cc -o test-compcov test-compcov.c
-  test -e test-instr -a -e test-compcov && {
-    {
-      mkdir -p in
-      echo 00000 > in/in
-      $ECHO "$GREY[*] running afl-fuzz for qemu_mode, this will take approx 10 seconds"
-      {
-        ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1
-      } >>errors 2>&1
-      test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-        $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode"
-        RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
-      } || {
-        echo CUT------------------------------------------------------------------CUT
-        cat errors
-        echo CUT------------------------------------------------------------------CUT
-        $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode"
-        CODE=1
-      }
-      rm -f errors
-
-      $ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds"
-      {
-        {
-          if file test-instr | grep -q "32-bit"; then
-            # for 32-bit reduce 8 nibbles to the lower 7 nibbles
-	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
-          else
-            # for 64-bit reduce 16 nibbles to the lower 9 nibbles
-	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
-          fi
-          export AFL_ENTRYPOINT=`expr 0x4${ADDR_LOWER_PART}`
-          $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr)
-          ../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr
-          unset AFL_ENTRYPOINT
-        } >>errors 2>&1
-      } >>errors 2>&1
-      test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
-        $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode AFL_ENTRYPOINT"
-        RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
-      } || {
-        echo CUT------------------------------------------------------------------CUT
-        cat errors
-        echo CUT------------------------------------------------------------------CUT
-        $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode AFL_ENTRYPOINT"
-        CODE=1
-      }
-      rm -f errors
-
-      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
-        test -e ../libcompcov.so && {
-          $ECHO "$GREY[*] running afl-fuzz for qemu_mode compcov, this will take approx 10 seconds"
-          {
-            export AFL_PRELOAD=../libcompcov.so
-            export AFL_COMPCOV_LEVEL=2
-            ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1
-            unset AFL_PRELOAD
-            unset AFL_COMPCOV_LEVEL
-          } >>errors 2>&1
-          test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
-            $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode compcov"
-          } || {
-            echo CUT------------------------------------------------------------------CUT
-            cat errors
-            echo CUT------------------------------------------------------------------CUT
-            $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode compcov"
-            CODE=1
-          }
-        } || {
-          $ECHO "$YELLOW[-] we cannot test qemu_mode compcov because it is not present"
-          INCOMPLETE=1
-        }
-        rm -f errors
-      } || {
-       $ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode compcov"
-      }
-      
-      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
-        $ECHO "$GREY[*] running afl-fuzz for qemu_mode cmplog, this will take approx 10 seconds"
-        {
-          ../afl-fuzz -m none -V10 -Q -c 0 -i in -o out -- ./test-compcov >>errors 2>&1
-        } >>errors 2>&1
-        test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
-          $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode cmplog"
-        } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-          $ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode cmplog"
-          CODE=1
-        }
-        rm -f errors
-      } || {
-       $ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode cmplog"
-      }
-
-      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
-        $ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
-        {
-          if file test-instr | grep -q "32-bit"; then
-            # for 32-bit reduce 8 nibbles to the lower 7 nibbles
-	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
-          else
-            # for 64-bit reduce 16 nibbles to the lower 9 nibbles
-	    ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
-          fi
-          export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4${ADDR_LOWER_PART}`
-          export AFL_QEMU_PERSISTENT_GPR=1
-          $ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')"
-          env|grep AFL_|sort
-          file test-instr
-          ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr
-          unset AFL_QEMU_PERSISTENT_ADDR
-        } >>errors 2>&1
-        test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-          $ECHO "$GREEN[+] afl-fuzz is working correctly with persistent qemu_mode"
-          RUNTIMEP=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
-          test -n "$RUNTIME" -a -n "$RUNTIMEP" && {
-            DIFF=`expr $RUNTIMEP / $RUNTIME`
-            test "$DIFF" -gt 1 && { # must be at least twice as fast
-              $ECHO "$GREEN[+] persistent qemu_mode was noticeable faster than standard qemu_mode"
-            } || {
-              $ECHO "$YELLOW[-] persistent qemu_mode was not noticeable faster than standard qemu_mode"
-            }
-          } || {
-            $ECHO "$YELLOW[-] we got no data on executions performed? weird!"
-          }
-        } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-          $ECHO "$RED[!] afl-fuzz is not working correctly with persistent qemu_mode"
-          CODE=1
-        }
-        rm -rf in out errors
-      } || {
-       $ECHO "$YELLOW[-] not an intel or arm platform, cannot test persistent qemu_mode"
-      }
-
-      test -e ../qemu_mode/unsigaction/unsigaction32.so && {
-        ${AFL_CC} -o test-unsigaction32 -m32 test-unsigaction.c >> errors 2>&1 && {
-	  ./test-unsigaction32
-          RETVAL_NORMAL32=$?
-	  LD_PRELOAD=../qemu_mode/unsigaction/unsigaction32.so ./test-unsigaction32
-          RETVAL_LIBUNSIGACTION32=$?
-	  test $RETVAL_NORMAL32 = "2" -a $RETVAL_LIBUNSIGACTION32 = "0" && {
-            $ECHO "$GREEN[+] qemu_mode unsigaction library (32 bit) ignores signals"
-	  } || {
-	    test $RETVAL_NORMAL32 != "2" && {
-	      $ECHO "$RED[!] cannot trigger signal in test program (32 bit)"
-	    }
-	    test $RETVAL_LIBUNSIGACTION32 != "0" && {
-	      $ECHO "$RED[!] signal in test program (32 bit) is not ignored with unsigaction"
-	    }
-            CODE=1
-          }
-        } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-	  $ECHO "$RED[!] cannot compile test program (32 bit) for unsigaction library"
-          CODE=1
-        }
-      } || {
-        $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (32 bit) because it is not present"
-        INCOMPLETE=1
-      }
-      test -e ../qemu_mode/unsigaction/unsigaction64.so && {
-        ${AFL_CC} -o test-unsigaction64 -m64 test-unsigaction.c >> errors 2>&1 && {
-	  ./test-unsigaction64
-          RETVAL_NORMAL64=$?
-	  LD_PRELOAD=../qemu_mode/unsigaction/unsigaction64.so ./test-unsigaction64
-          RETVAL_LIBUNSIGACTION64=$?
-	  test $RETVAL_NORMAL64 = "2" -a $RETVAL_LIBUNSIGACTION64 = "0" && {
-            $ECHO "$GREEN[+] qemu_mode unsigaction library (64 bit) ignores signals"
-	  } || {
-	    test $RETVAL_NORMAL64 != "2" && {
-	      $ECHO "$RED[!] cannot trigger signal in test program (64 bit)"
-	    }
-	    test $RETVAL_LIBUNSIGACTION64 != "0" && {
-	      $ECHO "$RED[!] signal in test program (64 bit) is not ignored with unsigaction"
-	    }
-            CODE=1
-          }
-          unset LD_PRELOAD
-        } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-	  $ECHO "$RED[!] cannot compile test program (64 bit) for unsigaction library"
-          CODE=1
-        }
-      } || {
-        $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (64 bit) because it is not present"
-        INCOMPLETE=1
-      }
-      rm -rf errors test-unsigaction32 test-unsigaction64
-    }
-  } || {
-    $ECHO "$RED[!] gcc compilation of test targets failed - what is going on??"
-    CODE=1
-  }
-
-  rm -f test-instr test-compcov
-} || {
-  $ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
-  INCOMPLETE=1
-}
-
-$ECHO "$BLUE[*] Testing: unicorn_mode"
-test -d ../unicorn_mode/unicornafl && {
-  test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
-    {
-      # We want to see python errors etc. in logs, in case something doesn't work
-      export AFL_DEBUG_CHILD_OUTPUT=1
-
-      # some python version should be available now
-      PYTHONS="`command -v python3` `command -v python` `command -v python2`"
-      EASY_INSTALL_FOUND=0
-      for PYTHON in $PYTHONS ; do
-
-        if $PYTHON -c "help('easy_install');" </dev/null | grep -q module ; then
-
-            EASY_INSTALL_FOUND=1
-            PY=$PYTHON
-            break
-
-        fi
-
-      done
-      if [ "0" = $EASY_INSTALL_FOUND ]; then
-
-        echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools'."
-        PREREQ_NOTFOUND=1
-
-      fi
-
-
-      cd ../unicorn_mode/samples/persistent
-      make >>errors 2>&1
-      $ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds"
-      AFL_DEBUG_CHILD_OUTPUT=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
-      test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-        $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)"
-      } || {
-        echo CUT------------------------------------------------------------------CUT
-        cat errors
-        echo CUT------------------------------------------------------------------CUT
-        $ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode (persistent)"
-        CODE=1
-      }
-
-      rm -rf out errors >/dev/null
-      make clean >/dev/null
-      cd ../../../test
-
-      # travis workaround
-      test "$PY" = "/opt/pyenv/shims/python" -a -x /usr/bin/python && PY=/usr/bin/python
-      mkdir -p in
-      echo 0 > in/in
-      $ECHO "$GREY[*] Using python binary $PY"
-      if ! $PY -c 'import unicornafl' 2>/dev/null ; then
-        $ECHO "$YELLOW[-] we cannot test unicorn_mode for python because it is not present"
-        INCOMPLETE=1
-      else
-      {
-        $ECHO "$GREY[*] running afl-fuzz for unicorn_mode in python, this will take approx 25 seconds"
-        {
-          ../afl-fuzz -m ${MEM_LIMIT} -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1
-        } >>errors 2>&1
-        test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
-          $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode"
-        } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-          $ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode"
-          CODE=1
-        }
-        rm -f errors
-
-        printf '\x01\x01' > in/in
-        # This seed is close to the first byte of the comparison.
-        # If CompCov works, a new tuple will appear in the map => new input in queue
-        $ECHO "$GREY[*] running afl-fuzz for unicorn_mode compcov, this will take approx 35 seconds"
-        {
-          export AFL_COMPCOV_LEVEL=2
-          ../afl-fuzz -m ${MEM_LIMIT} -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1
-          unset AFL_COMPCOV_LEVEL
-        } >>errors 2>&1
-        test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
-          $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode compcov"
-        } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-          $ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode compcov"
-          CODE=1
-        }
-        rm -rf in out errors
-      }
-      fi
-
-      unset AFL_DEBUG_CHILD_OUTPUT
-
-    }
-  } || {
-    $ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??"
-    CODE=1
-  }
-
-} || {
-  $ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
-  INCOMPLETE=1
-}
-
-$ECHO "$BLUE[*] Testing: custom mutator"
-test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
-  # normalize path
-  CUSTOM_MUTATOR_PATH=$(cd $(pwd)/../examples/custom_mutators;pwd)
-  test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
-    unset AFL_CC
-    # Compile the vulnerable program for single mutator
-    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
-      }
-    }
-    # 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
-      }
-    }
-    # Compile the custom mutator
-    cc -D_FIXED_CHAR=0x41 -g -fPIC -shared -I../include ../examples/custom_mutators/simple_example.c -o libexamplemutator.so > /dev/null 2>&1
-    cc -D_FIXED_CHAR=0x42 -g -fPIC -shared -I../include ../examples/custom_mutators/simple_example.c -o libexamplemutator2.so > /dev/null 2>&1
-    test -e test-custom-mutator -a -e ./libexamplemutator.so && {
-      # Create input directory
-      mkdir -p in
-      echo "00000" > in/in
-
-      # Run afl-fuzz w/ the C mutator
-      $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 5 seconds"
-      {
-        AFL_CUSTOM_MUTATOR_LIBRARY=./libexamplemutator.so AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V1 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
-      } >>errors 2>&1
-
-      # Check results
-      test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
-        $ECHO "$GREEN[+] afl-fuzz is working correctly with the C mutator"
-      } || {
-        echo CUT------------------------------------------------------------------CUT
-        cat errors
-        echo CUT------------------------------------------------------------------CUT
-        $ECHO "$RED[!] afl-fuzz is not working correctly with the C mutator"
-        CODE=1
-      }
-
-      # Clean
-      rm -rf out errors
-
-      # Run afl-fuzz w/ multiple C mutators
-      $ECHO "$GREY[*] running afl-fuzz with multiple custom C mutators, this will take approx 5 seconds"
-      {
-        AFL_CUSTOM_MUTATOR_LIBRARY="./libexamplemutator.so;./libexamplemutator2.so" AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V1 -m ${MEM_LIMIT} -i in -o out -- ./test-multiple-mutators >>errors 2>&1
-      } >>errors 2>&1
-
-      test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
-        $ECHO "$GREEN[+] afl-fuzz is working correctly with multiple C mutators"
-      } || {
-        echo CUT------------------------------------------------------------------CUT
-        cat errors
-        echo CUT------------------------------------------------------------------CUT
-        $ECHO "$RED[!] afl-fuzz is not working correctly with multiple C mutators"
-        CODE=1
-      }
-
-      # Clean
-      rm -rf out errors 
-
-      # Run afl-fuzz w/ the Python mutator
-      $ECHO "$GREY[*] running afl-fuzz for the Python mutator, this will take approx 5 seconds"
-      {
-        export PYTHONPATH=${CUSTOM_MUTATOR_PATH}
-        export AFL_PYTHON_MODULE=example
-        AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V5 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
-        unset PYTHONPATH
-        unset AFL_PYTHON_MODULE
-      } >>errors 2>&1
-
-      # Check results
-      test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
-        $ECHO "$GREEN[+] afl-fuzz is working correctly with the Python mutator"
-      } || {
-        echo CUT------------------------------------------------------------------CUT
-        cat errors
-        echo CUT------------------------------------------------------------------CUT
-        $ECHO "$RED[!] afl-fuzz is not working correctly with the Python mutator"
-        CODE=1
-      }
-
-      # Clean
-      rm -rf in out errors
-      rm -rf ${CUSTOM_MUTATOR_PATH}/__pycache__/
-      rm -f test-multiple-mutators test-custom-mutator libexamplemutator.so libexamplemutator2.so
-    } || {
-      ls .
-      ls ${CUSTOM_MUTATOR_PATH}
-      $ECHO "$RED[!] cannot compile the test program or the custom mutator"
-      CODE=1
-    }
-
-    #test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; }
-
-    make -C ../examples/custom_mutators clean > /dev/null 2>&1
-    rm -f test-custom-mutator
-    rm -f test-custom-mutators
-  } || {
-    $ECHO "$YELLOW[-] no custom mutators in $CUSTOM_MUTATOR_PATH, cannot test"
-    INCOMPLETE=1
-  }
-  unset CUSTOM_MUTATOR_PATH
-} || {
-  $ECHO "$YELLOW[-] no python support in afl-fuzz, cannot test"
-  INCOMPLETE=1
-}
-
-$ECHO "$BLUE[*] Execution cmocka Unit-Tests $GREY"
-unset AFL_CC
-make -C .. unit || CODE=1 INCOMPLETE=1 :
-
-$ECHO "$GREY[*] all test cases completed.$RESET"
-test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed"
-test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed"
-test "$CODE" = "0" && $ECHO "$GREEN[+] all tests were successful :-)$RESET"
-test "$CODE" = "0" || $ECHO "$RED[!] failure in tests :-($RESET"
-exit $CODE
diff --git a/test/travis/bionic/Dockerfile b/test/travis/bionic/Dockerfile
index d1b53e70..00ab96f9 100644
--- a/test/travis/bionic/Dockerfile
+++ b/test/travis/bionic/Dockerfile
@@ -31,6 +31,7 @@ RUN apt-get update && apt-get -y install \
 
 ENV AFL_NO_UI=1
 ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
+ENV LLVM_CONFIG=llvm-config-6.0
 
 RUN cd / && \
     git clone https://github.com/AFLplusplus/AFLplusplus && \
diff --git a/test/unittests/unit_hash.c b/test/unittests/unit_hash.c
index 041d107a..22245ed6 100644
--- a/test/unittests/unit_hash.c
+++ b/test/unittests/unit_hash.c
@@ -30,6 +30,7 @@ extern void exit(int status);
 extern void __real_exit(int status);
 void __wrap_exit(int status);
 void __wrap_exit(int status) {
+    (void)status;
     assert(0);
 }
 
@@ -39,11 +40,13 @@ extern int printf(const char *format, ...);
 extern int __real_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...) {
+    (void)format;
     return 1;
 }
 
 /* Rand with 0 seed would broke in the past */
 static void test_hash(void **state) {
+    (void)state;
 
     char bitmap[64] = {0};
     u64 hash0 = hash64(bitmap, sizeof(bitmap), 0xa5b35705);
@@ -62,6 +65,8 @@ static void test_hash(void **state) {
 }
 
 int main(int argc, char **argv) {
+    (void)argc;
+    (void)argv;
 
     const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_hash)
diff --git a/test/unittests/unit_list.c b/test/unittests/unit_list.c
index 4c2063b6..43665f1a 100644
--- a/test/unittests/unit_list.c
+++ b/test/unittests/unit_list.c
@@ -27,23 +27,26 @@ extern void mock_assert(const int result, const char* const expression,
     (compile with `--wrap=exit`) */
 extern void exit(int status);
 extern void __real_exit(int status);
-void __wrap_exit(int status);
+//void __wrap_exit(int status);
 void __wrap_exit(int status) {
+    (void)status;
     assert(0);
 }
 
 /* ignore all printfs */
 #undef printf
 extern int printf(const char *format, ...);
-extern int __real_printf(const char *format, ...);
+//extern int __real_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...) {
+    (void)format;
     return 1;
 }
 
 static list_t testlist = {.element_prealloc_count = 0};
 
 static void test_contains(void **state) {
+    (void)state;
 
     u32 one = 1;
     u32 two = 2;
@@ -56,6 +59,7 @@ static void test_contains(void **state) {
 }
 
 static void test_foreach(void **state) {
+    (void)state;
 
     u32 one = 1;
     u32 two = 2;
@@ -75,6 +79,7 @@ static void test_foreach(void **state) {
 }
 
 static void test_long_list(void **state) {
+    (void)state;
 
     u32 result1 = 0;
     u32 result2 = 0;
@@ -118,6 +123,8 @@ static void test_long_list(void **state) {
 }
 
 int main(int argc, char **argv) {
+    (void)argc;
+    (void)argv;
 
 	const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_contains),
diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c
index 429d38ed..889ced8a 100644
--- a/test/unittests/unit_maybe_alloc.c
+++ b/test/unittests/unit_maybe_alloc.c
@@ -28,6 +28,7 @@ void __wrap_exit(int status);
 extern void exit(int status);
 extern void __real_exit(int status);
 void __wrap_exit(int status) {
+    (void) status;
     assert(0);
 }
 
@@ -35,8 +36,9 @@ int __wrap_printf(const char *format, ...);
 /* ignore all printfs */
 #undef printf
 extern int printf(const char *format, ...);
-extern int __real_printf(const char *format, ...);
+//extern int __real_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...) {
+    (void)format;
     return 1;
 }
 
@@ -51,6 +53,7 @@ static int setup(void **state) {
 */
 
 static void test_null_allocs(void **state) {
+    (void)state;
 
     void *buf = NULL;
     size_t size = 0;
@@ -62,6 +65,7 @@ static void test_null_allocs(void **state) {
 }
 
 static void test_nonpow2_size(void **state) {
+    (void)state;
 
     char *buf = ck_alloc(150);
     size_t size = 150;
@@ -75,6 +79,7 @@ static void test_nonpow2_size(void **state) {
 }
 
 static void test_zero_size(void **state) {
+    (void)state;
 
     char *buf = NULL;
     size_t size = 0;
@@ -95,6 +100,7 @@ static void test_zero_size(void **state) {
 }
 
 static void test_unchanged_size(void **state) {
+    (void)state;
 
     void *buf = ck_alloc(100);
     size_t size = 100;
@@ -107,6 +113,7 @@ static void test_unchanged_size(void **state) {
 }
 
 static void test_grow_multiple(void **state) {
+    (void)state;
 
     char *buf = NULL;
     size_t size = 0;
@@ -146,6 +153,8 @@ static int teardown(void **state) {
 */
 
 int main(int argc, char **argv) {
+    (void)argc;
+    (void)argv;
 
 	const struct CMUnitTest tests[] = {
 		cmocka_unit_test(test_null_allocs),
diff --git a/test/unittests/unit_preallocable.c b/test/unittests/unit_preallocable.c
index b0963a15..ea16da85 100644
--- a/test/unittests/unit_preallocable.c
+++ b/test/unittests/unit_preallocable.c
@@ -29,6 +29,7 @@ extern void exit(int status);
 extern void __real_exit(int status);
 void __wrap_exit(int status);
 void __wrap_exit(int status) {
+    (void)status;
     assert(0);
 }
 
@@ -36,8 +37,9 @@ void __wrap_exit(int status) {
 #undef printf
 extern int printf(const char *format, ...);
 extern int __real_printf(const char *format, ...);
-int __wrap_printf(const char *format, ...);
+//int __wrap_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...) {
+    (void)format;
     return 1;
 }
 
@@ -51,9 +53,10 @@ typedef struct prealloc_me
 
 #define PREALLOCED_BUF_SIZE (64)
 prealloc_me_t prealloc_me_buf[PREALLOCED_BUF_SIZE];
-size_t prealloc_me_size = 0;
+s32 prealloc_me_size = 0;
 
 static void test_alloc_free(void **state) {
+    (void)state;
 
     prealloc_me_t *prealloced = NULL;
     PRE_ALLOC(prealloced, prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
@@ -63,6 +66,7 @@ static void test_alloc_free(void **state) {
 }
 
 static void test_prealloc_overflow(void **state) {
+    (void)state;
 
     u32 i = 0;
     prealloc_me_t *prealloced[PREALLOCED_BUF_SIZE + 10];
@@ -102,6 +106,8 @@ static void test_prealloc_overflow(void **state) {
 }
 
 int main(int argc, char **argv) {
+    (void)argc;
+    (void)argv;
 
 	const struct CMUnitTest tests[] = {
 		cmocka_unit_test(test_alloc_free),
diff --git a/test/unittests/unit_rand.c b/test/unittests/unit_rand.c
index 0a90d8d1..1ad02a80 100644
--- a/test/unittests/unit_rand.c
+++ b/test/unittests/unit_rand.c
@@ -29,8 +29,9 @@ extern void mock_assert(const int result, const char* const expression,
     (compile with `--wrap=exit`) */
 extern void exit(int status);
 extern void __real_exit(int status);
-void __wrap_exit(int status);
+//void __wrap_exit(int status);
 void __wrap_exit(int status) {
+    (void)status;
     assert(0);
 }
 
@@ -40,11 +41,13 @@ extern int printf(const char *format, ...);
 extern int __real_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...);
 int __wrap_printf(const char *format, ...) {
+    (void)format;
     return 1;
 }
 
 /* Rand with 0 seed would broke in the past */
 static void test_rand_0(void **state) {
+    (void)state;
 
     afl_state_t afl = {0};
     rand_set_seed(&afl, 0);
@@ -58,6 +61,7 @@ static void test_rand_0(void **state) {
 }
 
 static void test_rand_below(void **state) {
+    (void)state;
 
     afl_state_t afl = {0};
     rand_set_seed(&afl, 1337);
@@ -70,6 +74,8 @@ static void test_rand_below(void **state) {
 }
 
 int main(int argc, char **argv) {
+    (void)argc;
+    (void)argv;
 
     const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_rand_0),