about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndrea Fioraldi <andreafioraldi@gmail.com>2020-12-08 22:43:05 +0100
committerAndrea Fioraldi <andreafioraldi@gmail.com>2020-12-08 22:43:05 +0100
commitad29eef2712f8d0b69c1acd79c6a5dfb4e2cc7f8 (patch)
treef74be06e8d1834ada6abe3daf40744e134cb9e3c
parentc70b7ffd80ee95cdf3bf1276bfbd4a590e74d3f1 (diff)
parent6fb74342b8a3e7aa62e9e0cfe79bd84d9076a275 (diff)
downloadafl++-ad29eef2712f8d0b69c1acd79c6a5dfb4e2cc7f8.tar.gz
Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev
-rwxr-xr-x.custom-format.py10
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules5
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--GNUmakefile50
-rw-r--r--GNUmakefile.gcc_plugin2
-rw-r--r--GNUmakefile.llvm4
-rw-r--r--README.md22
-rwxr-xr-xafl-cmin9
-rwxr-xr-xafl-cmin.bash2
-rw-r--r--custom_mutators/README.md10
-rw-r--r--custom_mutators/grammar_mutator/GRAMMAR_VERSION1
-rwxr-xr-xcustom_mutators/grammar_mutator/build_grammar_mutator.sh139
m---------custom_mutators/grammar_mutator/grammar_mutator0
-rwxr-xr-xcustom_mutators/grammar_mutator/update_grammar_ref.sh50
-rw-r--r--custom_mutators/symcc/symcc.c123
-rw-r--r--custom_mutators/symcc/test_examples/file_test.c36
-rw-r--r--custom_mutators/symcc/test_examples/stdin_test.c28
-rw-r--r--dictionaries/README.md2
-rw-r--r--docs/Changelog.md31
-rw-r--r--docs/FAQ.md2
l---------docs/README.md1
-rw-r--r--docs/binaryonly_fuzzing.md6
-rw-r--r--docs/custom_mutators.md41
-rw-r--r--docs/env_variables.md33
-rw-r--r--docs/life_pro_tips.md4
-rw-r--r--docs/notes_for_asan.md4
-rw-r--r--docs/parallel_fuzzing.md2
-rwxr-xr-xexamples/afl_untracer/libtestinstr.sobin17152 -> 0 bytes
-rw-r--r--include/afl-fuzz.h60
-rw-r--r--include/alloc-inl.h22
-rw-r--r--include/common.h4
-rw-r--r--include/debug.h10
-rw-r--r--include/envs.h6
-rw-r--r--include/forkserver.h21
-rw-r--r--instrumentation/LLVMInsTrim.so.cc4
-rw-r--r--instrumentation/README.gcc_plugin.md2
-rw-r--r--instrumentation/README.lto.md33
-rw-r--r--instrumentation/README.persistent_mode.md45
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc18
-rw-r--r--instrumentation/afl-compiler-rt.o.c57
-rw-r--r--instrumentation/afl-gcc-pass.so.cc36
-rw-r--r--instrumentation/afl-llvm-common.cc34
-rw-r--r--instrumentation/afl-llvm-lto-instrumentlist.so.cc9
-rw-r--r--instrumentation/split-compares-pass.so.cc15
-rw-r--r--libdislocator/README.md2
-rw-r--r--libtokencap/README.md2
-rwxr-xr-xqbdi_mode/template.cpp2
-rw-r--r--qemu_mode/README.md4
-rw-r--r--qemu_mode/README.persistent.md2
-rwxr-xr-xqemu_mode/build_qemu_support.sh2
m---------qemu_mode/qemuafl0
-rw-r--r--src/afl-analyze.c4
-rw-r--r--src/afl-as.c2
-rw-r--r--src/afl-cc.c381
-rw-r--r--src/afl-common.c4
-rw-r--r--src/afl-forkserver.c175
-rw-r--r--src/afl-fuzz-bitmap.c85
-rw-r--r--src/afl-fuzz-init.c38
-rw-r--r--src/afl-fuzz-mutators.c80
-rw-r--r--src/afl-fuzz-one.c18
-rw-r--r--src/afl-fuzz-python.c83
-rw-r--r--src/afl-fuzz-queue.c83
-rw-r--r--src/afl-fuzz-run.c9
-rw-r--r--src/afl-fuzz-state.c13
-rw-r--r--src/afl-fuzz.c92
-rw-r--r--src/afl-ld-lto.c18
-rw-r--r--src/afl-showmap.c29
-rw-r--r--src/afl-tmin.c39
-rwxr-xr-xtest/test-custom-mutators.sh8
-rwxr-xr-xtest/test-gcc-plugin.sh2
-rwxr-xr-xtest/test-llvm-lto.sh2
-rwxr-xr-xtest/test-llvm.sh2
-rwxr-xr-xtest/test-pre.sh2
-rwxr-xr-xtest/test-unicorn-mode.sh6
-rw-r--r--unicorn_mode/UNICORNAFL_VERSION2
-rwxr-xr-xunicorn_mode/build_unicorn_support.sh2
-rw-r--r--unicorn_mode/helper_scripts/unicorn_dumper_gdb.py64
-rw-r--r--unicorn_mode/helper_scripts/unicorn_dumper_ida.py2
-rw-r--r--unicorn_mode/helper_scripts/unicorn_loader.py271
m---------unicorn_mode/unicornafl0
-rw-r--r--utils/README.md (renamed from examples/README.md)4
-rw-r--r--utils/afl_frida/GNUmakefile (renamed from examples/afl_frida/GNUmakefile)0
-rw-r--r--utils/afl_frida/Makefile (renamed from examples/afl_frida/Makefile)0
-rw-r--r--utils/afl_frida/README.md (renamed from examples/afl_frida/README.md)0
-rw-r--r--utils/afl_frida/afl-frida.c (renamed from examples/afl_frida/afl-frida.c)0
-rw-r--r--utils/afl_frida/afl-frida.h (renamed from examples/afl_frida/afl-frida.h)0
-rw-r--r--utils/afl_frida/libtestinstr.c (renamed from examples/afl_frida/libtestinstr.c)0
-rw-r--r--utils/afl_network_proxy/GNUmakefile (renamed from examples/afl_network_proxy/GNUmakefile)0
-rw-r--r--utils/afl_network_proxy/Makefile (renamed from examples/afl_network_proxy/Makefile)0
-rw-r--r--utils/afl_network_proxy/README.md (renamed from examples/afl_network_proxy/README.md)0
-rw-r--r--utils/afl_network_proxy/afl-network-client.c (renamed from examples/afl_network_proxy/afl-network-client.c)0
-rw-r--r--utils/afl_network_proxy/afl-network-server.c (renamed from examples/afl_network_proxy/afl-network-server.c)15
-rw-r--r--utils/afl_proxy/Makefile (renamed from examples/afl_proxy/Makefile)0
-rw-r--r--utils/afl_proxy/README.md (renamed from examples/afl_proxy/README.md)0
-rw-r--r--utils/afl_proxy/afl-proxy.c (renamed from examples/afl_proxy/afl-proxy.c)0
-rw-r--r--utils/afl_untracer/Makefile (renamed from examples/afl_untracer/Makefile)0
-rw-r--r--utils/afl_untracer/README.md (renamed from examples/afl_untracer/README.md)0
-rw-r--r--utils/afl_untracer/TODO (renamed from examples/afl_untracer/TODO)0
-rw-r--r--utils/afl_untracer/afl-untracer.c (renamed from examples/afl_untracer/afl-untracer.c)0
-rw-r--r--utils/afl_untracer/ghidra_get_patchpoints.java (renamed from examples/afl_untracer/ghidra_get_patchpoints.java)2
-rw-r--r--utils/afl_untracer/ida_get_patchpoints.py (renamed from examples/afl_untracer/ida_get_patchpoints.py)0
-rw-r--r--utils/afl_untracer/libtestinstr.c (renamed from examples/afl_untracer/libtestinstr.c)0
-rw-r--r--utils/afl_untracer/patches.txt (renamed from examples/afl_untracer/patches.txt)0
-rw-r--r--utils/aflpp_driver/GNUmakefile (renamed from examples/aflpp_driver/GNUmakefile)0
-rw-r--r--utils/aflpp_driver/Makefile (renamed from examples/aflpp_driver/Makefile)0
-rw-r--r--utils/aflpp_driver/aflpp_driver.c (renamed from examples/aflpp_driver/aflpp_driver.c)0
-rw-r--r--utils/aflpp_driver/aflpp_driver_test.c (renamed from examples/aflpp_driver/aflpp_driver_test.c)0
-rw-r--r--utils/aflpp_driver/aflpp_qemu_driver.c (renamed from examples/aflpp_driver/aflpp_qemu_driver.c)4
-rw-r--r--utils/aflpp_driver/aflpp_qemu_driver_hook.c (renamed from examples/aflpp_driver/aflpp_qemu_driver_hook.c)0
-rwxr-xr-xutils/analysis_scripts/queue2csv.sh (renamed from examples/analysis_scripts/queue2csv.sh)0
-rw-r--r--utils/argv_fuzzing/Makefile (renamed from examples/argv_fuzzing/Makefile)0
-rw-r--r--utils/argv_fuzzing/README.md (renamed from examples/argv_fuzzing/README.md)0
-rw-r--r--utils/argv_fuzzing/argv-fuzz-inl.h (renamed from examples/argv_fuzzing/argv-fuzz-inl.h)0
-rw-r--r--utils/argv_fuzzing/argvfuzz.c (renamed from examples/argv_fuzzing/argvfuzz.c)0
-rwxr-xr-xutils/asan_cgroups/limit_memory.sh (renamed from examples/asan_cgroups/limit_memory.sh)0
-rw-r--r--utils/bash_shellshock/shellshock-fuzz.diff (renamed from examples/bash_shellshock/shellshock-fuzz.diff)0
-rw-r--r--utils/canvas_harness/canvas_harness.html (renamed from examples/canvas_harness/canvas_harness.html)0
-rwxr-xr-xutils/clang_asm_normalize/as (renamed from examples/clang_asm_normalize/as)0
-rwxr-xr-xutils/crash_triage/triage_crashes.sh (renamed from examples/crash_triage/triage_crashes.sh)0
-rw-r--r--utils/custom_mutators/Makefile (renamed from examples/custom_mutators/Makefile)0
-rw-r--r--utils/custom_mutators/README.md (renamed from examples/custom_mutators/README.md)0
-rw-r--r--utils/custom_mutators/XmlMutatorMin.py (renamed from examples/custom_mutators/XmlMutatorMin.py)0
-rw-r--r--utils/custom_mutators/common.py (renamed from examples/custom_mutators/common.py)0
-rw-r--r--utils/custom_mutators/custom_mutator_helpers.h (renamed from examples/custom_mutators/custom_mutator_helpers.h)0
-rw-r--r--utils/custom_mutators/example.c (renamed from examples/custom_mutators/example.c)0
-rw-r--r--utils/custom_mutators/example.py (renamed from examples/custom_mutators/example.py)0
-rw-r--r--utils/custom_mutators/post_library_gif.so.c (renamed from examples/custom_mutators/post_library_gif.so.c)0
-rw-r--r--utils/custom_mutators/post_library_png.so.c (renamed from examples/custom_mutators/post_library_png.so.c)0
-rw-r--r--utils/custom_mutators/simple-chunk-replace.py (renamed from examples/custom_mutators/simple-chunk-replace.py)0
-rw-r--r--utils/custom_mutators/simple_example.c (renamed from examples/custom_mutators/simple_example.c)0
-rw-r--r--utils/custom_mutators/wrapper_afl_min.py (renamed from examples/custom_mutators/wrapper_afl_min.py)0
-rw-r--r--utils/defork/Makefile (renamed from examples/defork/Makefile)0
-rw-r--r--utils/defork/README.md (renamed from examples/defork/README.md)0
-rw-r--r--utils/defork/defork.c (renamed from examples/defork/defork.c)0
-rw-r--r--utils/defork/forking_target.c (renamed from examples/defork/forking_target.c)0
-rwxr-xr-xutils/distributed_fuzzing/sync_script.sh (renamed from examples/distributed_fuzzing/sync_script.sh)0
-rw-r--r--utils/libpng_no_checksum/libpng-nocrc.patch (renamed from examples/libpng_no_checksum/libpng-nocrc.patch)0
-rw-r--r--utils/persistent_mode/Makefile (renamed from examples/persistent_demo/Makefile)0
-rw-r--r--utils/persistent_mode/persistent_demo.c (renamed from examples/persistent_demo/persistent_demo.c)0
-rw-r--r--utils/persistent_mode/persistent_demo_new.c (renamed from examples/persistent_demo/persistent_demo_new.c)6
-rw-r--r--utils/persistent_mode/test-instr.c (renamed from examples/persistent_demo/test-instr.c)0
-rw-r--r--utils/qemu_persistent_hook/Makefile (renamed from examples/qemu_persistent_hook/Makefile)0
-rw-r--r--utils/qemu_persistent_hook/README.md (renamed from examples/qemu_persistent_hook/README.md)0
-rw-r--r--utils/qemu_persistent_hook/read_into_rdi.c (renamed from examples/qemu_persistent_hook/read_into_rdi.c)0
-rw-r--r--utils/qemu_persistent_hook/test.c (renamed from examples/qemu_persistent_hook/test.c)0
-rw-r--r--utils/socket_fuzzing/Makefile (renamed from examples/socket_fuzzing/Makefile)0
-rw-r--r--utils/socket_fuzzing/README.md (renamed from examples/socket_fuzzing/README.md)0
-rw-r--r--utils/socket_fuzzing/socketfuzz.c (renamed from examples/socket_fuzzing/socketfuzz.c)0
149 files changed, 1825 insertions, 734 deletions
diff --git a/.custom-format.py b/.custom-format.py
index 60f6d9c3..fad74a69 100755
--- a/.custom-format.py
+++ b/.custom-format.py
@@ -29,7 +29,7 @@ CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
 if CLANG_FORMAT_BIN is None:
     o = 0
     try:
-        p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE)
+        p = subprocess.Popen(["clang-format-11", "--version"], stdout=subprocess.PIPE)
         o, _ = p.communicate()
         o = str(o, "utf-8")
         o = re.sub(r".*ersion ", "", o)
@@ -37,7 +37,7 @@ if CLANG_FORMAT_BIN is None:
         o = o[:o.find(".")]
         o = int(o)
     except:
-        print ("clang-format-10 is needed. Aborted.")
+        print ("clang-format-11 is needed. Aborted.")
         exit(1)
     #if o < 7:
     #    if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
@@ -46,13 +46,13 @@ if CLANG_FORMAT_BIN is None:
     #        CLANG_FORMAT_BIN = 'clang-format-8'
     #    elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0:
     #        CLANG_FORMAT_BIN = 'clang-format-9'
-    #    elif subprocess.call(['which', 'clang-format-10'], stdout=subprocess.PIPE) == 0:
-    #        CLANG_FORMAT_BIN = 'clang-format-10'
+    #    elif subprocess.call(['which', 'clang-format-11'], stdout=subprocess.PIPE) == 0:
+    #        CLANG_FORMAT_BIN = 'clang-format-11'
     #    else:
     #        print ("clang-format 7 or above is needed. Aborted.")
     #        exit(1)
     else:
-        CLANG_FORMAT_BIN = 'clang-format-10'
+        CLANG_FORMAT_BIN = 'clang-format-11'
             
 COLUMN_LIMIT = 80
 for line in fmt.split("\n"):
diff --git a/.gitignore b/.gitignore
index 97f99bf6..82a81605 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
 *.pyc
 *.dSYM
 as
+a.out
 ld
 in
 out
diff --git a/.gitmodules b/.gitmodules
index 7c7613ac..c787ec0e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,9 +1,8 @@
 [submodule "unicorn_mode/unicornafl"]
 	path = unicorn_mode/unicornafl
 	url = https://github.com/AFLplusplus/unicornafl
-
-[submodule "custom_mutators/Grammar-Mutator"]
-	path = custom_mutators/Grammar-Mutator
+[submodule "custom_mutators/grammar_mutator"]
+	path = custom_mutators/grammar_mutator/grammar_mutator
 	url = https://github.com/AFLplusplus/Grammar-Mutator
 [submodule "qemu_mode/qemuafl"]
 	path = qemu_mode/qemuafl
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ccacef5f..c36ed9d8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,9 +16,9 @@ project, or added a file in a directory we already format, otherwise run:
 ```
 
 Regarding the coding style, please follow the AFL style.
-No camel case at all and use the AFL's macros wherever possible 
+No camel case at all and use AFL's macros wherever possible
 (e.g. WARNF, FATAL, MAP_SIZE, ...).
 
 Remember that AFLplusplus has to build and run on many platforms, so
 generalize your Makefiles/GNUmakefile (or your patches to our pre-existing
-Makefiles) to be as much generic as possible.
+Makefiles) to be as generic as possible.
diff --git a/GNUmakefile b/GNUmakefile
index 764c9baa..309a7d4c 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -85,7 +85,9 @@ ifneq "$(shell uname)" "Darwin"
    endif
  endif
  # OS X does not like _FORTIFY_SOURCE=2
- CFLAGS_OPT += -D_FORTIFY_SOURCE=2
+ ifndef DEBUG
+   CFLAGS_OPT += -D_FORTIFY_SOURCE=2
+ endif
 endif
 
 ifeq "$(shell uname)" "SunOS"
@@ -232,7 +234,9 @@ else
 endif
 
 ifneq "$(filter Linux GNU%,$(shell uname))" ""
+ ifndef DEBUG
   override CFLAGS += -D_FORTIFY_SOURCE=2
+ endif
   LDFLAGS += -ldl -lrt -lm
 endif
 
@@ -417,7 +421,7 @@ src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
 	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
 
 afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
-	$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
+	$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
 
 afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
 	$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
@@ -496,8 +500,8 @@ code-format:
 	./.custom-format.py -i instrumentation/*.c
 	@#./.custom-format.py -i custom_mutators/*/*.c* # destroys libfuzzer :-(
 	@#./.custom-format.py -i custom_mutators/*/*.h # destroys honggfuzz :-(
-	./.custom-format.py -i examples/*/*.c*
-	./.custom-format.py -i examples/*/*.h
+	./.custom-format.py -i utils/*/*.c*
+	./.custom-format.py -i utils/*/*.h
 	./.custom-format.py -i test/*.c
 	./.custom-format.py -i qemu_mode/libcompcov/*.c
 	./.custom-format.py -i qemu_mode/libcompcov/*.cc
@@ -512,7 +516,7 @@ code-format:
 ifndef AFL_NO_X86
 test_build: afl-cc afl-as afl-showmap
 	@echo "[*] Testing the CC wrapper and instrumentation output..."
-	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
+	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
 	ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
 	echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
 	@rm -f test-instr
@@ -538,14 +542,14 @@ all_done: test_build
 
 .PHONY: clean
 clean:
-	rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ test/unittests/unit_hash test/unittests/unit_rand
+	rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand
 	-$(MAKE) -f GNUmakefile.llvm clean
 	-$(MAKE) -f GNUmakefile.gcc_plugin clean
 	$(MAKE) -C libdislocator clean
 	$(MAKE) -C libtokencap clean
-	$(MAKE) -C examples/afl_network_proxy clean
-	$(MAKE) -C examples/socket_fuzzing clean
-	$(MAKE) -C examples/argv_fuzzing clean
+	$(MAKE) -C utils/afl_network_proxy clean
+	$(MAKE) -C utils/socket_fuzzing clean
+	$(MAKE) -C utils/argv_fuzzing clean
 	$(MAKE) -C qemu_mode/unsigaction clean
 	$(MAKE) -C qemu_mode/libcompcov clean
 ifeq "$(IN_REPO)" "1"
@@ -568,10 +572,10 @@ distrib: all
 	-$(MAKE) -f GNUmakefile.gcc_plugin
 	$(MAKE) -C libdislocator
 	$(MAKE) -C libtokencap
-	$(MAKE) -C examples/aflpp_driver
-	$(MAKE) -C examples/afl_network_proxy
-	$(MAKE) -C examples/socket_fuzzing
-	$(MAKE) -C examples/argv_fuzzing
+	$(MAKE) -C utils/aflpp_driver
+	$(MAKE) -C utils/afl_network_proxy
+	$(MAKE) -C utils/socket_fuzzing
+	$(MAKE) -C utils/argv_fuzzing
 	-cd qemu_mode && sh ./build_qemu_support.sh
 	-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
 
@@ -579,9 +583,9 @@ distrib: all
 binary-only: all
 	$(MAKE) -C libdislocator
 	$(MAKE) -C libtokencap
-	$(MAKE) -C examples/afl_network_proxy
-	$(MAKE) -C examples/socket_fuzzing
-	$(MAKE) -C examples/argv_fuzzing
+	$(MAKE) -C utils/afl_network_proxy
+	$(MAKE) -C utils/socket_fuzzing
+	$(MAKE) -C utils/argv_fuzzing
 	-cd qemu_mode && sh ./build_qemu_support.sh
 	-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
 
@@ -591,7 +595,7 @@ source-only: all
 	-$(MAKE) -f GNUmakefile.gcc_plugin
 	$(MAKE) -C libdislocator
 	$(MAKE) -C libtokencap
-	$(MAKE) -C examples/aflpp_driver
+	$(MAKE) -C utils/aflpp_driver
 
 %.8:	%
 	@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
@@ -624,15 +628,17 @@ install: all $(MANPAGES)
 	@if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
 	@if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
 	@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
-	@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
-	@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
-	@if [ -f examples/afl_network_proxy/afl-network-server ]; then $(MAKE) -C examples/afl_network_proxy install; fi
-	@if [ -f examples/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 examples/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
-	@if [ -f examples/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 examples/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
+	@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
+	@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
+	@if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi
+	@if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
+	@if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
 	-$(MAKE) -f GNUmakefile.llvm install
 	-$(MAKE) -f GNUmakefile.gcc_plugin install
 	ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc
 	ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
+	ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang
+	ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang++
 	@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
 	install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
 	install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin
index bf3a3288..3f658a47 100644
--- a/GNUmakefile.gcc_plugin
+++ b/GNUmakefile.gcc_plugin
@@ -19,7 +19,7 @@
 #
 #   http://www.apache.org/licenses/LICENSE-2.0
 #
-
+#TEST_MMAP=1
 PREFIX      ?= /usr/local
 HELPER_PATH ?= $(PREFIX)/lib/afl
 BIN_PATH    ?= $(PREFIX)/bin
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index cc28695d..6e80de81 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -34,7 +34,7 @@ ifeq "$(shell uname)" "OpenBSD"
   LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
   HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
   ifeq "$(HAS_OPT)" "1"
-    $(warn llvm_mode needs a complete llvm installation (versions 3.4 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
+    $(warning llvm_mode needs a complete llvm installation (versions 3.4 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
   endif
 else
   LLVM_CONFIG ?= llvm-config
@@ -361,6 +361,8 @@ instrumentation/afl-common.o: ./src/afl-common.c
 	@ln -sf afl-cc ./afl-c++
 	@ln -sf afl-cc ./afl-gcc
 	@ln -sf afl-cc ./afl-g++
+	@ln -sf afl-cc ./afl-clang
+	@ln -sf afl-cc ./afl-clang++
 	@ln -sf afl-cc ./afl-clang-fast
 	@ln -sf afl-cc ./afl-clang-fast++
 ifneq "$(AFL_CLANG_FLTO)" ""
diff --git a/README.md b/README.md
index b1e20f75..94d5008e 100644
--- a/README.md
+++ b/README.md
@@ -22,8 +22,8 @@
   afl++ is a superior fork to Google's afl - more speed, more and better
   mutations, more and better instrumentation, custom module support, etc.
 
-  If you want to use afl++ for you academic work, check the [papers page](https://aflplus.plus/papers/)
-  in the website.
+  If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
+  on the website.
 
 ## Major changes in afl++ 3.0
 
@@ -55,6 +55,7 @@ behaviours and defaults:
     * a caching of testcases can now be performed and can be modified by
       editing config.h for TESTCASE_CACHE or by specifying the env variable
       `AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500 (default: 50).
+  * examples/ got renamed to utils/
 
 ## Contents
 
@@ -273,7 +274,7 @@ anything below 9 is not recommended.
     v
 +---------------------------------+
 | clang/clang++ 3.3+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
-+---------------------------------+     see [instrumentation/README.md](instrumentation/README.md)
++---------------------------------+     see [instrumentation/README.llvm.md](instrumentation/README.llvm.md)
     |
     | if not, or if the target fails with LLVM afl-clang-fast/++
     |
@@ -292,7 +293,7 @@ anything below 9 is not recommended.
 Clickable README links for the chosen compiler:
 
   * [LTO mode - afl-clang-lto](instrumentation/README.lto.md)
-  * [LLVM mode - afl-clang-fast](instrumentation/README.md)
+  * [LLVM mode - afl-clang-fast](instrumentation/README.llvm.md)
   * [GCC_PLUGIN mode - afl-gcc-fast](instrumentation/README.gcc_plugin.md)
   * GCC mode (afl-gcc) has no README as it has no own features
 
@@ -525,7 +526,7 @@ as test data in there.
 
 If you do not want anything special, the defaults are already usually best,
 hence all you need is to specify the seed input directory with the result of
-step [2. Collect inputs](#a)a-collect-inputs)):
+step [2a. Collect inputs](#a-collect-inputs):
 `afl-fuzz -i input -o output -- bin/target -d @@`
 Note that the directory specified with -o will be created if it does not exist.
 
@@ -541,7 +542,7 @@ 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 none` - which is usually required for ASAN compiled targets.
 
-Adding a dictionary is helpful. See the [dictionaries/](dictionaries/) if
+Adding a dictionary is helpful. See the directory [dictionaries/](dictionaries/) if
 something is already included for your data format, and tell afl-fuzz to load
 that dictionary by adding `-x dictionaries/FORMAT.dict`. With afl-clang-lto
 you have an autodictionary generation for which you need to do nothing except
@@ -760,10 +761,10 @@ cd unicorn_mode
 
 If the goal is to fuzz a dynamic library then there are two options available.
 For both you need to write a small hardness that loads and calls the library.
-Faster is the frida solution: [examples/afl_frida/README.md](examples/afl_frida/README.md)
+Faster is the frida solution: [utils/afl_frida/README.md](utils/afl_frida/README.md)
 
 Another, less precise and slower option is using ptrace with debugger interrupt
-instrumentation: [examples/afl_untracer/README.md](examples/afl_untracer/README.md)
+instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md)
 
 ### More
 
@@ -1037,7 +1038,7 @@ Here are some of the most important caveats for AFL:
     wholly wrap the actual data format to be tested.
 
     To work around this, you can comment out the relevant checks (see
-    examples/libpng_no_checksum/ for inspiration); if this is not possible,
+    utils/libpng_no_checksum/ for inspiration); if this is not possible,
     you can also write a postprocessor, one of the hooks of custom mutators.
     See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use
     `AFL_CUSTOM_MUTATOR_LIBRARY`
@@ -1109,7 +1110,8 @@ without feedback, bug reports, or patches from:
   Andrea Biondo                         Vincent Le Garrec
   Khaled Yakdan                         Kuang-che Wu
   Josephine Calliotte                   Konrad Welc
-  David Carlier                         Ruben ten Hove
+  Thomas Rooijakkers                    David Carlier
+  Ruben ten Hove
 ```
 
 Thank you!
diff --git a/afl-cmin b/afl-cmin
index 0dbf1390..93174b8b 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -113,14 +113,15 @@ function usage() {
 "  -C            - keep crashing inputs, reject everything else\n" \
 "  -e            - solve for edge coverage only, ignore hit counts\n" \
 "\n" \
-"For additional tips, please consult docs/README.md\n" \
+"For additional tips, please consult README.md\n" \
 "\n" \
 "Environment variables used:\n" \
+"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \
+"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
+"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
 "AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
 "AFL_PATH: path for the afl-showmap binary\n" \
-"AFL_SKIP_BIN_CHECK: skip check for target binary\n" \
-"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n"
-"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n"
+"AFL_SKIP_BIN_CHECK: skip check for target binary\n"
    exit 1
 }
 
diff --git a/afl-cmin.bash b/afl-cmin.bash
index 3e29aa5c..637949bc 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -128,7 +128,7 @@ Minimization settings:
   -C            - keep crashing inputs, reject everything else
   -e            - solve for edge coverage only, ignore hit counts
 
-For additional tips, please consult docs/README.md.
+For additional tips, please consult README.md.
 
 Environment variables used:
 AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
diff --git a/custom_mutators/README.md b/custom_mutators/README.md
index 0cf52746..b0444c85 100644
--- a/custom_mutators/README.md
+++ b/custom_mutators/README.md
@@ -7,15 +7,13 @@ For further information and documentation on how to write your own, read [the do
 
 If you use git to clone afl++, then the following will incorporate our
 excellent grammar custom mutator:
-```
-git submodule init
-git submodule update
+```sh
+git submodule update --init
 ```
 
-otherwise just use the script: `grammar_mutator/build_grammar_mutator.sh`
+Read the README in the [Grammar-Mutator] repository on how to use it.
 
-Read the [Grammar-Mutator/README.md](Grammar-Mutator/README.md) on how to use
-it.
+[Grammar-Mutator]: https://github.com/AFLplusplus/Grammar-Mutator
 
 ## Production-Ready Custom Mutators
 
diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION
new file mode 100644
index 00000000..a3fe6bb1
--- /dev/null
+++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION
@@ -0,0 +1 @@
+b3c4fcf
diff --git a/custom_mutators/grammar_mutator/build_grammar_mutator.sh b/custom_mutators/grammar_mutator/build_grammar_mutator.sh
index f3f5e164..ef145dfe 100755
--- a/custom_mutators/grammar_mutator/build_grammar_mutator.sh
+++ b/custom_mutators/grammar_mutator/build_grammar_mutator.sh
@@ -1,17 +1,140 @@
 #!/bin/sh
+#
+# american fuzzy lop++ - unicorn mode build script
+# ------------------------------------------------
+#
+# Originally written by Nathan Voss <njvoss99@gmail.com>
+#
+# Adapted from code by Andrew Griffiths <agriffiths@google.com> and
+#                      Michal Zalewski
+#
+# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
+#
+# CompareCoverage and NeverZero counters by Andrea Fioraldi
+#                                <andreafioraldi@gmail.com>
+#
+# Copyright 2017 Battelle Memorial Institute. All rights reserved.
+# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# This script downloads, patches, and builds a version of Unicorn with
+# minor tweaks to allow Unicorn-emulated binaries to be run under
+# afl-fuzz.
+#
+# The modifications reside in patches/*. The standalone Unicorn library
+# will be written to /usr/lib/libunicornafl.so, and the Python bindings
+# will be installed system-wide.
+#
+# You must make sure that Unicorn Engine is not already installed before
+# running this script. If it is, please uninstall it first.
 
-test -d Grammar-Mutator || git clone --depth=1 https://github.com/AFLplusplus/Grammar-Mutator
+GRAMMAR_VERSION="$(cat ./GRAMMAR_VERSION)"
+GRAMMAR_REPO="https://github.com/AFLplusplus/grammar-mutator"
 
-cd Grammar-Mutator || exit 1
-git stash ; git pull
+echo "================================================="
+echo "Grammar Mutator build script"
+echo "================================================="
+echo
+
+echo "[*] Performing basic sanity checks..."
+
+PLT=`uname -s`
+
+if [ ! -f "../../config.h" ]; then
+
+  echo "[-] Error: key files not found - wrong working directory?"
+  exit 1
+
+fi
+
+PYTHONBIN=`command -v python3 || command -v python || command -v python2 || echo python3`
+MAKECMD=make
+TARCMD=tar
+
+if [ "$PLT" = "Darwin" ]; then
+  CORES=`sysctl -n hw.ncpu`
+  TARCMD=tar
+fi
+
+if [ "$PLT" = "FreeBSD" ]; then
+  MAKECMD=gmake
+  CORES=`sysctl -n hw.ncpu`
+  TARCMD=gtar
+fi
+
+if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
+  MAKECMD=gmake
+  CORES=`sysctl -n hw.ncpu`
+  TARCMD=gtar
+fi
+
+PREREQ_NOTFOUND=
+for i in git $MAKECMD $TARCMD; do
+
+  T=`command -v "$i" 2>/dev/null`
+
+  if [ "$T" = "" ]; then
+
+    echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar."
+    PREREQ_NOTFOUND=1
+
+  fi
+
+done
+
+if echo "$CC" | grep -qF /afl-; then
+
+  echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
+  PREREQ_NOTFOUND=1
+
+fi
+
+if [ "$PREREQ_NOTFOUND" = "1" ]; then
+  exit 1
+fi
+
+echo "[+] All checks passed!"
+
+echo "[*] Making sure grammar mutator is checked out"
+
+git status 1>/dev/null 2>/dev/null
+if [ $? -eq 0 ]; then
+  echo "[*] initializing grammar mutator submodule"
+  git submodule init || exit 1
+  git submodule update ./grammar-mutator 2>/dev/null # ignore errors
+else
+  echo "[*] cloning grammar mutator"
+  test -d grammar-mutator || {
+    CNT=1
+    while [ '!' -d grammar-mutator -a "$CNT" -lt 4 ]; do
+      echo "Trying to clone grammar-mutator (attempt $CNT/3)"
+      git clone "$GRAMMAR_REPO" 
+      CNT=`expr "$CNT" + 1`
+    done
+  }
+fi
+
+test -d grammar-mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
+echo "[+] Got grammar mutator."
 
+cd "grammar-mutator" || exit 1
+echo "[*] Checking out $GRAMMAR_VERSION"
+sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
+git checkout "$GRAMMAR_VERSION" || exit 1
+echo "[*] Downloading antlr..."
 wget -c https://www.antlr.org/download/antlr-4.8-complete.jar
+cd ..
 
 echo
 echo
-echo "All successfully prepared!"
-echo "To build for your grammar just do:"
-echo "  cd Grammar_Mutator"
-echo "  make GRAMMAR_FILE=/path/to/your/grammar"
-echo "You will find a JSON and RUBY grammar in Grammar_Mutator/grammars to play with."
+echo "[+] All successfully prepared!"
+echo "[!] To build for your grammar just do:"
+echo "      cd grammar-mutator"
+echo "      make GRAMMAR_FILE=/path/to/your/grammar"
+echo "[+] You will find a JSON and RUBY grammar in grammar-mutator/grammars to play with."
 echo
diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator
new file mode 160000
+Subproject b3c4fcfa6ae28918bc410f7747135eafd4fb726
diff --git a/custom_mutators/grammar_mutator/update_grammar_ref.sh b/custom_mutators/grammar_mutator/update_grammar_ref.sh
new file mode 100755
index 00000000..89067b13
--- /dev/null
+++ b/custom_mutators/grammar_mutator/update_grammar_ref.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+##################################################
+# AFL++ tool to update a git ref.
+# Usage: ./<script>.sh <new commit hash>
+# If no commit hash was provided, it'll take HEAD.
+##################################################
+
+TOOL="grammar mutator"
+VERSION_FILE='./GRAMMAR_VERSION'
+REPO_FOLDER='./grammar_mutator'
+THIS_SCRIPT=`basename $0`
+BRANCH="stable"
+
+NEW_VERSION="$1"
+
+if [ "$NEW_VERSION" = "-h" ]; then
+  echo "Internal script to update bound $TOOL version."
+  echo
+  echo "Usage: $THIS_SCRIPT <new commit hash>"
+  echo "If no commit hash is provided, will use HEAD."
+  echo "-h to show this help screen."
+  exit 1
+fi
+
+git submodule init && git submodule update ./grammar_mutator || exit 1
+cd "$REPO_FOLDER" || exit 1
+git fetch origin $BRANCH 1>/dev/null || exit 1
+git stash 1>/dev/null 2>/dev/null
+git stash drop 1>/dev/null 2>/dev/null
+git checkout $BRANCH
+
+if [ -z "$NEW_VERSION" ]; then
+  # No version provided, take HEAD.
+  NEW_VERSION=$(git rev-parse --short HEAD)
+fi
+
+if [ -z "$NEW_VERSION" ]; then
+  echo "Error getting version."
+  exit 1
+fi
+
+git checkout "$NEW_VERSION" || exit 1
+
+cd ..
+
+rm "$VERSION_FILE"
+echo "$NEW_VERSION" > "$VERSION_FILE"
+
+echo "Done. New $TOOL version is $NEW_VERSION."
diff --git a/custom_mutators/symcc/symcc.c b/custom_mutators/symcc/symcc.c
index f32f98f8..a609dafb 100644
--- a/custom_mutators/symcc/symcc.c
+++ b/custom_mutators/symcc/symcc.c
@@ -1,7 +1,10 @@
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include "config.h"
 #include "debug.h"
 #include "afl-fuzz.h"
@@ -21,6 +24,7 @@ typedef struct my_mutator {
   afl_state_t *afl;
   u8 *         mutator_buf;
   u8 *         out_dir;
+  u8 *         tmp_dir;
   u8 *         target;
   uint32_t     seed;
 
@@ -55,10 +59,11 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
   if (!(data->out_dir = getenv("SYMCC_OUTPUT_DIR"))) {
 
     data->out_dir = alloc_printf("%s/symcc", afl->out_dir);
-    setenv("SYMCC_OUTPUT_DIR", data->out_dir, 1);
 
   }
 
+  data->tmp_dir = alloc_printf("%s/tmp", data->out_dir);
+  setenv("SYMCC_OUTPUT_DIR", data->tmp_dir, 1);
   int pid = fork();
 
   if (pid == -1) return NULL;
@@ -84,6 +89,10 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   if (mkdir(data->out_dir, 0755))
     PFATAL("Could not create directory %s", data->out_dir);
+
+  if (mkdir(data->tmp_dir, 0755))
+    PFATAL("Could not create directory %s", data->tmp_dir);
+
   DBG("out_dir=%s, target=%s\n", data->out_dir, data->target);
 
   return data;
@@ -96,33 +105,119 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
                                 const uint8_t *filename_new_queue,
                                 const uint8_t *filename_orig_queue) {
 
-  int pid = fork();
+  int         pipefd[2];
+  struct stat st;
+  ACTF("Queueing to symcc: %s", filename_new_queue);
+  u8 *fn = alloc_printf("%s", filename_new_queue);
+  if (!(stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size)) {
 
-  if (pid == -1) return;
+    ck_free(fn);
+    PFATAL("Couldn't find enqueued file: %s", fn);
 
-  if (pid) pid = waitpid(pid, NULL, 0);
+  }
 
-  if (pid == 0) {
+  if (afl_struct->fsrv.use_stdin) {
+
+    if (pipe(pipefd) == -1) {
+
+      ck_free(fn);
+      PFATAL("Couldn't create a pipe for interacting with symcc child process");
+
+    }
+
+  }
+
+  int pid = fork();
 
-    setenv("SYMCC_INPUT_FILE", afl_struct->fsrv.out_file, 1);
+  if (pid == -1) return;
+
+  if (pid) {
 
     if (afl_struct->fsrv.use_stdin) {
 
-      u8 *fn = alloc_printf("%s/%s", afl_struct->out_dir, filename_new_queue);
+      close(pipefd[0]);
       int fd = open(fn, O_RDONLY);
 
       if (fd >= 0) {
 
         ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
-        close(fd);
         DBG("fn=%s, fd=%d, size=%ld\n", fn, fd, r);
-        if (r <= 0) return;
-        close(0);
-        ck_write(0, data->mutator_buf, r, fn);
         ck_free(fn);
+        close(fd);
+        if (r <= 0) {
+
+          close(pipefd[1]);
+          return;
+
+        }
+
+        if (r > fcntl(pipefd[1], F_GETPIPE_SZ))
+          fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE);
+        ck_write(pipefd[1], data->mutator_buf, r, filename_new_queue);
+
+      } else {
+
+        ck_free(fn);
+        close(pipefd[1]);
+        PFATAL(
+            "Something happened to the enqueued file before sending its "
+            "contents to symcc binary");
 
       }
 
+      close(pipefd[1]);
+
+    }
+
+    pid = waitpid(pid, NULL, 0);
+
+    // At this point we need to transfer files to output dir, since their names
+    // collide and symcc will just overwrite them
+
+    struct dirent **nl;
+    int32_t         items = scandir(data->tmp_dir, &nl, NULL, NULL);
+    u8 *            origin_name = basename(filename_new_queue);
+    int32_t         i;
+    if (items > 0) {
+
+      for (i = 0; i < (u32)items; ++i) {
+
+        struct stat st;
+        u8 *source_name = alloc_printf("%s/%s", data->tmp_dir, nl[i]->d_name);
+        DBG("test=%s\n", fn);
+        if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
+
+          u8 *destination_name =
+              alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
+          rename(source_name, destination_name);
+          ck_free(destination_name);
+          DBG("found=%s\n", source_name);
+
+        }
+
+        ck_free(source_name);
+        free(nl[i]);
+
+      }
+
+      free(nl);
+
+    }
+
+  }
+
+  if (pid == 0) {
+
+    if (afl_struct->fsrv.use_stdin) {
+
+      unsetenv("SYMCC_INPUT_FILE");
+      close(pipefd[1]);
+      dup2(pipefd[0], 0);
+
+    } else {
+
+      setenv("SYMCC_INPUT_FILE", afl_struct->fsrv.out_file, 1);
+
     }
 
     DBG("exec=%s\n", data->target);
@@ -130,6 +225,7 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
     close(2);
     dup2(afl_struct->fsrv.dev_null_fd, 1);
     dup2(afl_struct->fsrv.dev_null_fd, 2);
+
     execvp(data->target, afl_struct->argv);
     DBG("exec=FAIL\n");
     exit(-1);
@@ -180,7 +276,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 
   struct dirent **nl;
   int32_t         i, done = 0, items = scandir(data->out_dir, &nl, NULL, NULL);
-  size_t          size = 0;
+  ssize_t         size = 0;
 
   if (items <= 0) return 0;
 
@@ -199,6 +295,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 
           size = read(fd, data->mutator_buf, max_size);
           *out_buf = data->mutator_buf;
+
           close(fd);
           done = 1;
 
@@ -217,7 +314,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 
   free(nl);
   DBG("FUZZ size=%lu\n", size);
-  return size;
+  return (uint32_t)size;
 
 }
 
diff --git a/custom_mutators/symcc/test_examples/file_test.c b/custom_mutators/symcc/test_examples/file_test.c
new file mode 100644
index 00000000..f2b92986
--- /dev/null
+++ b/custom_mutators/symcc/test_examples/file_test.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv) {
+
+  if (argc < 2) {
+
+    printf("Need a file argument\n");
+    return 1;
+
+  }
+
+  int fd = open(argv[1], O_RDONLY);
+  if (fd < 0) {
+
+    printf("Couldn't open file\n");
+    return 1;
+
+  }
+
+  uint32_t value = 0;
+
+  read(fd, &value, sizeof(value));
+  close(fd);
+
+  value = value ^ 0xffffffff;
+  if (value == 0x11223344) printf("Value one\n");
+  if (value == 0x44332211) printf("Value two\n");
+  if (value != 0x0) printf("Not zero\n");
+  return 0;
+
+}
+
diff --git a/custom_mutators/symcc/test_examples/stdin_test.c b/custom_mutators/symcc/test_examples/stdin_test.c
new file mode 100644
index 00000000..3acfc523
--- /dev/null
+++ b/custom_mutators/symcc/test_examples/stdin_test.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+
+  char     input_buffer[16];
+  uint32_t comparisonValue;
+  size_t   bytesRead;
+  bytesRead = read(STDIN_FILENO, input_buffer, sizeof(input_buffer));
+  if (bytesRead < 0) exit(-1);
+  comparisonValue = *(uint32_t *)input_buffer;
+  comparisonValue = comparisonValue ^ 0xff112233;
+  if (comparisonValue == 0x66554493) {
+
+    printf("First value\n");
+
+  } else {
+
+    if (comparisonValue == 0x84444415) printf("Second value\n");
+
+  }
+
+  return 0;
+
+}
+
diff --git a/dictionaries/README.md b/dictionaries/README.md
index 616a83cc..7c587abb 100644
--- a/dictionaries/README.md
+++ b/dictionaries/README.md
@@ -1,6 +1,6 @@
 # AFL dictionaries
 
-(See [../docs/README.md](../docs/README.md) for the general instruction manual.)
+(See [../README.md](../README.md) for the general instruction manual.)
 
 This subdirectory contains a set of dictionaries that can be used in
 conjunction with the -x option to allow the fuzzer to effortlessly explore the
diff --git a/docs/Changelog.md b/docs/Changelog.md
index a69f2ff4..5201eb8b 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -11,6 +11,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
 
 ### Version ++3.00a (develop)
   - llvm_mode/ and gcc_plugin/ moved to instrumentation/
+  - examples/ renamed to utils/
   - all compilers combined to afl-cc which emulates the previous ones
   - afl-llvm/gcc-rt.o merged into afl-compiler-rt.o
   - afl-fuzz
@@ -21,40 +22,50 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
       a schedule performance score, which is much better that the previous
       walk the whole queue approach. Select the old mode with -Z (auto enabled
       with -M)
-    - rpc.statsd support by Edznux, thanks a lot!
+    - rpc.statsd support, for stats and charts, by Edznux, thanks a lot!
     - Marcel Boehme submitted a patch that improves all AFFast schedules :)
     - not specifying -M or -S will now auto-set "-S default"
     - reading testcases from -i now descends into subdirectories
-    - allow up to 4 times the -x command line option
-    - loaded extras now have a duplicate protection
+    - allow the -x command line option up to 4 times
+    - loaded extras now have a duplication protection
     - If test cases are too large we do a partial read on the maximum
       supported size
     - longer seeds with the same trace information will now be ignored
       for fuzzing but still be used for splicing
     - crashing seeds are now not prohibiting a run anymore but are
-      skipped. They are used for splicing though.
+      skipped - they are used for splicing, though
     - update MOpt for expanded havoc modes
+    - setting the env var AFL_NO_AUTODICT will not load an LTO autodictionary
     - added NO_SPLICING compile option and makefile define
     - added INTROSPECTION make target that writes all mutations to
       out/NAME/introspection.txt
-    - added INTROSPECTION support for custom modules
     - print special compile time options used in help output
+    - when using -c cmplog, one of the childs was not killed, fixed
+    - somewhere we broke -n dumb fuzzing, fixed
+    - added afl_custom_describe to the custom mutator API to allow for easy
+      mutation reproduction on crashing inputs
   - instrumentation
     - We received an enhanced gcc_plugin module from AdaCore, thank you
       very much!!
     - not overriding -Ox or -fno-unroll-loops anymore
     - we now have our own trace-pc-guard implementation. It is the same as
       -fsanitize-coverage=trace-pc-guard from llvm 12, but: it is a) inline
-      and b) works from llvm 10+ on :)
+      and b) works from llvm 10.0.1 + onwards :)
     - new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz
       -x dictionary of string comparisons found during compilation
     - LTO autodict now also collects interesting cmp comparisons,
       std::string compare + find + ==, bcmp
     - fix crash in dict2file for integers > 64 bit
-  - unicornafl synced with upstream (arm64 fix, better rust bindings)
-  - added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
-  - added a new custom mutator: libfuzzer that integrates libfuzzer mutations
-  - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
+  - custom mutators
+    - added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
+    - added a new custom mutator: libfuzzer that integrates libfuzzer mutations
+    - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
+    - added INTROSPECTION support for custom modules
+    - python fuzz function was not optional, fixed
+    - some python mutator speed improvements
+  - unicornafl synced with upstream version 1.02 (fixes, better rust bindings)
+  - renamed AFL_DEBUG_CHILD_OUTPUT to AFL_DEBUG_CHILD
+  - added AFL_CRASH_EXITCODE env variable to treat a child exitcode as crash
 
 
 ### Version ++2.68c (release)
diff --git a/docs/FAQ.md b/docs/FAQ.md
index 064638f4..714d50eb 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -63,7 +63,7 @@ x10 - that is a x100 difference!).
 If modifying the source is not an option (e.g. because you only have a binary
 and perform binary fuzzing) you can also use a shared library with AFL_PRELOAD
 to emulate the network. This is also much faster than the real network would be.
-See [examples/socket_fuzzing/](../examples/socket_fuzzing/).
+See [utils/socket_fuzzing/](../utils/socket_fuzzing/).
 
 There is an outdated afl++ branch that implements networking if you are
 desperate though: [https://github.com/AFLplusplus/AFLplusplus/tree/networking](https://github.com/AFLplusplus/AFLplusplus/tree/networking) - 
diff --git a/docs/README.md b/docs/README.md
deleted file mode 120000
index 32d46ee8..00000000
--- a/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-../README.md
\ No newline at end of file
diff --git a/docs/binaryonly_fuzzing.md b/docs/binaryonly_fuzzing.md
index cb1288ef..66734452 100644
--- a/docs/binaryonly_fuzzing.md
+++ b/docs/binaryonly_fuzzing.md
@@ -15,7 +15,7 @@
   high enough. Otherwise try retrowrite, afl-dyninst and if these
   fail too then try standard qemu_mode with AFL_ENTRYPOINT to where you need it.
 
-  If your target is a library use examples/afl_frida/.
+  If your target is a library use utils/afl_frida/.
 
   If your target is non-linux then use unicorn_mode/.
 
@@ -65,14 +65,14 @@
 ## AFL FRIDA
 
    If you want to fuzz a binary-only shared library then you can fuzz it with
-   frida-gum via examples/afl_frida/, you will have to write a harness to
+   frida-gum via utils/afl_frida/, you will have to write a harness to
    call the target function in the library, use afl-frida.c as a template.
 
 
 ## AFL UNTRACER
 
    If you want to fuzz a binary-only shared library then you can fuzz it with
-   examples/afl_untracer/, use afl-untracer.c as a template.
+   utils/afl_untracer/, use afl-untracer.c as a template.
    It is slower than AFL FRIDA (see above).
 
 
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 2516e511..a2c544e3 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -34,6 +34,7 @@ C/C++:
 void *afl_custom_init(afl_state_t *afl, unsigned int seed);
 unsigned int afl_custom_fuzz_count(void *data, const unsigned char *buf, size_t buf_size);
 size_t afl_custom_fuzz(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, unsigned char *add_buf, size_t add_buf_size, size_t max_size);
+const char *afl_custom_describe(void *data, size_t max_description_len);
 size_t afl_custom_post_process(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf);
 int afl_custom_init_trim(void *data, unsigned char *buf, size_t buf_size);
 size_t afl_custom_trim(void *data, unsigned char **out_buf);
@@ -57,6 +58,9 @@ def fuzz_count(buf, add_buf, max_size):
 def fuzz(buf, add_buf, max_size):
     return mutated_out
 
+def describe(max_description_length):
+    return "description_of_current_mutation"
+
 def post_process(buf):
     return out_buf
 
@@ -102,7 +106,7 @@ def introspection():
     of fuzzing attempts with this input based on a few factors.
     If however the custom mutator wants to set this number instead on how often
     it is called for a specific queue entry, use this function.
-    This function in mostly useful if **not** `AFL_CUSTOM_MUTATOR_ONLY` is used.
+    This function is most useful if `AFL_CUSTOM_MUTATOR_ONLY` is **not** used.
 
 - `fuzz` (optional):
 
@@ -110,12 +114,19 @@ def introspection():
     additional test case.
     Note that this function is optional - but it makes sense to use it.
     You would only skip this if `post_process` is used to fix checksums etc.
-    so you are using it e.g. as a post processing library.
+    so if you are using it e.g. as a post processing library.
+
+- `describe` (optional):
+
+    When this function is called, it shall describe the current testcase,
+    generated by the last mutation. This will be called, for example,
+    to name the written testcase file after a crash occurred.
+    Using it can help to reproduce crashing mutations.
 
 - `havoc_mutation` and `havoc_mutation_probability` (optional):
 
     `havoc_mutation` performs a single custom mutation on a given input. This
-    mutation is stacked with the other mutations in havoc. The other method,
+    mutation is stacked with other mutations in havoc. The other method,
     `havoc_mutation_probability`, returns the probability that `havoc_mutation`
     is called in havoc. By default, it is 6%.
 
@@ -130,6 +141,9 @@ def introspection():
     `post_process` function. This function is then transforming the data into the
     format expected by the API before executing the target.
 
+    This can return any python object that implements the buffer protocol and
+    supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
+
 - `queue_new_entry` (optional):
 
     This methods is called after adding a new test case to the queue.
@@ -168,7 +182,7 @@ trimmed input. Here's a quick API description:
     on this input (e.g. if your input has n elements and you want to remove them
     one by one, return n, if you do a binary search, return log(n), and so on).
 
-    If your trimming algorithm doesn't allow you to determine the amount of
+    If your trimming algorithm doesn't allow to determine the amount of
     (remaining) steps easily (esp. while running), then you can alternatively
     return 1 here and always return 0 in `post_trim` until you are finished and
     no steps remain. In that case, returning 1 in `post_trim` will end the
@@ -210,19 +224,20 @@ Optionally, the following environment variables are supported:
 
 - `AFL_PYTHON_ONLY`
 
-    Deprecated and removed, use `AFL_CUSTOM_MUTATOR_ONLY` instead
-    trimming can cause the same test breakage like havoc and splice.
+    Deprecated and removed, use `AFL_CUSTOM_MUTATOR_ONLY` instead.
 
 - `AFL_DEBUG`
 
-    When combined with `AFL_NO_UI`, this causes the C trimming code to emit additional messages about the performance and actions of your custom trimmer. Use this to see if it works :)
+    When combined with `AFL_NO_UI`, this causes the C trimming code to emit
+    additional messages about the performance and actions of your custom
+    trimmer. Use this to see if it works :)
 
 ## 3) Usage
 
 ### Prerequisite
 
-For Python mutator, the python 3 or 2 development package is required. On
-Debian/Ubuntu/Kali this can be done:
+For Python mutators, the python 3 or 2 development package is required. On
+Debian/Ubuntu/Kali it can be installed like this:
 
 ```bash
 sudo apt install python3-dev
@@ -240,13 +255,13 @@ In case your setup is different, set the necessary variables like this:
 
 ### Custom Mutator Preparation
 
-For C/C++ mutator, the source code must be compiled as a shared object:
+For C/C++ mutators, the source code must be compiled as a shared object:
 ```bash
 gcc -shared -Wall -O3 example.c -o example.so
 ```
 Note that if you specify multiple custom mutators, the corresponding functions will
 be called in the order in which they are specified. e.g first `post_process` function of
-`example_first.so` will be called and then that of `example_second.so`
+`example_first.so` will be called and then that of `example_second.so`.
 
 ### Run
 
@@ -265,8 +280,8 @@ afl-fuzz /path/to/program
 
 ## 4) Example
 
-Please see [example.c](../examples/custom_mutators/example.c) and
-[example.py](../examples/custom_mutators/example.py)
+Please see [example.c](../utils/custom_mutators/example.c) and
+[example.py](../utils/custom_mutators/example.py)
 
 ## 5) Other Resources
 
diff --git a/docs/env_variables.md b/docs/env_variables.md
index a36f2b4e..e203055f 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -55,7 +55,7 @@ make fairly broad use of environmental variables instead:
     in your `$PATH`.
 
   - `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
-    One possible use of this is examples/clang_asm_normalize/, which lets
+    One possible use of this is utils/clang_asm_normalize/, which lets
     you instrument hand-written assembly when compiling clang code by plugging
     a normalizer into the chain. (There is no equivalent feature for GCC.)
 
@@ -294,6 +294,9 @@ checks or alter some of the more exotic semantics of the tool:
     on Linux systems. This slows things down, but lets you run more instances
     of afl-fuzz than would be prudent (if you really want to).
 
+  - Setting `AFL_NO_AUTODICT` will not load an LTO generated auto dictionary
+    that is compiled into the target.
+
   - `AFL_SKIP_CRASHES` causes AFL++ to tolerate crashing files in the input
     queue. This can help with rare situations where a program crashes only
     intermittently, but it's not really recommended under normal operating
@@ -306,6 +309,14 @@ checks or alter some of the more exotic semantics of the tool:
     don't want AFL++ to spend too much time classifying that stuff and just
     rapidly put all timeouts in that bin.
 
+  - Setting `AFL_FORKSRV_INIT_TMOUT` allows you to specify a different timeout
+    to wait for the forkserver to spin up. The default is the `-t` value times
+    `FORK_WAIT_MULT` from `config.h` (usually 10), so for a `-t 100`, the
+    default would wait for `1000` milliseconds. Setting a different time here is useful
+    if the target has a very slow startup time, for example when doing
+    full-system fuzzing or emulation, but you don't want the actual runs
+    to wait too long for timeouts.
+
   - `AFL_NO_ARITH` causes AFL++ to skip most of the deterministic arithmetics.
     This can be useful to speed up the fuzzing of text-based file formats.
 
@@ -380,8 +391,12 @@ checks or alter some of the more exotic semantics of the tool:
     processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to
     exit soon after the first crash is found.
 
-  - Setting `AFL_DEBUG_CHILD_OUTPUT` will not suppress the child output.
+  - Setting `AFL_DEBUG_CHILD` will not suppress the child output.
+    This lets you see all output of the child, making setup issues obvious.
+    For example, in an unicornafl harness, you might see python stacktraces.
+    You may also see other logs that way, indicating why the forkserver won't start.
     Not pretty but good for debugging purposes.
+    Note that `AFL_DEBUG_CHILD_OUTPUT` is deprecated.
 
   - Setting `AFL_NO_CPU_RED` will not display very high cpu usages in red color.
 
@@ -389,6 +404,13 @@ checks or alter some of the more exotic semantics of the tool:
     for an existing out folder, even if a different `-i` was provided.
     Without this setting, afl-fuzz will refuse execution for a long-fuzzed out dir.
 
+  - Setting `AFL_MAX_DET_EXRAS` will change the threshold at what number of elements
+    in the `-x` dictionary and LTO autodict (combined) the probabilistic mode will
+    kick off. In probabilistic mode not all dictionary entires will be used all
+    of the times for fuzzing mutations to not slow down fuzzing.
+    The default count is `200` elements. So for the 200 + 1st element, there is a
+    1 in 201 chance, that one of the dictionary entries will not be used directly.
+
   - Setting `AFL_NO_FORKSRV` disables the forkserver optimization, reverting to
     fork + execve() call for every tested input. This is useful mostly when
     working with unruly libraries that create threads or do other crazy
@@ -406,6 +428,13 @@ checks or alter some of the more exotic semantics of the tool:
     matches your StatsD server.
     Available flavors are `dogstatsd`, `librato`, `signalfx` and `influxdb`.
 
+  - Setting `AFL_CRASH_EXITCODE` sets the exit code afl treats as crash.
+    For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting
+    in an `-1` return code (i.e. `exit(-1)` got called), will be treated
+    as if a crash had ocurred.
+    This may be beneficial if you look for higher-level faulty conditions in which your
+    target still exits gracefully.
+
   - Outdated environment variables that are not supported anymore:
     `AFL_DEFER_FORKSRV`
     `AFL_PERSISTENT`
diff --git a/docs/life_pro_tips.md b/docs/life_pro_tips.md
index 323f16f1..77845c63 100644
--- a/docs/life_pro_tips.md
+++ b/docs/life_pro_tips.md
@@ -78,10 +78,10 @@ Be sure to check out docs/sister_projects.md before writing your own.
 
 ## Need to fuzz the command-line arguments of a particular program?
 
-You can find a simple solution in examples/argv_fuzzing.
+You can find a simple solution in utils/argv_fuzzing.
 
 ## Attacking a format that uses checksums? 
 
 Remove the checksum-checking code or use a postprocessor!
-See examples/custom_mutators/ for more.
+See utils/custom_mutators/ for more.
 
diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md
index 2e18c15f..f08ae3fb 100644
--- a/docs/notes_for_asan.md
+++ b/docs/notes_for_asan.md
@@ -20,7 +20,7 @@ Because of this, fuzzing with ASAN is recommended only in four scenarios:
     - Precisely gauge memory needs using http://jwilk.net/software/recidivm .
 
     - Limit the memory available to process using cgroups on Linux (see
-      examples/asan_cgroups).
+      utils/asan_cgroups).
 
 To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The
 afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags.
@@ -74,7 +74,7 @@ There are also cgroups, but they are Linux-specific, not universally available
 even on Linux systems, and they require root permissions to set up; I'm a bit
 hesitant to make afl-fuzz require root permissions just for that. That said,
 if you are on Linux and want to use cgroups, check out the contributed script
-that ships in examples/asan_cgroups/.
+that ships in utils/asan_cgroups/.
 
 In settings where cgroups aren't available, we have no nice, portable way to
 avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for
diff --git a/docs/parallel_fuzzing.md b/docs/parallel_fuzzing.md
index bf57ace8..8f2afe1b 100644
--- a/docs/parallel_fuzzing.md
+++ b/docs/parallel_fuzzing.md
@@ -152,7 +152,7 @@ write a simple script that performs two actions:
     done
     ```
 
-There is an example of such a script in examples/distributed_fuzzing/.
+There is an example of such a script in utils/distributed_fuzzing/.
 
 There are other (older) more featured, experimental tools:
   * https://github.com/richo/roving
diff --git a/examples/afl_untracer/libtestinstr.so b/examples/afl_untracer/libtestinstr.so
deleted file mode 100755
index 389a946c..00000000
--- a/examples/afl_untracer/libtestinstr.so
+++ /dev/null
Binary files differdiff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index c355263b..2f2d31d3 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -113,6 +113,7 @@
     #include <kstat.h>
     #include <sys/sysinfo.h>
     #include <sys/pset.h>
+    #include <strings.h>
   #endif
 #endif                                                         /* __linux__ */
 
@@ -143,8 +144,8 @@ struct queue_entry {
   u8 *fname;                            /* File name for the test case      */
   u32 len;                              /* Input length                     */
 
-  u8 cal_failed,                        /* Calibration failed?              */
-      trim_done,                        /* Trimmed?                         */
+  u8   cal_failed;                      /* Calibration failed?              */
+  bool trim_done,                       /* Trimmed?                         */
       was_fuzzed,                       /* historical, but needed for MOpt  */
       passed_det,                       /* Deterministic stages passed?     */
       has_new_cov,                      /* Triggers new coverage?           */
@@ -167,7 +168,8 @@ struct queue_entry {
   u8 *trace_mini;                       /* Trace bytes, if kept             */
   u32 tc_ref;                           /* Trace bytes ref count            */
 
-  double perf_score;                    /* performance score                */
+  double perf_score,                    /* performance score                */
+      weight;
 
   u8 *testcase_buf;                     /* The testcase buffer, if loaded.  */
 
@@ -311,6 +313,7 @@ enum {
   /* 10 */ PY_FUNC_QUEUE_GET,
   /* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
   /* 12 */ PY_FUNC_INTROSPECTION,
+  /* 13 */ PY_FUNC_DESCRIBE,
   PY_FUNC_COUNT
 
 };
@@ -325,8 +328,7 @@ typedef struct py_mutator {
   u8 *   fuzz_buf;
   size_t fuzz_size;
 
-  u8 *   post_process_buf;
-  size_t post_process_size;
+  Py_buffer post_process_buf;
 
   u8 *   trim_buf;
   size_t trim_size;
@@ -362,13 +364,14 @@ typedef struct afl_env_vars {
   u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
       afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
       afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
-      afl_bench_until_crash, afl_debug_child_output, afl_autoresume,
-      afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd;
+      afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
+      afl_cycle_schedules, afl_expand_havoc, afl_statsd;
 
   u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
       *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
       *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
-      *afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries;
+      *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
+      *afl_testcache_entries;
 
 } afl_env_vars_t;
 
@@ -754,7 +757,7 @@ struct custom_mutator {
    * When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can
    * also give introspection information back with this function.
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @return pointer to a text string (const char*)
    */
   const char *(*afl_custom_introspection)(void *data);
@@ -770,7 +773,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param buf Buffer containing the test case
    * @param buf_size Size of the test case
    * @return The amount of fuzzes to perform on this queue entry, 0 = skip
@@ -782,7 +785,7 @@ struct custom_mutator {
    *
    * (Optional for now. Required in the future)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param[in] buf Pointer to the input data to be mutated and the mutated
    *     output
    * @param[in] buf_size Size of the input/output data
@@ -798,13 +801,28 @@ struct custom_mutator {
                             u8 *add_buf, size_t add_buf_size, size_t max_size);
 
   /**
+   * Describe the current testcase, generated by the last mutation.
+   * This will be called, for example, to give the written testcase a name
+   * after a crash ocurred. It can help to reproduce crashing mutations.
+   *
+   * (Optional)
+   *
+   * @param data pointer returned by afl_customm_init for this custom mutator
+   * @paramp[in] max_description_len maximum size avaliable for the description.
+   *             A longer return string is legal, but will be truncated.
+   * @return A valid ptr to a 0-terminated string.
+   *         An empty or NULL return will result in a default description
+   */
+  const char *(*afl_custom_describe)(void *data, size_t max_description_len);
+
+  /**
    * A post-processing function to use right before AFL writes the test case to
    * disk in order to execute the target.
    *
    * (Optional) If this functionality is not needed, simply don't define this
    * function.
    *
-   * @param[in] data pointer returned in afl_custom_init for this fuzz case
+   * @param[in] data pointer returned in afl_custom_init by this custom mutator
    * @param[in] buf Buffer containing the test case to be executed
    * @param[in] buf_size Size of the test case
    * @param[out] out_buf Pointer to the buffer storing the test case after
@@ -831,7 +849,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param buf Buffer containing the test case
    * @param buf_size Size of the test case
    * @return The amount of possible iteration steps to trim the input.
@@ -850,7 +868,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param[out] out_buf Pointer to the buffer containing the trimmed test case.
    *             The library can reuse a buffer for each call
    *             and will have to free the buf (for example in deinit)
@@ -865,7 +883,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param success Indicates if the last trim operation was successful.
    * @return The next trim iteration index (from 0 to the maximum amount of
    *     steps returned in init_trim). Negative on error.
@@ -878,7 +896,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param[in] data pointer returned in afl_custom_init for this fuzz case
+   * @param[in] data pointer returned in afl_custom_init by this custom mutator
    * @param[in] buf Pointer to the input data to be mutated and the mutated
    *     output
    * @param[in] buf_size Size of input data
@@ -897,7 +915,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @return The probability (0-100).
    */
   u8 (*afl_custom_havoc_mutation_probability)(void *data);
@@ -907,7 +925,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param filename File name of the test case in the queue entry
    * @return Return True(1) if the fuzzer will fuzz the queue entry, and
    *     False(0) otherwise.
@@ -920,7 +938,7 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    * @param filename_new_queue File name of the new queue entry
    * @param filename_orig_queue File name of the original queue entry. This
    *     argument can be NULL while initializing the fuzzer
@@ -930,7 +948,7 @@ struct custom_mutator {
   /**
    * Deinitialize the custom mutator.
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param data pointer returned in afl_custom_init by this custom mutator
    */
   void (*afl_custom_deinit)(void *data);
 
@@ -1006,7 +1024,7 @@ void classify_counts(afl_forkserver_t *);
 void init_count_class16(void);
 void minimize_bits(afl_state_t *, u8 *, u8 *);
 #ifndef SIMPLE_FILES
-u8 *describe_op(afl_state_t *, u8);
+u8 *describe_op(afl_state_t *, u8, size_t);
 #endif
 u8 save_if_interesting(afl_state_t *, void *, u32, u8);
 u8 has_new_bits(afl_state_t *, u8 *);
diff --git a/include/alloc-inl.h b/include/alloc-inl.h
index d7aa51a7..68255fb6 100644
--- a/include/alloc-inl.h
+++ b/include/alloc-inl.h
@@ -636,7 +636,7 @@ struct afl_alloc_buf {
 
 #define AFL_ALLOC_SIZE_OFFSET (offsetof(struct afl_alloc_buf, buf))
 
-/* Returs the container element to this ptr */
+/* Returns the container element to this ptr */
 static inline struct afl_alloc_buf *afl_alloc_bufptr(void *buf) {
 
   return (struct afl_alloc_buf *)((u8 *)buf - AFL_ALLOC_SIZE_OFFSET);
@@ -694,12 +694,18 @@ static inline void *afl_realloc(void **buf, size_t size_needed) {
   }
 
   /* alloc */
-  new_buf = (struct afl_alloc_buf *)realloc(new_buf, next_size);
-  if (unlikely(!new_buf)) {
+  struct afl_alloc_buf *newer_buf =
+      (struct afl_alloc_buf *)realloc(new_buf, next_size);
+  if (unlikely(!newer_buf)) {
 
+    free(new_buf);  // avoid a leak
     *buf = NULL;
     return NULL;
 
+  } else {
+
+    new_buf = newer_buf;
+
   }
 
   new_buf->complete_size = next_size;
@@ -730,12 +736,18 @@ static inline void *afl_realloc_exact(void **buf, size_t size_needed) {
   if (unlikely(current_size == size_needed)) { return *buf; }
 
   /* alloc */
-  new_buf = (struct afl_alloc_buf *)realloc(new_buf, size_needed);
-  if (unlikely(!new_buf)) {
+  struct afl_alloc_buf *newer_buf =
+      (struct afl_alloc_buf *)realloc(new_buf, size_needed);
+  if (unlikely(!newer_buf)) {
 
+    free(new_buf);  // avoid a leak
     *buf = NULL;
     return NULL;
 
+  } else {
+
+    new_buf = newer_buf;
+
   }
 
   new_buf->complete_size = size_needed;
diff --git a/include/common.h b/include/common.h
index c364ade0..125c3abf 100644
--- a/include/common.h
+++ b/include/common.h
@@ -31,14 +31,14 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <stdbool.h>
 #include "types.h"
-#include "stdbool.h"
 
 /* STRINGIFY_VAL_SIZE_MAX will fit all stringify_ strings. */
 
 #define STRINGIFY_VAL_SIZE_MAX (16)
 
-void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin);
+void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin);
 void check_environment_vars(char **env);
 
 char **argv_cpy_dup(int argc, char **argv);
diff --git a/include/debug.h b/include/debug.h
index e6d3c3fc..5512023c 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -270,6 +270,16 @@
                            \
   } while (0)
 
+/* Show a prefixed debug output. */
+
+#define DEBUGF(x...)                         \
+  do {                                       \
+                                             \
+    SAYF(cMGN "[D] " cBRI "DEBUG: " cRST x); \
+    SAYF(cRST "");                           \
+                                             \
+  } while (0)
+
 /* Error-checking versions of read() and write() that call RPFATAL() as
    appropriate. */
 
diff --git a/include/envs.h b/include/envs.h
index b753d5f8..c0f41ca5 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -6,6 +6,7 @@ static char *afl_environment_deprecated[] = {
 
     "AFL_LLVM_WHITELIST",
     "AFL_GCC_WHITELIST",
+    "AFL_DEBUG_CHILD_OUTPUT",
     "AFL_DEFER_FORKSRV",
     "AFL_POST_LIBRARY",
     "AFL_PERSISTENT",
@@ -31,12 +32,13 @@ static char *afl_environment_variables[] = {
     "AFL_CODE_START",
     "AFL_COMPCOV_BINNAME",
     "AFL_COMPCOV_LEVEL",
+    "AFL_CRASH_EXITCODE",
     "AFL_CUSTOM_MUTATOR_LIBRARY",
     "AFL_CUSTOM_MUTATOR_ONLY",
     "AFL_CXX",
     "AFL_CYCLE_SCHEDULES",
     "AFL_DEBUG",
-    "AFL_DEBUG_CHILD_OUTPUT",
+    "AFL_DEBUG_CHILD",
     "AFL_DEBUG_GDB",
     "AFL_DISABLE_TRIM",
     "AFL_DONT_OPTIMIZE",
@@ -99,6 +101,7 @@ static char *afl_environment_variables[] = {
     "AFL_LLVM_LTO_STARTID",
     "AFL_LLVM_LTO_DONTWRITEID",
     "AFL_NO_ARITH",
+    "AFL_NO_AUTODICT",
     "AFL_NO_BUILTIN",
     "AFL_NO_CPU_RED",
     "AFL_NO_FORKSRV",
@@ -123,6 +126,7 @@ static char *afl_environment_variables[] = {
     "AFL_QEMU_PERSISTENT_CNT",
     "AFL_QEMU_PERSISTENT_GPR",
     "AFL_QEMU_PERSISTENT_HOOK",
+    "AFL_QEMU_PERSISTENT_MEM",
     "AFL_QEMU_PERSISTENT_RET",
     "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
     "AFL_QEMU_PERSISTENT_EXITS",
diff --git a/include/forkserver.h b/include/forkserver.h
index 300ecffc..5d5c728f 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -37,9 +37,7 @@ typedef struct afl_forkserver {
 
   /* a program that includes afl-forkserver needs to define these */
 
-  u8  uses_asan;                        /* Target uses ASAN?                */
   u8 *trace_bits;                       /* SHM with instrumentation bitmap  */
-  u8  use_stdin;                        /* use stdin for sending data       */
 
   s32 fsrv_pid,                         /* PID of the fork server           */
       child_pid,                        /* PID of the fuzzed program        */
@@ -53,8 +51,6 @@ typedef struct afl_forkserver {
       fsrv_ctl_fd,                      /* Fork server control pipe (write) */
       fsrv_st_fd;                       /* Fork server status pipe (read)   */
 
-  u8 no_unlink;                         /* do not unlink cur_input          */
-
   u32 exec_tmout;                       /* Configurable exec timeout (ms)   */
   u32 init_tmout;                       /* Configurable init timeout (ms)   */
   u32 map_size;                         /* map size used by the target      */
@@ -73,13 +69,22 @@ typedef struct afl_forkserver {
 
   u8 last_kill_signal;                  /* Signal that killed the child     */
 
-  u8 use_shmem_fuzz;                    /* use shared mem for test cases    */
+  bool use_shmem_fuzz;                  /* use shared mem for test cases    */
+
+  bool support_shmem_fuzz;              /* set by afl-fuzz                  */
+
+  bool use_fauxsrv;                     /* Fauxsrv for non-forking targets? */
+
+  bool qemu_mode;                       /* if running in qemu mode or not   */
+
+  bool use_stdin;                       /* use stdin for sending data       */
 
-  u8 support_shmem_fuzz;                /* set by afl-fuzz                  */
+  bool no_unlink;                       /* do not unlink cur_input          */
 
-  u8 use_fauxsrv;                       /* Fauxsrv for non-forking targets? */
+  bool uses_asan;                       /* Target uses ASAN?                */
 
-  u8 qemu_mode;                         /* if running in qemu mode or not   */
+  bool uses_crash_exitcode;             /* Custom crash exitcode specified? */
+  u8   crash_exitcode;                  /* The crash exitcode specified     */
 
   u32 *shmem_fuzz_len;                  /* length of the fuzzing test case  */
 
diff --git a/instrumentation/LLVMInsTrim.so.cc b/instrumentation/LLVMInsTrim.so.cc
index 61a420ba..6b3231e6 100644
--- a/instrumentation/LLVMInsTrim.so.cc
+++ b/instrumentation/LLVMInsTrim.so.cc
@@ -268,8 +268,8 @@ struct InsTrim : public ModulePass {
 
         for (auto &BB : F)
           if (BB.size() > 0) ++bb_cnt;
-        SAYF(cMGN "[D] " cRST "Function %s size %zu %u\n",
-             F.getName().str().c_str(), F.size(), bb_cnt);
+        DEBUGF("Function %s size %zu %u\n", F.getName().str().c_str(), F.size(),
+               bb_cnt);
 
       }
 
diff --git a/instrumentation/README.gcc_plugin.md b/instrumentation/README.gcc_plugin.md
index 919801d1..12449efd 100644
--- a/instrumentation/README.gcc_plugin.md
+++ b/instrumentation/README.gcc_plugin.md
@@ -147,7 +147,7 @@ The numerical value specified within the loop controls the maximum number
 of iterations before AFL will restart the process from scratch. This minimizes
 the impact of memory leaks and similar glitches; 1000 is a good starting point.
 
-A more detailed template is shown in ../examples/persistent_demo/.
+A more detailed template is shown in ../utils/persistent_mode/.
 Similarly to the previous mode, the feature works only with afl-gcc-fast or
 afl-clang-fast; #ifdef guards can be used to suppress it when using other
 compilers.
diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md
index abdbd2ac..a2814173 100644
--- a/instrumentation/README.lto.md
+++ b/instrumentation/README.lto.md
@@ -60,7 +60,12 @@ AUTODICTIONARY: 11 strings found
 
 ## Getting llvm 11+
 
-### Installing llvm from the llvm repository (version 11)
+### Installing llvm version 11
+
+llvm 11 should be available in all current Linux repositories.
+If you use an outdated Linux distribution read the next section.
+
+### Installing llvm from the llvm repository (version 12)
 
 Installing the llvm snapshot builds is easy and mostly painless:
 
@@ -73,11 +78,11 @@ then add the pgp key of llvm and install the packages:
 ```
 wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - 
 apt-get update && apt-get upgrade -y
-apt-get install -y clang-11 clang-tools-11 libc++1-11 libc++-11-dev \
-    libc++abi1-11 libc++abi-11-dev libclang1-11 libclang-11-dev \
-    libclang-common-11-dev libclang-cpp11 libclang-cpp11-dev liblld-11 \
-    liblld-11-dev liblldb-11 liblldb-11-dev libllvm11 libomp-11-dev \
-    libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools
+apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
+    libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
+    libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
+    liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \
+    libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools
 ```
 
 ### Building llvm yourself (version 12)
@@ -120,16 +125,22 @@ While compiling, a dictionary based on string comparisons is automatically
 generated and put into the target binary. This dictionary is transfered to afl-fuzz
 on start. This improves coverage statistically by 5-10% :)
 
+Note that if for any reason you do not want to use the autodictionary feature
+then just set the environment variable `AFL_NO_AUTODICT` when starting afl-fuzz.
+
 ## Fixed memory map
 
-To speed up fuzzing, it is possible to set a fixed shared memory map.
+To speed up fuzzing a little bit more, it is possible to set a fixed shared
+memory map.
 Recommended 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).
+
+Also on unusual operating systems/processors/kernels or weird libraries the
+recommended 0x10000 address might not work, so then change the fixed address.
+
+To enable this feature set AFL_LLVM_MAP_ADDR with the address.
 
 ## Document edge IDs
 
diff --git a/instrumentation/README.persistent_mode.md b/instrumentation/README.persistent_mode.md
index e095f036..2cf76adf 100644
--- a/instrumentation/README.persistent_mode.md
+++ b/instrumentation/README.persistent_mode.md
@@ -11,7 +11,7 @@ and that its state can be resetted so that multiple calls can be performed
 without resource leaks and former runs having no impact on following runs
 (this can be seen by the `stability` indicator in the `afl-fuzz` UI).
 
-Examples can be found in [examples/persistent_mode](../examples/persistent_mode).
+Examples can be found in [utils/persistent_mode](../utils/persistent_mode).
 
 ## 2) TLDR;
 
@@ -23,15 +23,20 @@ __AFL_FUZZ_INIT();
 
 main() {
 
+  // anything else here, eg. command line arguments, initialization, etc.
+
 #ifdef __AFL_HAVE_MANUAL_CONTROL
   __AFL_INIT();
 #endif
 
   unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;  // must be after __AFL_INIT
+                                                 // and before __AFL_LOOP!
 
   while (__AFL_LOOP(10000)) {
 
-    int len = __AFL_FUZZ_TESTCASE_LEN;
+    int len = __AFL_FUZZ_TESTCASE_LEN;  // don't use the macro directly in a
+                                        // call!
+
     if (len < 8) continue;  // check for a required/useful minimum input length
 
     /* Setup function call, e.g. struct target *tmp = libtarget_init() */
@@ -110,37 +115,13 @@ With the location selected, add this code in the appropriate spot:
 ```
 
 You don't need the #ifdef guards, but including them ensures that the program
-will keep working normally when compiled with a tool other than afl-clang-fast.
-
-Finally, recompile the program with afl-clang-fast/lto (afl-gcc or afl-clang will
-*not* generate a deferred-initialization binary) - and you should be all set!
+will keep working normally when compiled with a tool other than afl-clang-fast/
+afl-clang-lto/afl-gcc-fast.
 
-*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:
+Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
+(afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
+and you should be all set!
 
-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
 
@@ -169,7 +150,7 @@ the impact of memory leaks and similar glitches; 1000 is a good starting point,
 and going much higher increases the likelihood of hiccups without giving you
 any real performance benefits.
 
-A more detailed template is shown in ../examples/persistent_demo/.
+A more detailed template is shown in ../utils/persistent_mode/.
 Similarly to the previous mode, the feature works only with afl-clang-fast; #ifdef
 guards can be used to suppress it when using other compilers.
 
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index b3c55108..102b44a4 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -544,7 +544,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
     be_quiet = 1;
 
   skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
-  // scanForDangerousFunctions(&M);
+
+  initInstrumentList();
+  scanForDangerousFunctions(&M);
 
   if (debug) {
 
@@ -819,6 +821,8 @@ void ModuleSanitizerCoverage::instrumentFunction(
     Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   if (F.empty()) return;
+  if (!isInInstrumentList(&F)) return;
+
   if (F.getName().find(".module_ctor") != std::string::npos)
     return;  // Should not instrument sanitizer init functions.
   if (F.getName().startswith("__sanitizer_"))
@@ -1123,11 +1127,11 @@ void ModuleSanitizerCoverage::InjectTraceForCmp(
       Value *     A1 = ICMP->getOperand(1);
       if (!A0->getType()->isIntegerTy()) continue;
       uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());
-      int      CallbackIdx =
-          TypeSize == 8
-              ? 0
-              : TypeSize == 16 ? 1
-                               : TypeSize == 32 ? 2 : TypeSize == 64 ? 3 : -1;
+      int      CallbackIdx = TypeSize == 8    ? 0
+                             : TypeSize == 16 ? 1
+                             : TypeSize == 32 ? 2
+                             : TypeSize == 64 ? 3
+                                              : -1;
       if (CallbackIdx < 0) continue;
       // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
       auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
@@ -1315,6 +1319,7 @@ std::string ModuleSanitizerCoverage::getSectionEnd(
 }
 
 char ModuleSanitizerCoverageLegacyPass::ID = 0;
+
 INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
                       "Pass for instrumenting coverage on functions", false,
                       false)
@@ -1323,6 +1328,7 @@ INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
 INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
                     "Pass for instrumenting coverage on functions", false,
                     false)
+
 ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
     const SanitizerCoverageOptions &Options,
     const std::vector<std::string> &AllowlistFiles,
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 864f5bb6..32e4da85 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -101,6 +101,11 @@ int __afl_sharedmem_fuzzing __attribute__((weak));
 
 struct cmp_map *__afl_cmp_map;
 
+/* Child pid? */
+
+static s32 child_pid;
+static void (*old_sigterm_handler)(int) = 0;
+
 /* Running in persistent mode? */
 
 static u8 is_persistent;
@@ -109,6 +114,14 @@ static u8 is_persistent;
 
 static u8 _is_sancov;
 
+/* ensure we kill the child on termination */
+
+void at_exit(int signal) {
+
+  if (child_pid > 0) { kill(child_pid, SIGKILL); }
+
+}
+
 /* Uninspired gcc plugin instrumentation */
 
 void __afl_trace(const u32 x) {
@@ -150,6 +163,12 @@ static void __afl_map_shm_fuzz() {
 
   char *id_str = getenv(SHM_FUZZ_ENV_VAR);
 
+  if (getenv("AFL_DEBUG")) {
+
+    fprintf(stderr, "DEBUG: fuzzcase shmem %s\n", id_str ? id_str : "none");
+
+  }
+
   if (id_str) {
 
     u8 *map = NULL;
@@ -182,7 +201,8 @@ static void __afl_map_shm_fuzz() {
 
     if (!map || map == (void *)-1) {
 
-      perror("Could not access fuzzign shared memory");
+      perror("Could not access fuzzing shared memory");
+      send_forkserver_error(FS_ERROR_SHM_OPEN);
       exit(1);
 
     }
@@ -199,6 +219,7 @@ static void __afl_map_shm_fuzz() {
   } else {
 
     fprintf(stderr, "Error: variable for fuzzing shared memory is not set\n");
+    send_forkserver_error(FS_ERROR_SHM_OPEN);
     exit(1);
 
   }
@@ -322,6 +343,8 @@ static void __afl_map_shm(void) {
         send_forkserver_error(FS_ERROR_MAP_ADDR);
       else
         send_forkserver_error(FS_ERROR_MMAP);
+      perror("mmap for map");
+
       exit(2);
 
     }
@@ -332,20 +355,22 @@ static void __afl_map_shm(void) {
 
     __afl_area_ptr = shmat(shm_id, (void *)__afl_map_addr, 0);
 
-#endif
-
     /* Whooooops. */
 
-    if (__afl_area_ptr == (void *)-1) {
+    if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) {
 
       if (__afl_map_addr)
         send_forkserver_error(FS_ERROR_MAP_ADDR);
       else
         send_forkserver_error(FS_ERROR_SHMAT);
+
+      perror("shmat for map");
       _exit(1);
 
     }
 
+#endif
+
     /* Write something into the bitmap so that even with low AFL_INST_RATIO,
        our parent doesn't give up on us. */
 
@@ -363,6 +388,7 @@ static void __afl_map_shm(void) {
 
       fprintf(stderr, "can not acquire mmap for address %p\n",
               (void *)__afl_map_addr);
+      send_forkserver_error(FS_ERROR_SHM_OPEN);
       exit(1);
 
     }
@@ -397,7 +423,8 @@ static void __afl_map_shm(void) {
     shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
     if (shm_fd == -1) {
 
-      fprintf(stderr, "shm_open() failed\n");
+      perror("shm_open() failed\n");
+      send_forkserver_error(FS_ERROR_SHM_OPEN);
       exit(1);
 
     }
@@ -411,6 +438,7 @@ static void __afl_map_shm(void) {
       shm_fd = -1;
 
       fprintf(stderr, "mmap() failed\n");
+      send_forkserver_error(FS_ERROR_SHM_OPEN);
       exit(2);
 
     }
@@ -422,7 +450,13 @@ static void __afl_map_shm(void) {
     __afl_cmp_map = shmat(shm_id, NULL, 0);
 #endif
 
-    if (__afl_cmp_map == (void *)-1) _exit(1);
+    if (!__afl_cmp_map || __afl_cmp_map == (void *)-1) {
+
+      perror("shmat for cmplog");
+      send_forkserver_error(FS_ERROR_SHM_OPEN);
+      _exit(1);
+
+    }
 
   }
 
@@ -432,7 +466,6 @@ static void __afl_map_shm(void) {
 static void __afl_start_snapshots(void) {
 
   static u8 tmp[4] = {0, 0, 0, 0};
-  s32       child_pid;
   u32       status = 0;
   u32       already_read_first = 0;
   u32       was_killed;
@@ -579,6 +612,7 @@ static void __afl_start_snapshots(void) {
         //(void)nice(-20);  // does not seem to improve
 
         signal(SIGCHLD, old_sigchld_handler);
+        signal(SIGTERM, old_sigterm_handler);
 
         close(FORKSRV_FD);
         close(FORKSRV_FD + 1);
@@ -633,6 +667,11 @@ static void __afl_start_snapshots(void) {
 
 static void __afl_start_forkserver(void) {
 
+  struct sigaction orig_action;
+  sigaction(SIGTERM, NULL, &orig_action);
+  old_sigterm_handler = orig_action.sa_handler;
+  signal(SIGTERM, at_exit);
+
 #ifdef __linux__
   if (/*!is_persistent &&*/ !__afl_cmp_map && !getenv("AFL_NO_SNAPSHOT") &&
       afl_snapshot_init() >= 0) {
@@ -645,7 +684,6 @@ static void __afl_start_forkserver(void) {
 #endif
 
   u8  tmp[4] = {0, 0, 0, 0};
-  s32 child_pid;
   u32 status = 0;
   u32 already_read_first = 0;
   u32 was_killed;
@@ -793,6 +831,7 @@ static void __afl_start_forkserver(void) {
         //(void)nice(-20);
 
         signal(SIGCHLD, old_sigchld_handler);
+        signal(SIGTERM, old_sigterm_handler);
 
         close(FORKSRV_FD);
         close(FORKSRV_FD + 1);
@@ -992,7 +1031,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
   // For stability analysis, if you want to know to which function unstable
   // edge IDs belong - uncomment, recompile+install llvm_mode, recompile
   // the target. libunwind and libbacktrace are better solutions.
-  // Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture
+  // Set AFL_DEBUG_CHILD=1 and run afl-fuzz with 2>file to capture
   // the backtrace output
   /*
   uint32_t unstable[] = { ... unstable edge IDs };
diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc
index f94bb57f..e116e7d1 100644
--- a/instrumentation/afl-gcc-pass.so.cc
+++ b/instrumentation/afl-gcc-pass.so.cc
@@ -627,9 +627,8 @@ struct afl_pass : gimple_opt_pass {
       }
 
       if (debug)
-        SAYF(cMGN "[D] " cRST
-                  "loaded allowlist with %zu file and %zu function entries\n",
-             allowListFiles.size(), allowListFunctions.size());
+        DEBUGF("loaded allowlist with %zu file and %zu function entries\n",
+               allowListFiles.size(), allowListFunctions.size());
 
     }
 
@@ -702,9 +701,8 @@ struct afl_pass : gimple_opt_pass {
       }
 
       if (debug)
-        SAYF(cMGN "[D] " cRST
-                  "loaded denylist with %zu file and %zu function entries\n",
-             denyListFiles.size(), denyListFunctions.size());
+        DEBUGF("loaded denylist with %zu file and %zu function entries\n",
+               denyListFiles.size(), denyListFunctions.size());
 
     }
 
@@ -745,10 +743,10 @@ struct afl_pass : gimple_opt_pass {
             if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
 
               if (debug)
-                SAYF(cMGN "[D] " cRST
-                          "Function %s is in the deny function list, "
-                          "not instrumenting ... \n",
-                     instFunction.c_str());
+                DEBUGF(
+                    "Function %s is in the deny function list, not "
+                    "instrumenting ... \n",
+                    instFunction.c_str());
               return false;
 
             }
@@ -825,10 +823,10 @@ struct afl_pass : gimple_opt_pass {
             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());
+                DEBUGF(
+                    "Function %s is in the allow function list, instrumenting "
+                    "... \n",
+                    instFunction.c_str());
               return true;
 
             }
@@ -859,11 +857,11 @@ struct afl_pass : gimple_opt_pass {
               if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
 
                 if (debug)
-                  SAYF(cMGN "[D] " cRST
-                            "Function %s is in the allowlist (%s), "
-                            "instrumenting ... \n",
-                       IDENTIFIER_POINTER(DECL_NAME(F->decl)),
-                       source_file.c_str());
+                  DEBUGF(
+                      "Function %s is in the allowlist (%s), instrumenting ... "
+                      "\n",
+                      IDENTIFIER_POINTER(DECL_NAME(F->decl)),
+                      source_file.c_str());
                 return true;
 
               }
diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc
index 189b4ec6..21c4d204 100644
--- a/instrumentation/afl-llvm-common.cc
+++ b/instrumentation/afl-llvm-common.cc
@@ -173,9 +173,8 @@ void initInstrumentList() {
     }
 
     if (debug)
-      SAYF(cMGN "[D] " cRST
-                "loaded allowlist with %zu file and %zu function entries\n",
-           allowListFiles.size(), allowListFunctions.size());
+      DEBUGF("loaded allowlist with %zu file and %zu function entries\n",
+             allowListFiles.size(), allowListFunctions.size());
 
   }
 
@@ -248,9 +247,8 @@ void initInstrumentList() {
     }
 
     if (debug)
-      SAYF(cMGN "[D] " cRST
-                "loaded denylist with %zu file and %zu function entries\n",
-           denyListFiles.size(), denyListFunctions.size());
+      DEBUGF("loaded denylist with %zu file and %zu function entries\n",
+             denyListFiles.size(), denyListFunctions.size());
 
   }
 
@@ -409,10 +407,10 @@ bool isInInstrumentList(llvm::Function *F) {
           if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
 
             if (debug)
-              SAYF(cMGN "[D] " cRST
-                        "Function %s is in the deny function list, "
-                        "not instrumenting ... \n",
-                   instFunction.c_str());
+              DEBUGF(
+                  "Function %s is in the deny function list, not instrumenting "
+                  "... \n",
+                  instFunction.c_str());
             return false;
 
           }
@@ -489,10 +487,10 @@ bool isInInstrumentList(llvm::Function *F) {
           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());
+              DEBUGF(
+                  "Function %s is in the allow function list, instrumenting "
+                  "... \n",
+                  instFunction.c_str());
             return true;
 
           }
@@ -523,10 +521,10 @@ bool isInInstrumentList(llvm::Function *F) {
             if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
 
               if (debug)
-                SAYF(cMGN "[D] " cRST
-                          "Function %s is in the allowlist (%s), "
-                          "instrumenting ... \n",
-                     F->getName().str().c_str(), source_file.c_str());
+                DEBUGF(
+                    "Function %s is in the allowlist (%s), instrumenting ... "
+                    "\n",
+                    F->getName().str().c_str(), source_file.c_str());
               return true;
 
             }
diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
index a7331444..416dbb88 100644
--- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
@@ -105,15 +105,14 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
     if (isInInstrumentList(&F)) {
 
       if (debug)
-        SAYF(cMGN "[D] " cRST "function %s is in the instrument file list\n",
-             F.getName().str().c_str());
+        DEBUGF("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());
+        DEBUGF("function %s is NOT in the instrument file list\n",
+               F.getName().str().c_str());
 
       auto &        Ctx = F.getContext();
       AttributeList Attrs = F.getAttributes();
diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc
index 3f05dd97..33a87719 100644
--- a/instrumentation/split-compares-pass.so.cc
+++ b/instrumentation/split-compares-pass.so.cc
@@ -601,15 +601,12 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     if (op_size != op1->getType()->getPrimitiveSizeInBits()) { continue; }
 
     const unsigned int sizeInBits = op0->getType()->getPrimitiveSizeInBits();
-    const unsigned int precision =
-        sizeInBits == 32
-            ? 24
-            : sizeInBits == 64
-                  ? 53
-                  : sizeInBits == 128 ? 113
-                                      : sizeInBits == 16 ? 11
-                                                         /* sizeInBits == 80 */
-                                                         : 65;
+    const unsigned int precision = sizeInBits == 32    ? 24
+                                   : sizeInBits == 64  ? 53
+                                   : sizeInBits == 128 ? 113
+                                   : sizeInBits == 16  ? 11
+                                                      /* sizeInBits == 80 */
+                                                      : 65;
 
     const unsigned           shiftR_exponent = precision - 1;
     const unsigned long long mask_fraction =
diff --git a/libdislocator/README.md b/libdislocator/README.md
index 873d8806..1785463e 100644
--- a/libdislocator/README.md
+++ b/libdislocator/README.md
@@ -1,6 +1,6 @@
 # libdislocator, an abusive allocator
 
-  (See ../docs/README.md for the general instruction manual.)
+  (See ../README.md for the general instruction manual.)
 
 This is a companion library that can be used as a drop-in replacement for the
 libc allocator in the fuzzed binaries. It improves the odds of bumping into
diff --git a/libtokencap/README.md b/libtokencap/README.md
index 0a3591eb..13a440da 100644
--- a/libtokencap/README.md
+++ b/libtokencap/README.md
@@ -1,6 +1,6 @@
 # strcmp() / memcmp() token capture library
 
-  (See ../docs/README.md for the general instruction manual.)
+  (See ../README.md for the general instruction manual.)
 
 This companion library allows you to instrument `strcmp()`, `memcmp()`,
 and related functions to automatically extract syntax tokens passed to any of
diff --git a/qbdi_mode/template.cpp b/qbdi_mode/template.cpp
index 55c5a3f3..b2066cc8 100755
--- a/qbdi_mode/template.cpp
+++ b/qbdi_mode/template.cpp
@@ -44,7 +44,7 @@ target_func              p_target_func = NULL;
 rword                    module_base = 0;
 rword                    module_end = 0;
 static unsigned char
-               dummy[MAP_SIZE]; /* costs MAP_SIZE but saves a few instructions */
+    dummy[MAP_SIZE];         /* costs MAP_SIZE but saves a few instructions */
 unsigned char *afl_area_ptr = NULL;           /* Exported for afl_gen_trace */
 
 unsigned long afl_prev_loc = 0;
diff --git a/qemu_mode/README.md b/qemu_mode/README.md
index 1c5d240c..9818846d 100644
--- a/qemu_mode/README.md
+++ b/qemu_mode/README.md
@@ -1,6 +1,6 @@
 # High-performance binary-only instrumentation for afl-fuzz
 
-  (See ../docs/README.md for the general instruction manual.)
+  (See ../README.md for the general instruction manual.)
 
 ## 1) Introduction
 
@@ -179,7 +179,7 @@ match.
 ## 12) Gotchas, feedback, bugs
 
 If you need to fix up checksums or do other cleanup on mutated test cases, see
-examples/custom_mutators/ for a viable solution.
+utils/custom_mutators/ for a viable solution.
 
 Do not mix QEMU mode with ASAN, MSAN, or the likes; QEMU doesn't appreciate
 the "shadow VM" trick employed by the sanitizers and will probably just
diff --git a/qemu_mode/README.persistent.md b/qemu_mode/README.persistent.md
index d9e7e1cc..2ca5c873 100644
--- a/qemu_mode/README.persistent.md
+++ b/qemu_mode/README.persistent.md
@@ -172,4 +172,4 @@ and so the input_buf variables of the hook becomes meaningful. Otherwise,
 you have to read the input from a file like stdin.
 
 An example that you can use with little modification for your target can
-be found here: [examples/qemu_persistent_hook](../examples/qemu_persistent_hook)
+be found here: [utils/qemu_persistent_hook](../utils/qemu_persistent_hook)
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index 683026bb..c24cc995 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -114,7 +114,7 @@ git status 1>/dev/null 2>/dev/null
 if [ $? -eq 0 ]; then
   echo "[*] initializing qemuafl submodule"
   git submodule init || exit 1
-  git submodule update 2>/dev/null # ignore errors
+  git submodule update ./qemuafl 2>/dev/null # ignore errors
 else
   echo "[*] cloning qemuafl"
   test -d qemuafl || {
diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl
-Subproject d66c9e2654efa8939f0fe6995d11a72b98a4da3
+Subproject 21ff34383764a8c6f66509b3b8d5282468c721e
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index c8acebb3..2780deff 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -78,9 +78,9 @@ static u64 mem_limit = MEM_LIMIT;      /* Memory limit (MB)                 */
 
 static s32 dev_null_fd = -1;           /* FD to /dev/null                   */
 
-static u8 edges_only,                  /* Ignore hit counts?                */
+static bool edges_only,                  /* Ignore hit counts?              */
     use_hex_offsets,                   /* Show hex offsets?                 */
-    use_stdin = 1;                     /* Use stdin for program input?      */
+    use_stdin = true;                     /* Use stdin for program input?   */
 
 static volatile u8 stop_soon,          /* Ctrl-C pressed?                   */
     child_timed_out;                   /* Child timed out?                  */
diff --git a/src/afl-as.c b/src/afl-as.c
index 7d70bfcd..3d6f7d5e 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -27,7 +27,7 @@
    utility has right now is to be able to skip them gracefully and allow the
    compilation process to continue.
 
-   That said, see examples/clang_asm_normalize/ for a solution that may
+   That said, see utils/clang_asm_normalize/ for a solution that may
    allow clang users to make things work even with hand-crafted assembly. Just
    note that there is no equivalent for GCC.
 
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 771a58f5..273a9f2f 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -48,15 +48,16 @@
 static u8 * obj_path;                  /* Path to runtime libraries         */
 static u8 **cc_params;                 /* Parameters passed to the real CC  */
 static u32  cc_par_cnt = 1;            /* Param count, including argv0      */
+static u8   clang_mode;                /* Invoked as afl-clang*?            */
 static u8   llvm_fullpath[PATH_MAX];
-static u8   instrument_mode, instrument_opt_mode, ngram_size, lto_mode,
-    compiler_mode, plusplus_mode;
-static u8  have_gcc, have_llvm, have_gcc_plugin, have_lto;
-static u8 *lto_flag = AFL_CLANG_FLTO, *argvnull;
-static u8  debug;
-static u8  cwd[4096];
-static u8  cmplog_mode;
-u8         use_stdin;                                              /* dummy */
+static u8   instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
+static u8   compiler_mode, plusplus_mode, have_instr_env = 0;
+static u8   have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0;
+static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
+static u8   debug;
+static u8   cwd[4096];
+static u8   cmplog_mode;
+u8          use_stdin;                                             /* dummy */
 // static u8 *march_opt = CFLAGS_OPT;
 
 enum {
@@ -105,20 +106,43 @@ u8 *getthecwd() {
 
 }
 
-/* Try to find the runtime libraries. If that fails, abort. */
+/* Try to find a specific runtime we need, returns NULL on fail. */
+
+/*
+  in find_object() we look here:
+
+  1. if obj_path is already set we look there first
+  2. then we check the $AFL_PATH environment variable location if set
+  3. next we check argv[0] if it has path information and use it
+    a) we also check ../lib/afl
+  4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and
+     FreeBSD with procfs)
+    a) and check here in ../lib/afl too
+  5. we look into the AFL_PATH define (usually /usr/local/lib/afl)
+  6. we finally try the current directory
+
+  if all these attempts fail - we return NULL and the caller has to decide
+  what to do.
+*/
 
 static u8 *find_object(u8 *obj, u8 *argv0) {
 
   u8 *afl_path = getenv("AFL_PATH");
   u8 *slash = NULL, *tmp;
 
+  if (obj_path) {
+
+    tmp = alloc_printf("%s/%s", obj_path, obj);
+
+    if (!access(tmp, R_OK)) { return tmp; }
+
+    ck_free(tmp);
+
+  }
+
   if (afl_path) {
 
-#ifdef __ANDROID__
     tmp = alloc_printf("%s/%s", afl_path, obj);
-#else
-    tmp = alloc_printf("%s/%s", afl_path, obj);
-#endif
 
     if (!access(tmp, R_OK)) {
 
@@ -131,125 +155,127 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
 
   }
 
-  if (argv0) slash = strrchr(argv0, '/');
+  if (argv0) {
 
-  if (slash) {
+    slash = strrchr(argv0, '/');
 
-    u8 *dir;
+    if (slash) {
 
-    *slash = 0;
-    dir = ck_strdup(argv0);
-    *slash = '/';
+      u8 *dir = ck_strdup(argv0);
 
-#ifdef __ANDROID__
-    tmp = alloc_printf("%s/%s", dir, obj);
-#else
-    tmp = alloc_printf("%s/%s", dir, obj);
-#endif
+      slash = strrchr(dir, '/');
+      *slash = 0;
 
-    if (!access(tmp, R_OK)) {
+      tmp = alloc_printf("%s/%s", dir, obj);
 
-      obj_path = dir;
-      return tmp;
+      if (!access(tmp, R_OK)) {
 
-    }
+        obj_path = dir;
+        return tmp;
 
-    ck_free(tmp);
-    ck_free(dir);
+      }
 
-  }
+      ck_free(tmp);
+      tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);
 
-  tmp = alloc_printf("%s/%s", AFL_PATH, obj);
-#ifdef __ANDROID__
-  if (!access(tmp, R_OK)) {
+      if (!access(tmp, R_OK)) {
 
-#else
-  if (!access(tmp, R_OK)) {
+        u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
+        obj_path = dir2;
+        ck_free(dir);
+        return tmp;
 
-#endif
+      }
 
-    obj_path = AFL_PATH;
-    return tmp;
+      ck_free(tmp);
+      ck_free(dir);
 
-  }
+    }
 
-  ck_free(tmp);
-  return NULL;
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
+    defined(__ANDROID__) || defined(__NetBSD__)
+  #define HAS_PROC_FS 1
+#endif
+#ifdef HAS_PROC_FS
+    else {
+
+      char *procname = NULL;
+  #if defined(__FreeBSD__) || defined(__DragonFly__)
+      procname = "/proc/curproc/file";
+  #elif defined(__linux__) || defined(__ANDROID__)
+      procname = "/proc/self/exe";
+  #elif defined(__NetBSD__)
+      procname = "/proc/curproc/exe";
+  #endif
+      if (procname) {
 
-}
+        char    exepath[PATH_MAX];
+        ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
+        if (exepath_len > 0 && exepath_len < PATH_MAX) {
 
-/* Try to find the runtime libraries. If that fails, abort. */
+          exepath[exepath_len] = 0;
+          slash = strrchr(exepath, '/');
 
-static void find_obj(u8 *argv0) {
+          if (slash) {
 
-  u8 *afl_path = getenv("AFL_PATH");
-  u8 *slash, *tmp;
+            *slash = 0;
+            tmp = alloc_printf("%s/%s", exepath, obj);
 
-  if (afl_path) {
+            if (!access(tmp, R_OK)) {
 
-#ifdef __ANDROID__
-    tmp = alloc_printf("%s/afl-compiler-rt.so", afl_path);
-#else
-    tmp = alloc_printf("%s/afl-compiler-rt.o", afl_path);
-#endif
+              u8 *dir = alloc_printf("%s", exepath);
+              obj_path = dir;
+              return tmp;
 
-    if (!access(tmp, R_OK)) {
+            }
 
-      obj_path = afl_path;
-      ck_free(tmp);
-      return;
+            ck_free(tmp);
+            tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);
 
-    }
+            if (!access(tmp, R_OK)) {
 
-    ck_free(tmp);
+              u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
+              obj_path = dir;
+              return tmp;
 
-  }
+            }
 
-  slash = strrchr(argv0, '/');
+          }
 
-  if (slash) {
+        }
 
-    u8 *dir;
+      }
 
-    *slash = 0;
-    dir = ck_strdup(argv0);
-    *slash = '/';
+    }
 
-#ifdef __ANDROID__
-    tmp = alloc_printf("%s/afl-compiler-rt.so", dir);
-#else
-    tmp = alloc_printf("%s/afl-compiler-rt.o", dir);
 #endif
+#undef HAS_PROC_FS
 
-    if (!access(tmp, R_OK)) {
+  }
 
-      obj_path = dir;
-      ck_free(tmp);
-      return;
+  tmp = alloc_printf("%s/%s", AFL_PATH, obj);
 
-    }
+  if (!access(tmp, R_OK)) {
 
-    ck_free(tmp);
-    ck_free(dir);
+    obj_path = AFL_PATH;
+    return tmp;
 
   }
 
-#ifdef __ANDROID__
-  if (!access(AFL_PATH "/afl-compiler-rt.so", R_OK)) {
+  ck_free(tmp);
 
-#else
-  if (!access(AFL_PATH "/afl-compiler-rt.o", R_OK)) {
+  tmp = alloc_printf("./%s", obj);
 
-#endif
+  if (!access(tmp, R_OK)) {
 
-    obj_path = AFL_PATH;
-    return;
+    obj_path = ".";
+    return tmp;
 
   }
 
-  FATAL(
-      "Unable to find 'afl-compiler-rt.o' or 'afl-llvm-pass.so'. Please set "
-      "AFL_PATH");
+  ck_free(tmp);
+
+  return NULL;
 
 }
 
@@ -288,7 +314,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       if (compiler_mode >= GCC_PLUGIN) {
 
-        alt_cxx = "g++";
+        if (compiler_mode == GCC) {
+
+          alt_cxx = clang_mode ? "clang++" : "g++";
+
+        } else {
+
+          alt_cxx = "g++";
+
+        }
 
       } else {
 
@@ -313,7 +347,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       if (compiler_mode >= GCC_PLUGIN) {
 
-        alt_cc = "gcc";
+        if (compiler_mode == GCC) {
+
+          alt_cc = clang_mode ? "clang" : "gcc";
+
+        } else {
+
+          alt_cc = "gcc";
+
+        }
 
       } else {
 
@@ -337,12 +379,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     cc_params[cc_par_cnt++] = "-B";
     cc_params[cc_par_cnt++] = obj_path;
 
+    if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
+
   }
 
   if (compiler_mode == GCC_PLUGIN) {
 
-    char *fplugin_arg =
-        alloc_printf("-fplugin=%s", find_object("afl-gcc-pass.so", argvnull));
+    char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
     cc_params[cc_par_cnt++] = fplugin_arg;
 
   }
@@ -354,19 +397,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (lto_mode && plusplus_mode)
       cc_params[cc_par_cnt++] = "-lc++";  // needed by fuzzbench, early
 
-    if (lto_mode) {
-
-      if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-          getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-          getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
+    if (lto_mode && have_instr_env) {
 
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
-
-      }
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
 
     }
 
@@ -508,11 +545,25 @@ static void edit_params(u32 argc, char **argv, char **envp) {
       if (instrument_mode == INSTRUMENT_PCGUARD) {
 
 #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+        if (have_instr_list) {
+
+          if (!be_quiet)
+            SAYF(
+                "Using unoptimized trace-pc-guard, due usage of "
+                "-fsanitize-coverage-allow/denylist, you can use "
+                "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
+          cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+
+        } else {
+
+          cc_params[cc_par_cnt++] = "-Xclang";
+          cc_params[cc_par_cnt++] = "-load";
+          cc_params[cc_par_cnt++] = "-Xclang";
+          cc_params[cc_par_cnt++] =
+              alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+
+        }
+
 #else
   #if LLVM_MAJOR >= 4
         if (!be_quiet)
@@ -590,6 +641,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
     if (!strcmp(cur, "-m64")) bit_mode = 64;
 
+    if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list="))
+      have_instr_list = 1;
+
     if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
       asan_set = 1;
 
@@ -675,7 +729,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   }
 
   if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
-      getenv("LAF_TRANSFORM_COMPARES") || lto_mode) {
+      getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") ||
+      lto_mode) {
 
     cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
     cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
@@ -826,7 +881,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     }
 
-  #ifndef __APPLE__
+  #if !defined(__APPLE__) && !defined(__sun)
     if (!shared_linking)
       cc_params[cc_par_cnt++] =
           alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
@@ -856,6 +911,14 @@ int main(int argc, char **argv, char **envp) {
 
     be_quiet = 1;
 
+  if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") ||
+      getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") ||
+      getenv("AFL_LLVM_BLOCKLIST")) {
+
+    have_instr_env = 1;
+
+  }
+
   if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
   argvnull = (u8 *)argv[0];
   check_environment_vars(envp);
@@ -915,7 +978,9 @@ int main(int argc, char **argv, char **envp) {
 
   } else if (strncmp(callname, "afl-gcc", 7) == 0 ||
 
-             strncmp(callname, "afl-g++", 7) == 0) {
+             strncmp(callname, "afl-g++", 7) == 0 ||
+
+             strncmp(callname, "afl-clang", 9) == 0) {
 
     compiler_mode = GCC;
 
@@ -959,6 +1024,14 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
+  if (strncmp(callname, "afl-clang", 9) == 0) {
+
+    clang_mode = 1;
+
+    if (strncmp(callname, "afl-clang++", 11) == 0) { plusplus_mode = 1; }
+
+  }
+
   for (i = 1; i < argc; i++) {
 
     if (strncmp(argv[i], "--afl", 5) == 0) {
@@ -1011,26 +1084,25 @@ int main(int argc, char **argv, char **envp) {
     if (instrument_mode == 0)
       instrument_mode = INSTRUMENT_PCGUARD;
     else if (instrument_mode != INSTRUMENT_PCGUARD)
-      FATAL("you can not set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
+      FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
 
   }
 
-  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"))
+  if (have_instr_env && getenv("AFL_DONT_OPTIMIZE")) {
+
     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")) {
 
     if (instrument_mode == 0)
       instrument_mode = INSTRUMENT_CFG;
     else if (instrument_mode != INSTRUMENT_CFG)
-      FATAL(
-          "you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
+      FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
 
   }
 
@@ -1307,15 +1379,20 @@ int main(int argc, char **argv, char **envp) {
             "  AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
             "filename\n");
 
+#if LLVM_MAJOR < 9
+  #define COUNTER_BEHAVIOUR \
+    "  AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
+#else
+  #define COUNTER_BEHAVIOUR \
+    "  AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
+#endif
       if (have_llvm)
         SAYF(
             "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
             "variables:\n"
-#if LLVM_MAJOR < 9
-            "  AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
-#else
-            "  AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
-#endif
+
+            COUNTER_BEHAVIOUR
+
             "  AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
             "comparisons\n"
             "  AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
@@ -1426,22 +1503,20 @@ int main(int argc, char **argv, char **envp) {
 #if LLVM_MAJOR <= 6
     instrument_mode = INSTRUMENT_AFL;
 #else
-    if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-        getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-        getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
+  #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
+    if (have_instr_env) {
 
       instrument_mode = INSTRUMENT_AFL;
-      WARNF(
-          "switching to classic instrumentation because "
-          "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");
+      if (!be_quiet)
+        WARNF(
+            "Switching to classic instrumentation because "
+            "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1.");
 
     } else
 
+  #endif
       instrument_mode = INSTRUMENT_PCGUARD;
+
 #endif
 
   }
@@ -1487,18 +1562,16 @@ int main(int argc, char **argv, char **envp) {
         "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
         "together");
 
-  if (instrument_mode == INSTRUMENT_PCGUARD &&
-      (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
+#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
+  if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) {
+
     FATAL(
         "Instrumentation type PCGUARD does not support "
-        "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");
+        "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead.");
+
+  }
+
+#endif
 
   u8 *ptr2;
 
@@ -1525,7 +1598,7 @@ int main(int argc, char **argv, char **envp) {
 
   if (debug) {
 
-    SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
+    DEBUGF("cd '%s';", getthecwd());
     for (i = 0; i < argc; i++)
       SAYF(" '%s'", argv[i]);
     SAYF("\n");
@@ -1545,15 +1618,29 @@ int main(int argc, char **argv, char **envp) {
   if (!be_quiet && cmplog_mode)
     printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
 
-#ifndef __ANDROID__
-  find_obj(argv[0]);
+#ifdef __ANDROID__
+  ptr = find_object("afl-compiler-rt.so", argv[0]);
+#else
+  ptr = find_object("afl-compiler-rt.o", argv[0]);
 #endif
 
+  if (!ptr) {
+
+    FATAL(
+        "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH "
+        "environment variable.");
+
+  }
+
+  if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
+
+  ck_free(ptr);
+
   edit_params(argc, argv, envp);
 
   if (debug) {
 
-    SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
+    DEBUGF("cd '%s';", getthecwd());
     for (i = 0; i < (s32)cc_par_cnt; i++)
       SAYF(" '%s'", cc_params[i]);
     SAYF("\n");
diff --git a/src/afl-common.c b/src/afl-common.c
index 8cf1a444..ed0b0e53 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -46,7 +46,7 @@ u8  be_quiet = 0;
 u8 *doc_path = "";
 u8  last_intr = 0;
 
-void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
+void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
 
   u32 i = 0;
   u8  cwd[PATH_MAX];
@@ -63,7 +63,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
 
       if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
 
-      *use_stdin = 0;
+      *use_stdin = false;
 
       if (prog_in[0] != 0) {  // not afl-showmap special case
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 45be2abd..38cd529f 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -62,6 +62,7 @@ static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) {
 
   execv(fsrv->target_path, argv);
 
+  WARNF("Execv failed in forkserver.");
 }
 
 /* Initializes the struct */
@@ -76,8 +77,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->dev_urandom_fd = -1;
 
   /* Settings */
-  fsrv->use_stdin = 1;
-  fsrv->no_unlink = 0;
+  fsrv->use_stdin = true;
+  fsrv->no_unlink = false;
   fsrv->exec_tmout = EXEC_TIMEOUT;
   fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
   fsrv->mem_limit = MEM_LIMIT;
@@ -86,8 +87,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   /* exec related stuff */
   fsrv->child_pid = -1;
   fsrv->map_size = get_map_size();
-  fsrv->use_fauxsrv = 0;
-  fsrv->last_run_timed_out = 0;
+  fsrv->use_fauxsrv = false;
+  fsrv->last_run_timed_out = false;
+
+  fsrv->uses_crash_exitcode = false;
+  fsrv->uses_asan = false;
 
   fsrv->init_child_func = fsrv_exec_child;
 
@@ -109,6 +113,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->dev_urandom_fd = from->dev_urandom_fd;
   fsrv_to->out_fd = from->out_fd;  // not sure this is a good idea
   fsrv_to->no_unlink = from->no_unlink;
+  fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
+  fsrv_to->crash_exitcode = from->crash_exitcode;
 
   // These are forkserver specific.
   fsrv_to->out_dir_fd = -1;
@@ -116,7 +122,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->use_fauxsrv = 0;
   fsrv_to->last_run_timed_out = 0;
 
-  fsrv_to->init_child_func = fsrv_exec_child;
+  fsrv_to->init_child_func = from->init_child_func;
   // Note: do not copy ->add_extra_func
 
   list_append(&fsrv_list, fsrv_to);
@@ -272,7 +278,8 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
 
       *(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
 
-      PFATAL("Execv failed in fauxserver.");
+      WARNF("Execv failed in fauxserver.");
+      break;
 
     }
 
@@ -286,13 +293,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
     if (waitpid(child_pid, &status, 0) < 0) {
 
       // Zombie Child could not be collected. Scary!
-      PFATAL("Fauxserver could not determin child's exit code. ");
+      WARNF("Fauxserver could not determine child's exit code. ");
 
     }
 
     /* Relay wait status to AFL pipe, then loop back. */
 
-    if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
+    if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(1); }
 
   }
 
@@ -330,7 +337,7 @@ static void report_error_and_exit(int error) {
           "memory failed.");
       break;
     default:
-      FATAL("unknown error code %u from fuzzing target!", error);
+      FATAL("unknown error code %d from fuzzing target!", error);
 
   }
 
@@ -347,15 +354,16 @@ static void report_error_and_exit(int error) {
 void 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];
-  s32 status;
-  s32 rlen;
+  int   st_pipe[2], ctl_pipe[2];
+  s32   status;
+  s32   rlen;
+  char *ignore_autodict = getenv("AFL_NO_AUTODICT");
 
   if (!be_quiet) { ACTF("Spinning up the fork server..."); }
 
   if (fsrv->use_fauxsrv) {
 
-    /* TODO: Come up with sone nice way to initialize this all */
+    /* TODO: Come up with some nice way to initialize this all */
 
     if (fsrv->init_child_func != fsrv_exec_child) {
 
@@ -519,8 +527,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
        falling through. */
 
     *(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
-    fprintf(stderr, "Error: execv to target failed\n");
-    exit(0);
+    FATAL("Error: execv to target failed\n");
 
   }
 
@@ -606,7 +613,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
           fsrv->use_shmem_fuzz = 1;
           if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
 
-          if ((status & FS_OPT_AUTODICT) == 0) {
+          if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
 
             u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
             if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
@@ -659,101 +666,109 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
       if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
 
-        if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
+        if (ignore_autodict) {
 
-          // this is not afl-fuzz - or it is cmplog - we deny and return
-          if (fsrv->use_shmem_fuzz) {
+          if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); }
 
-            status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
+        } else {
 
-          } else {
+          if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
 
-            status = (FS_OPT_ENABLED);
+            // this is not afl-fuzz - or it is cmplog - we deny and return
+            if (fsrv->use_shmem_fuzz) {
 
-          }
+              status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
 
-          if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+            } else {
 
-            FATAL("Writing to forkserver failed.");
+              status = (FS_OPT_ENABLED);
 
-          }
+            }
 
-          return;
+            if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
 
-        }
+              FATAL("Writing to forkserver failed.");
 
-        if (!be_quiet) { ACTF("Using AUTODICT feature."); }
+            }
 
-        if (fsrv->use_shmem_fuzz) {
+            return;
 
-          status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
+          }
 
-        } else {
+          if (!be_quiet) { ACTF("Using AUTODICT feature."); }
 
-          status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
+          if (fsrv->use_shmem_fuzz) {
 
-        }
+            status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
 
-        if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+          } else {
 
-          FATAL("Writing to forkserver failed.");
+            status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
 
-        }
+          }
 
-        if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
+          if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
 
-          FATAL("Reading from forkserver failed.");
+            FATAL("Writing to forkserver failed.");
 
-        }
+          }
 
-        if (status < 2 || (u32)status > 0xffffff) {
+          if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
 
-          FATAL("Dictionary has an illegal size: %d", status);
+            FATAL("Reading from forkserver failed.");
 
-        }
+          }
 
-        u32 offset = 0, count = 0;
-        u32 len = status;
-        u8 *dict = ck_alloc(len);
-        if (dict == NULL) {
+          if (status < 2 || (u32)status > 0xffffff) {
 
-          FATAL("Could not allocate %u bytes of autodictionary memory", len);
+            FATAL("Dictionary has an illegal size: %d", status);
 
-        }
+          }
 
-        while (len != 0) {
+          u32 offset = 0, count = 0;
+          u32 len = status;
+          u8 *dict = ck_alloc(len);
+          if (dict == NULL) {
 
-          rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
-          if (rlen > 0) {
+            FATAL("Could not allocate %u bytes of autodictionary memory", len);
 
-            len -= rlen;
-            offset += rlen;
+          }
 
-          } else {
+          while (len != 0) {
+
+            rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
+            if (rlen > 0) {
+
+              len -= rlen;
+              offset += rlen;
 
-            FATAL(
-                "Reading autodictionary fail at position %u with %u bytes "
-                "left.",
-                offset, len);
+            } else {
+
+              FATAL(
+                  "Reading autodictionary fail at position %u with %u bytes "
+                  "left.",
+                  offset, len);
+
+            }
 
           }
 
-        }
+          offset = 0;
+          while (offset < (u32)status &&
+                 (u8)dict[offset] + offset < (u32)status) {
+
+            fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
+                                 (u8)dict[offset]);
+            offset += (1 + dict[offset]);
+            count++;
 
-        offset = 0;
-        while (offset < (u32)status &&
-               (u8)dict[offset] + offset < (u32)status) {
+          }
 
-          fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
-                               (u8)dict[offset]);
-          offset += (1 + dict[offset]);
-          count++;
+          if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
+          ck_free(dict);
 
         }
 
-        if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
-        ck_free(dict);
-
       }
 
     }
@@ -901,7 +916,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
         "      estimate the required amount of virtual memory for the "
         "binary.\n\n"
 
-        "    - the target was compiled with afl-clang-lto and a constructor "
+        "    - The target was compiled with afl-clang-lto and a constructor "
         "was\n"
         "      instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
         "your \n"
@@ -1054,6 +1069,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
   if (fsrv->child_pid <= 0) {
 
     if (*stop_soon_p) { return 0; }
+
+    if ((fsrv->child_pid & FS_OPT_ERROR) &&
+        FS_OPT_GET_ERROR(fsrv->child_pid) == FS_ERROR_SHM_OPEN)
+      FATAL(
+          "Target reported shared memory access failed (perhaps increase "
+          "shared memory available).");
+
     FATAL("Fork server is misbehaving (OOM?)");
 
   }
@@ -1126,10 +1148,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
 
   }
 
-  /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
-     must use a special exit code. */
+  /* MSAN in uses_asan mode uses a special exit code as it doesn't support
+  abort_on_error.
+  On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */
 
-  if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) {
+  if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
+      (fsrv->uses_crash_exitcode &&
+       WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) {
 
     fsrv->last_kill_signal = 0;
     return FSRV_RUN_CRASH;
@@ -1137,7 +1162,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
   }
 
   // Fauxserver should handle this now.
-  // if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
+  if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
 
   return FSRV_RUN_OK;
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index a4407af7..f1ca7400 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -425,8 +425,10 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
 /* Construct a file name for a new test case, capturing the operation
    that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
 
-u8 *describe_op(afl_state_t *afl, u8 hnb) {
+u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
 
+  size_t real_max_len =
+      MIN(max_description_len, sizeof(afl->describe_op_buf_256));
   u8 *ret = afl->describe_op_buf_256;
 
   if (unlikely(afl->syncing_party)) {
@@ -445,29 +447,66 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
 
     sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
 
-    sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
+    if (afl->current_custom_fuzz &&
+        afl->current_custom_fuzz->afl_custom_describe) {
 
-    if (afl->stage_cur_byte >= 0) {
+      /* We are currently in a custom mutator that supports afl_custom_describe,
+       * use it! */
 
-      sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
+      size_t len_current = strlen(ret);
+      ret[len_current++] = ',';
+      ret[len_current] = '\0';
 
-      if (afl->stage_val_type != STAGE_VAL_NONE) {
+      ssize_t size_left = real_max_len - len_current - strlen(",+cov") - 2;
+      if (unlikely(size_left <= 0)) FATAL("filename got too long");
 
-        sprintf(ret + strlen(ret), ",val:%s%+d",
-                (afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
-                afl->stage_cur_val);
+      const char *custom_description =
+          afl->current_custom_fuzz->afl_custom_describe(
+              afl->current_custom_fuzz->data, size_left);
+      if (!custom_description || !custom_description[0]) {
+
+        DEBUGF("Error getting a description from afl_custom_describe");
+        /* Take the stage name as description fallback */
+        sprintf(ret + len_current, "op:%s", afl->stage_short);
+
+      } else {
+
+        /* We got a proper custom description, use it */
+        strncat(ret + len_current, custom_description, size_left);
 
       }
 
     } else {
 
-      sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
+      /* Normal testcase descriptions start here */
+      sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
+
+      if (afl->stage_cur_byte >= 0) {
+
+        sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
+
+        if (afl->stage_val_type != STAGE_VAL_NONE) {
+
+          sprintf(ret + strlen(ret), ",val:%s%+d",
+                  (afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
+                  afl->stage_cur_val);
+
+        }
+
+      } else {
+
+        sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
+
+      }
 
     }
 
   }
 
-  if (hnb == 2) { strcat(ret, ",+cov"); }
+  if (new_bits == 2) { strcat(ret, ",+cov"); }
+
+  if (unlikely(strlen(ret) >= max_description_len))
+    FATAL("describe string is too long");
 
   return ret;
 
@@ -540,7 +579,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
   if (unlikely(len == 0)) { return 0; }
 
   u8 *queue_fn = "";
-  u8  hnb = '\0';
+  u8  new_bits = '\0';
   s32 fd;
   u8  keeping = 0, res;
   u64 cksum = 0;
@@ -566,7 +605,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
     /* Keep only if there are new bits in the map, add to queue for
        future fuzzing, etc. */
 
-    if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
+    if (!(new_bits = has_new_bits(afl, afl->virgin_bits))) {
 
       if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
       return 0;
@@ -575,8 +614,9 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-    queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
-                            afl->queued_paths, describe_op(afl, hnb));
+    queue_fn = alloc_printf(
+        "%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
+        describe_op(afl, new_bits, NAME_MAX - strlen("id:000000,")));
 
 #else
 
@@ -584,7 +624,10 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
         alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
 
 #endif                                                    /* ^!SIMPLE_FILES */
-
+    fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
+    if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
+    ck_write(fd, mem, len, queue_fn);
+    close(fd);
     add_to_queue(afl, queue_fn, len, 0);
 
 #ifdef INTROSPECTION
@@ -616,7 +659,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #endif
 
-    if (hnb == 2) {
+    if (new_bits == 2) {
 
       afl->queue_top->has_new_cov = 1;
       ++afl->queued_with_cov;
@@ -647,11 +690,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
     }
 
-    fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-    if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
-    ck_write(fd, mem, len, queue_fn);
-    close(fd);
-
     if (likely(afl->q_testcase_max_cache_size)) {
 
       queue_testcase_store_mem(afl, afl->queue_top, mem);
@@ -744,7 +782,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 #ifndef SIMPLE_FILES
 
       snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
-               afl->unique_hangs, describe_op(afl, 0));
+               afl->unique_hangs,
+               describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
 
 #else
 
@@ -789,7 +828,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
                afl->unique_crashes, afl->fsrv.last_kill_signal,
-               describe_op(afl, 0));
+               describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
 
 #else
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 19a8d77b..6707340b 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -355,7 +355,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
   if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
 
-  for (i = 0; i < ncpus; i++) {
+  for (i = 0; i < (s32)ncpus; i++) {
 
     k = kstat_lookup(m, "cpu_stat", i, NULL);
     if (kstat_read(m, k, &cs)) {
@@ -868,7 +868,19 @@ void perform_dry_run(afl_state_t *afl) {
 
         if (skip_crashes) {
 
-          WARNF("Test case results in a crash (skipping)");
+          if (afl->fsrv.uses_crash_exitcode) {
+
+            WARNF(
+                "Test case results in a crash or AFL_CRASH_EXITCODE %d "
+                "(skipping)",
+                (int)(s8)afl->fsrv.crash_exitcode);
+
+          } else {
+
+            WARNF("Test case results in a crash (skipping)");
+
+          }
+
           q->cal_failed = CAL_CHANCES;
           ++cal_failures;
           break;
@@ -954,7 +966,18 @@ void perform_dry_run(afl_state_t *afl) {
 #undef MSG_ULIMIT_USAGE
 #undef MSG_FORK_ON_APPLE
 
-        WARNF("Test case '%s' results in a crash, skipping", fn);
+        if (afl->fsrv.uses_crash_exitcode) {
+
+          WARNF(
+              "Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, "
+              "skipping",
+              fn, (int)(s8)afl->fsrv.crash_exitcode);
+
+        } else {
+
+          WARNF("Test case '%s' results in a crash, skipping", fn);
+
+        }
 
         /* Remove from fuzzing queue but keep for splicing */
 
@@ -2300,12 +2323,6 @@ void fix_up_sync(afl_state_t *afl) {
 
   u8 *x = afl->sync_id;
 
-  if (afl->non_instrumented_mode) {
-
-    FATAL("-S / -M and -n are mutually exclusive");
-
-  }
-
   while (*x) {
 
     if (!isalnum(*x) && *x != '_' && *x != '-') {
@@ -2503,7 +2520,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode) {
+  if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
+      afl->non_instrumented_mode) {
 
     return;
 
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 1d14f657..0c85458e 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -151,7 +151,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
   /* Mutator */
   /* "afl_custom_init", optional for backward compatibility */
   mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
-  if (!mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
+  if (!mutator->afl_custom_init) {
+
+    FATAL("Symbol 'afl_custom_init' not found.");
+
+  }
 
   /* "afl_custom_fuzz" or "afl_custom_mutator", required */
   mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@@ -161,49 +165,74 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
     WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
 
     mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
-    if (!mutator->afl_custom_fuzz)
+    if (!mutator->afl_custom_fuzz) {
+
       WARNF("Symbol 'afl_custom_mutator' not found.");
 
+    }
+
   }
 
   /* "afl_custom_introspection", optional */
 #ifdef INTROSPECTION
   mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
-  if (!mutator->afl_custom_introspection)
+  if (!mutator->afl_custom_introspection) {
+
     ACTF("optional symbol 'afl_custom_introspection' not found.");
+
+  }
+
 #endif
 
   /* "afl_custom_fuzz_count", optional */
   mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
-  if (!mutator->afl_custom_fuzz_count)
+  if (!mutator->afl_custom_fuzz_count) {
+
     ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
 
+  }
+
   /* "afl_custom_deinit", optional for backward compatibility */
   mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
-  if (!mutator->afl_custom_deinit)
+  if (!mutator->afl_custom_deinit) {
+
     FATAL("Symbol 'afl_custom_deinit' not found.");
 
+  }
+
   /* "afl_custom_post_process", optional */
   mutator->afl_custom_post_process = dlsym(dh, "afl_custom_post_process");
-  if (!mutator->afl_custom_post_process)
+  if (!mutator->afl_custom_post_process) {
+
     ACTF("optional symbol 'afl_custom_post_process' not found.");
 
+  }
+
   u8 notrim = 0;
   /* "afl_custom_init_trim", optional */
   mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
-  if (!mutator->afl_custom_init_trim)
+  if (!mutator->afl_custom_init_trim) {
+
     ACTF("optional symbol 'afl_custom_init_trim' not found.");
 
+  }
+
   /* "afl_custom_trim", optional */
   mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
-  if (!mutator->afl_custom_trim)
+  if (!mutator->afl_custom_trim) {
+
     ACTF("optional symbol 'afl_custom_trim' not found.");
 
+  }
+
   /* "afl_custom_post_trim", optional */
   mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
-  if (!mutator->afl_custom_post_trim)
+  if (!mutator->afl_custom_post_trim) {
+
     ACTF("optional symbol 'afl_custom_post_trim' not found.");
 
+  }
+
   if (notrim) {
 
     mutator->afl_custom_init_trim = NULL;
@@ -217,31 +246,54 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   /* "afl_custom_havoc_mutation", optional */
   mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation");
-  if (!mutator->afl_custom_havoc_mutation)
+  if (!mutator->afl_custom_havoc_mutation) {
+
     ACTF("optional symbol 'afl_custom_havoc_mutation' not found.");
 
+  }
+
   /* "afl_custom_havoc_mutation", optional */
   mutator->afl_custom_havoc_mutation_probability =
       dlsym(dh, "afl_custom_havoc_mutation_probability");
-  if (!mutator->afl_custom_havoc_mutation_probability)
+  if (!mutator->afl_custom_havoc_mutation_probability) {
+
     ACTF("optional symbol 'afl_custom_havoc_mutation_probability' not found.");
 
+  }
+
   /* "afl_custom_queue_get", optional */
   mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
-  if (!mutator->afl_custom_queue_get)
+  if (!mutator->afl_custom_queue_get) {
+
     ACTF("optional symbol 'afl_custom_queue_get' not found.");
 
+  }
+
   /* "afl_custom_queue_new_entry", optional */
   mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry");
-  if (!mutator->afl_custom_queue_new_entry)
+  if (!mutator->afl_custom_queue_new_entry) {
+
     ACTF("optional symbol 'afl_custom_queue_new_entry' not found");
 
+  }
+
+  /* "afl_custom_describe", optional */
+  mutator->afl_custom_describe = dlsym(dh, "afl_custom_describe");
+  if (!mutator->afl_custom_describe) {
+
+    ACTF("Symbol 'afl_custom_describe' not found.");
+
+  }
+
   OKF("Custom mutator '%s' installed successfully.", fn);
 
   /* Initialize the custom mutator */
-  if (mutator->afl_custom_init)
+  if (mutator->afl_custom_init) {
+
     mutator->data = mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
 
+  }
+
   mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
   mutator->stacked_custom_prob =
       6;  // like one of the default mutations in havoc
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 0adc3719..e6fa6064 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -445,8 +445,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   if (unlikely(afl->not_on_tty)) {
 
-    ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...",
-         afl->current_entry, afl->queued_paths, afl->unique_crashes);
+    ACTF(
+        "Fuzzing test case #%u (%u total, %llu uniq crashes found, "
+        "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...",
+        afl->current_entry, afl->queued_paths, afl->unique_crashes,
+        afl->queue_cur->perf_score, afl->queue_cur->exec_us,
+        likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
+        afl->queue_cur->bitmap_size);
     fflush(stdout);
 
   }
@@ -1790,11 +1795,16 @@ custom_mutator_stage:
 
       afl->current_custom_fuzz = el;
 
-      if (el->afl_custom_fuzz_count)
+      if (el->afl_custom_fuzz_count) {
+
         afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
-      else
+
+      } else {
+
         afl->stage_max = saved_max;
 
+      }
+
       has_custom_fuzz = true;
 
       afl->stage_short = el->name_short;
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 596b733e..8760194c 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -96,7 +96,7 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
     mutated_size = PyByteArray_Size(py_value);
 
     *out_buf = afl_realloc(BUF_PARAMS(fuzz), mutated_size);
-    if (unlikely(!out_buf)) { PFATAL("alloc"); }
+    if (unlikely(!*out_buf)) { PFATAL("alloc"); }
 
     memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
     Py_DECREF(py_value);
@@ -111,6 +111,37 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
 
 }
 
+static const char *custom_describe_py(void * py_mutator,
+                                      size_t max_description_len) {
+
+  PyObject *py_args, *py_value;
+
+  py_args = PyTuple_New(1);
+
+  PyLong_FromSize_t(max_description_len);
+
+  /* add_buf */
+  py_value = PyLong_FromSize_t(max_description_len);
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 0, py_value);
+
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DESCRIBE], py_args);
+
+  Py_DECREF(py_args);
+
+  if (py_value != NULL) { return PyBytes_AsString(py_value); }
+
+  return NULL;
+
+}
+
 static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
   (void)afl;
@@ -134,6 +165,18 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
   PyObject * py_module = py->py_module;
   PyObject **py_functions = py->py_functions;
 
+  // initialize the post process buffer; ensures it's always valid
+  PyObject *unused_bytes = PyByteArray_FromStringAndSize("OHAI", 4);
+  if (!unused_bytes) { FATAL("allocation failed!"); }
+  if (PyObject_GetBuffer(unused_bytes, &py->post_process_buf, PyBUF_SIMPLE) ==
+      -1) {
+
+    FATAL("buffer initialization failed");
+
+  }
+
+  Py_DECREF(unused_bytes);
+
   if (py_module != NULL) {
 
     u8 py_notrim = 0, py_idx;
@@ -144,6 +187,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
     py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
     if (!py_functions[PY_FUNC_FUZZ])
       py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
+    py_functions[PY_FUNC_DESCRIBE] =
+        PyObject_GetAttrString(py_module, "describe");
     py_functions[PY_FUNC_FUZZ_COUNT] =
         PyObject_GetAttrString(py_module, "fuzz_count");
     if (!py_functions[PY_FUNC_FUZZ])
@@ -313,7 +358,6 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
   struct custom_mutator *mutator;
 
   mutator = ck_alloc(sizeof(struct custom_mutator));
-  mutator->post_process_buf = NULL;
 
   mutator->name = module_name;
   ACTF("Loading Python mutator library from '%s'...", module_name);
@@ -329,9 +373,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
 
   if (py_functions[PY_FUNC_DEINIT]) { mutator->afl_custom_deinit = deinit_py; }
 
-  /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
-     is quite different from the custom mutator. */
-  mutator->afl_custom_fuzz = fuzz_py;
+  if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
+
+  if (py_functions[PY_FUNC_DESCRIBE]) {
+
+    mutator->afl_custom_describe = custom_describe_py;
+
+  }
 
   if (py_functions[PY_FUNC_POST_PROCESS]) {
 
@@ -405,10 +453,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
 size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
                        u8 **out_buf) {
 
-  size_t        py_out_buf_size;
   PyObject *    py_args, *py_value;
   py_mutator_t *py = (py_mutator_t *)py_mutator;
 
+  // buffer returned previously must be released; initialized during init
+  // so we don't need to do comparisons
+  PyBuffer_Release(&py->post_process_buf);
+
   py_args = PyTuple_New(1);
   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
@@ -428,20 +479,20 @@ size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
 
   if (py_value != NULL) {
 
-    py_out_buf_size = PyByteArray_Size(py_value);
+    if (PyObject_GetBuffer(py_value, &py->post_process_buf, PyBUF_SIMPLE) ==
+        -1) {
 
-    if (unlikely(!afl_realloc(BUF_PARAMS(post_process), py_out_buf_size))) {
-
-      PFATAL("alloc");
+      PyErr_Print();
+      FATAL(
+          "Python custom mutator: post_process call return value not a "
+          "bytes-like object");
 
     }
 
-    memcpy(py->post_process_buf, PyByteArray_AsString(py_value),
-           py_out_buf_size);
     Py_DECREF(py_value);
 
-    *out_buf = py->post_process_buf;
-    return py_out_buf_size;
+    *out_buf = (u8 *)py->post_process_buf.buf;
+    return py->post_process_buf.len;
 
   } else {
 
@@ -581,7 +632,7 @@ size_t trim_py(void *py_mutator, u8 **out_buf) {
 
     ret = PyByteArray_Size(py_value);
     *out_buf = afl_realloc(BUF_PARAMS(trim), ret);
-    if (unlikely(!out_buf)) { PFATAL("alloc"); }
+    if (unlikely(!*out_buf)) { PFATAL("alloc"); }
     memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
     Py_DECREF(py_value);
 
@@ -647,7 +698,7 @@ size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
 
       /* A new buf is needed... */
       *out_buf = afl_realloc(BUF_PARAMS(havoc), mutated_size);
-      if (unlikely(!out_buf)) { PFATAL("alloc"); }
+      if (unlikely(!*out_buf)) { PFATAL("alloc"); }
 
     }
 
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index c78df8be..071e4a4c 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -42,11 +42,29 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
 
 }
 
+double compute_weight(afl_state_t *afl, struct queue_entry *q,
+                      double avg_exec_us, double avg_bitmap_size) {
+
+  u32 hits = afl->n_fuzz[q->n_fuzz_entry];
+  if (hits == 0) hits = 1;
+
+  double weight = 1.0;
+  weight *= avg_exec_us / q->exec_us;
+  weight *= log(q->bitmap_size) / avg_bitmap_size;
+  weight /= log10(hits) + 1;
+
+  if (q->favored) weight *= 5;
+
+  return weight;
+
+}
+
 /* create the alias table that allows weighted random selection - expensive */
 
 void create_alias_table(afl_state_t *afl) {
 
-  u32 n = afl->queued_paths, i = 0, a, g;
+  u32    n = afl->queued_paths, i = 0, a, g;
+  double sum = 0;
 
   afl->alias_table =
       (u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
@@ -56,26 +74,69 @@ void create_alias_table(afl_state_t *afl) {
   int *   S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
   int *   L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
 
-  if (!P || !S || !L) { FATAL("could not aquire memory for alias table"); }
+  if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
+
+    FATAL("could not acquire memory for alias table");
+
+  }
+
   memset((void *)afl->alias_table, 0, n * sizeof(u32));
   memset((void *)afl->alias_probability, 0, n * sizeof(double));
 
-  double sum = 0;
+  if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
 
-  for (i = 0; i < n; i++) {
+    double avg_exec_us = 0.0;
+    double avg_bitmap_size = 0.0;
+    for (i = 0; i < n; i++) {
 
-    struct queue_entry *q = afl->queue_buf[i];
+      struct queue_entry *q = afl->queue_buf[i];
+      avg_exec_us += q->exec_us;
+      avg_bitmap_size += log(q->bitmap_size);
 
-    if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
+    }
 
-    sum += q->perf_score;
+    avg_exec_us /= afl->queued_paths;
+    avg_bitmap_size /= afl->queued_paths;
 
-  }
+    for (i = 0; i < n; i++) {
 
-  for (i = 0; i < n; i++) {
+      struct queue_entry *q = afl->queue_buf[i];
+
+      if (!q->disabled) {
+
+        q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size);
+        q->perf_score = calculate_score(afl, q);
+
+      }
 
-    struct queue_entry *q = afl->queue_buf[i];
-    P[i] = (q->perf_score * n) / sum;
+      sum += q->weight;
+
+    }
+
+    for (i = 0; i < n; i++) {
+
+      P[i] = (afl->queue_buf[i]->weight * n) / sum;
+
+    }
+
+  } else {
+
+    for (i = 0; i < n; i++) {
+
+      struct queue_entry *q = afl->queue_buf[i];
+
+      if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
+
+      sum += q->perf_score;
+
+    }
+
+    for (i = 0; i < n; i++) {
+
+      struct queue_entry *q = afl->queue_buf[i];
+      P[i] = (q->perf_score * n) / sum;
+
+    }
 
   }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index e969994d..5948d83a 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -79,7 +79,8 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
   s32  doc_fd;
   char fn[PATH_MAX];
   snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir,
-           afl->document_counter++, describe_op(afl, 0));
+           afl->document_counter++,
+           describe_op(afl, 0, NAME_MAX - strlen("000000000:")));
 
   if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
 
@@ -332,7 +333,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
     }
 
     afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
-                   afl->afl_env.afl_debug_child_output);
+                   afl->afl_env.afl_debug_child);
 
     if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) {
 
@@ -484,7 +485,7 @@ void sync_fuzzers(afl_state_t *afl) {
   DIR *          sd;
   struct dirent *sd_ent;
   u32            sync_cnt = 0, synced = 0, entries = 0;
-  u8             path[PATH_MAX + 256];
+  u8             path[PATH_MAX + 1 + NAME_MAX];
 
   sd = opendir(afl->sync_dir);
   if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
@@ -590,7 +591,7 @@ void sync_fuzzers(afl_state_t *afl) {
 
     while (m < n) {
 
-      if (strcmp(namelist[m]->d_name, entry)) {
+      if (strncmp(namelist[m]->d_name, entry, 9)) {
 
         m++;
 
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 61bd06b7..73b94466 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -268,11 +268,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_bench_until_crash =
                 get_afl_env(afl_environment_variables[i]) ? 1 : 0;
 
-          } else if (!strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
+          } else if (!strncmp(env, "AFL_DEBUG_CHILD",
 
+                              afl_environment_variable_len) ||
+                     !strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
                               afl_environment_variable_len)) {
 
-            afl->afl_env.afl_debug_child_output =
+            afl->afl_env.afl_debug_child =
                 get_afl_env(afl_environment_variables[i]) ? 1 : 0;
 
           } else if (!strncmp(env, "AFL_AUTORESUME",
@@ -392,6 +394,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_statsd_tags_flavor =
                 (u8 *)get_afl_env(afl_environment_variables[i]);
 
+          } else if (!strncmp(env, "AFL_CRASH_EXITCODE",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_crash_exitcode =
+                (u8 *)get_afl_env(afl_environment_variables[i]);
+
           }
 
         } else {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8a66018d..bbe6aec6 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -26,6 +26,7 @@
 #include "afl-fuzz.h"
 #include "cmplog.h"
 #include <limits.h>
+#include <stdlib.h>
 #ifndef USEMMAP
   #include <sys/mman.h>
   #include <sys/stat.h>
@@ -40,7 +41,7 @@ extern u64 time_spent_working;
 
 static void at_exit() {
 
-  int   i;
+  s32   i, pid1 = 0, pid2 = 0;
   char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
   char *ptr;
 
@@ -48,10 +49,10 @@ static void at_exit() {
   if (ptr && *ptr) unlink(ptr);
 
   ptr = getenv("__AFL_TARGET_PID1");
-  if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
+  if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) kill(pid1, SIGTERM);
 
   ptr = getenv("__AFL_TARGET_PID2");
-  if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
+  if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) kill(pid2, SIGTERM);
 
   i = 0;
   while (list[i] != NULL) {
@@ -75,6 +76,9 @@ static void at_exit() {
 
   }
 
+  if (pid1 > 0) { kill(pid1, SIGKILL); }
+  if (pid2 > 0) { kill(pid2, SIGKILL); }
+
 }
 
 /* Display usage hints. */
@@ -162,11 +166,12 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
       "AFL_BENCH_JUST_ONE: run the target just once\n"
       "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
+      "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
       "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
       "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
       "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
       "AFL_DEBUG: extra debugging output for Python mode trimming\n"
-      "AFL_DEBUG_CHILD_OUTPUT: do not suppress stdout/stderr from target\n"
+      "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
       "AFL_DISABLE_TRIM: disable the trimming of test cases\n"
       "AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
       "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
@@ -184,6 +189,7 @@ static void usage(u8 *argv0, int more_help) {
       "                    used. Defaults to 200.\n"
       "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
       "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
+      "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
       "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
       "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
       "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
@@ -350,6 +356,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 's': {
 
+        if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
         rand_set_seed(afl, strtoul(optarg, 0L, 10));
         afl->fixed_seed = 1;
         break;
@@ -419,6 +426,7 @@ int main(int argc, char **argv_orig, char **envp) {
       case 'i':                                                /* input dir */
 
         if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
+        if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
         afl->in_dir = optarg;
 
         if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
@@ -435,9 +443,26 @@ int main(int argc, char **argv_orig, char **envp) {
 
         u8 *c;
 
+        if (afl->non_instrumented_mode) {
+
+          FATAL("-M is not supported in non-instrumented mode");
+
+        }
+
         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
+
+        /* sanity check for argument: should not begin with '-' (possible
+         * option) */
+        if (optarg && *optarg == '-') {
+
+          FATAL(
+              "argument for -M started with a dash '-', which is used for "
+              "options");
+
+        }
+
         afl->sync_id = ck_strdup(optarg);
-        afl->skip_deterministic = 0;  // force determinsitic fuzzing
+        afl->skip_deterministic = 0;  // force deterministic fuzzing
         afl->old_seed_selection = 1;  // force old queue walking seed selection
 
         if ((c = strchr(afl->sync_id, ':'))) {
@@ -464,7 +489,24 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 'S':                                        /* secondary sync id */
 
+        if (afl->non_instrumented_mode) {
+
+          FATAL("-S is not supported in non-instrumented mode");
+
+        }
+
         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
+
+        /* sanity check for argument: should not begin with '-' (possible
+         * option) */
+        if (optarg && *optarg == '-') {
+
+          FATAL(
+              "argument for -M started with a dash '-', which is used for "
+              "options");
+
+        }
+
         afl->sync_id = ck_strdup(optarg);
         afl->is_secondary_node = 1;
         break;
@@ -620,6 +662,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 'n':                                                /* dumb mode */
 
+        if (afl->is_main_node || afl->is_secondary_node) {
+
+          FATAL("Non instrumented mode is not supported with -M / -S");
+
+        }
+
         if (afl->non_instrumented_mode) {
 
           FATAL("Multiple -n options not supported");
@@ -656,7 +704,7 @@ int main(int argc, char **argv_orig, char **envp) {
       case 'N':                                             /* Unicorn mode */
 
         if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
-        afl->fsrv.no_unlink = afl->no_unlink = 1;
+        afl->fsrv.no_unlink = (afl->no_unlink = true);
 
         break;
 
@@ -906,7 +954,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   afl->power_name = power_names[afl->schedule];
 
-  if (!afl->sync_id) {
+  if (!afl->non_instrumented_mode && !afl->sync_id) {
 
     auto_sync = 1;
     afl->sync_id = ck_strdup("default");
@@ -1089,6 +1137,23 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+  if (afl->afl_env.afl_crash_exitcode) {
+
+    long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
+    if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+        exitcode < -127 || exitcode > 128) {
+
+      FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+            afl->afl_env.afl_crash_exitcode);
+
+    }
+
+    afl->fsrv.uses_crash_exitcode = true;
+    // WEXITSTATUS is 8 bit unsigned
+    afl->fsrv.crash_exitcode = (u8)exitcode;
+
+  }
+
   if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
 
     FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
@@ -1338,7 +1403,11 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); }
+    if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
+
+      check_binary(afl, afl->cmplog_binary);
+
+    }
 
   }
 
@@ -1380,7 +1449,7 @@ int main(int argc, char **argv_orig, char **envp) {
     afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
     afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
     afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
-                   afl->afl_env.afl_debug_child_output);
+                   afl->afl_env.afl_debug_child);
     OKF("Cmplog forkserver successfully started");
 
   }
@@ -1436,9 +1505,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
   cull_queue(afl);
 
-  if (!afl->pending_not_fuzzed)
+  if (!afl->pending_not_fuzzed) {
+
     FATAL("We need at least on valid input seed that does not crash!");
 
+  }
+
   show_init_stats(afl);
 
   if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 771e2d0d..16feaa80 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -182,12 +182,12 @@ static void edit_params(int argc, char **argv) {
     instrim = 1;
 
   if (debug)
-    SAYF(cMGN "[D] " cRST
-              "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
-              "inst_present=%s rt_present=%s rt_lto_present=%s\n",
-         passthrough ? "true" : "false", instrim, gold_pos,
-         gold_present ? "true" : "false", inst_present ? "true" : "false",
-         rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
+    DEBUGF(
+        "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
+        "inst_present=%s rt_present=%s rt_lto_present=%s\n",
+        passthrough ? "true" : "false", instrim, gold_pos,
+        gold_present ? "true" : "false", inst_present ? "true" : "false",
+        rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
 
   for (i = 1; i < argc; i++) {
 
@@ -280,7 +280,7 @@ int main(int argc, char **argv) {
 
     if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
 
-    SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd);
+    DEBUGF("cd \"%s\";", thecwd);
     for (i = 0; i < argc; i++)
       SAYF(" \"%s\"", argv[i]);
     SAYF("\n");
@@ -315,7 +315,7 @@ int main(int argc, char **argv) {
 
   if (debug) {
 
-    SAYF(cMGN "[D]" cRST " cd \"%s\";", thecwd);
+    DEBUGF("cd \"%s\";", thecwd);
     for (i = 0; i < ld_param_cnt; i++)
       SAYF(" \"%s\"", ld_params[i]);
     SAYF("\n");
@@ -333,7 +333,7 @@ int main(int argc, char **argv) {
   if (pid < 0) PFATAL("fork() failed");
 
   if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
-  if (debug) SAYF(cMGN "[D] " cRST "linker result: %d\n", status);
+  if (debug) DEBUGF("linker result: %d\n", status);
 
   if (!just_version) {
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 4b357254..e07e76c8 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -667,6 +667,8 @@ static void usage(u8 *argv0) {
       "AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
       "inputs\n"
       "AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
+      "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
+      "crash\n"
       "AFL_DEBUG: enable extra developer output\n"
       "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
       "size\n"
@@ -904,7 +906,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (getenv("AFL_DEBUG")) {
 
-    SAYF(cMGN "[D]" cRST);
+    DEBUGF("");
     for (i = 0; i < argc; i++)
       SAYF(" %s", argv[i]);
     SAYF("\n");
@@ -1066,7 +1068,7 @@ int main(int argc, char **argv_orig, char **envp) {
     if (get_afl_env("AFL_DEBUG")) {
 
       int i = optind;
-      SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path);
+      DEBUGF("%s:", fsrv->target_path);
       while (argv[i] != NULL) {
 
         SAYF(" \"%s\"", argv[i++]);
@@ -1090,8 +1092,29 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+    if (getenv("AFL_CRASH_EXITCODE")) {
+
+      long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
+      if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+          exitcode < -127 || exitcode > 128) {
+
+        FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+              getenv("AFL_CRASH_EXITCODE"));
+
+      }
+
+      fsrv->uses_crash_exitcode = true;
+      // WEXITSTATUS is 8 bit unsigned
+      fsrv->crash_exitcode = (u8)exitcode;
+
+    }
+
     afl_fsrv_start(fsrv, use_argv, &stop_soon,
-                   get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+                   (get_afl_env("AFL_DEBUG_CHILD") ||
+                    get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+                       ? 1
+                       : 0);
+
     map_size = fsrv->map_size;
 
     if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 06037d61..b9045551 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -51,6 +51,7 @@
 #include <signal.h>
 #include <dirent.h>
 #include <fcntl.h>
+#include <limits.h>
 
 #include <sys/wait.h>
 #include <sys/time.h>
@@ -841,17 +842,17 @@ static void usage(u8 *argv0) {
       "For additional tips, please consult %s/README.md.\n\n"
 
       "Environment variables used:\n"
-      "TMPDIR: directory to use for temporary input files\n"
-      "ASAN_OPTIONS: custom settings for ASAN\n"
-      "              (must contain abort_on_error=1 and symbolize=0)\n"
-      "MSAN_OPTIONS: custom settings for MSAN\n"
-      "              (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
+      "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
+      "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
       "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
       "              the target was compiled for\n"
       "AFL_PRELOAD:  LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
-      "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
-
+      "ASAN_OPTIONS: custom settings for ASAN\n"
+      "              (must contain abort_on_error=1 and symbolize=0)\n"
+      "MSAN_OPTIONS: custom settings for MSAN\n"
+      "              (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
+      "TMPDIR: directory to use for temporary input files\n"
       , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
 
   exit(1);
@@ -1122,6 +1123,23 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+  if (getenv("AFL_CRASH_EXITCODE")) {
+
+    long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
+    if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+        exitcode < -127 || exitcode > 128) {
+
+      FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+            getenv("AFL_CRASH_EXITCODE"));
+
+    }
+
+    fsrv->uses_crash_exitcode = true;
+    // WEXITSTATUS is 8 bit unsigned
+    fsrv->crash_exitcode = (u8)exitcode;
+
+  }
+
   shm_fuzz = ck_alloc(sizeof(sharedmem_t));
 
   /* initialize cmplog_mode */
@@ -1141,8 +1159,11 @@ int main(int argc, char **argv_orig, char **envp) {
 
   read_initial_file();
 
-  afl_fsrv_start(fsrv, use_argv, &stop_soon,
-                 get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+  afl_fsrv_start(
+      fsrv, use_argv, &stop_soon,
+      (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+          ? 1
+          : 0);
 
   if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
     shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
diff --git a/test/test-custom-mutators.sh b/test/test-custom-mutators.sh
index d4d21048..24c95ac7 100755
--- a/test/test-custom-mutators.sh
+++ b/test/test-custom-mutators.sh
@@ -5,7 +5,7 @@
 $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)
+  CUSTOM_MUTATOR_PATH=$(cd $(pwd)/../utils/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
@@ -29,8 +29,8 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
       }
     }
     # 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
+    cc -D_FIXED_CHAR=0x41 -g -fPIC -shared -I../include ../utils/custom_mutators/simple_example.c -o libexamplemutator.so > /dev/null 2>&1
+    cc -D_FIXED_CHAR=0x42 -g -fPIC -shared -I../include ../utils/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
@@ -109,7 +109,7 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
 
     #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
+    make -C ../utils/custom_mutators clean > /dev/null 2>&1
     rm -f test-custom-mutator
     rm -f test-custom-mutators
   } || {
diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh
index b0ff2be0..71d86364 100755
--- a/test/test-gcc-plugin.sh
+++ b/test/test-gcc-plugin.sh
@@ -94,7 +94,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
     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
+  ../afl-gcc-fast -o test-persistent ../utils/persistent_mode/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"
diff --git a/test/test-llvm-lto.sh b/test/test-llvm-lto.sh
index 6b327633..d0b8f8fc 100755
--- a/test/test-llvm-lto.sh
+++ b/test/test-llvm-lto.sh
@@ -57,7 +57,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
     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
+  ../afl-clang-lto -o test-persistent ../utils/persistent_mode/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"
diff --git a/test/test-llvm.sh b/test/test-llvm.sh
index 7daac0f2..4fcaf367 100755
--- a/test/test-llvm.sh
+++ b/test/test-llvm.sh
@@ -209,7 +209,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
     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
+  ../afl-clang-fast -o test-persistent ../utils/persistent_mode/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"
diff --git a/test/test-pre.sh b/test/test-pre.sh
index fc14ee0b..4c708a68 100755
--- a/test/test-pre.sh
+++ b/test/test-pre.sh
@@ -135,4 +135,4 @@ test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
 CODE=0
 INCOMPLETE=0
 
-fi
\ No newline at end of file
+fi
diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh
index 7ac4cdd2..b4c6eb3e 100755
--- a/test/test-unicorn-mode.sh
+++ b/test/test-unicorn-mode.sh
@@ -7,7 +7,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
   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
+      export AFL_DEBUG_CHILD=1
 
       # some python version should be available now
       PYTHONS="`command -v python3` `command -v python` `command -v python2`"
@@ -34,7 +34,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
       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
+      AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
       test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && {
         $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)"
       } || {
@@ -96,7 +96,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
       }
       fi
 
-      unset AFL_DEBUG_CHILD_OUTPUT
+      unset AFL_DEBUG_CHILD
 
     }
   } || {
diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION
index c5569fbd..99025a06 100644
--- a/unicorn_mode/UNICORNAFL_VERSION
+++ b/unicorn_mode/UNICORNAFL_VERSION
@@ -1 +1 @@
-f44ec48f
+8cca4801
diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh
index b4d2058f..f1306a06 100755
--- a/unicorn_mode/build_unicorn_support.sh
+++ b/unicorn_mode/build_unicorn_support.sh
@@ -149,7 +149,7 @@ git status 1>/dev/null 2>/dev/null
 if [ $? -eq 0 ]; then
   echo "[*] initializing unicornafl submodule"
   git submodule init || exit 1
-  git submodule update 2>/dev/null # ignore errors
+  git submodule update ./unicornafl 2>/dev/null # ignore errors
 else
   echo "[*] cloning unicornafl"
   test -d unicornafl || {
diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py b/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
index 22b9fd47..8c8f9641 100644
--- a/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
+++ b/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
@@ -1,13 +1,13 @@
 """
     unicorn_dumper_gdb.py
-    
+
     When run with GDB sitting at a debug breakpoint, this
     dumps the current state (registers/memory/etc) of
-    the process to a directory consisting of an index 
-    file with register and segment information and 
+    the process to a directory consisting of an index
+    file with register and segment information and
     sub-files containing all actual process memory.
-    
-    The output of this script is expected to be used 
+
+    The output of this script is expected to be used
     to initialize context for Unicorn emulation.
 
     -----------
@@ -44,6 +44,7 @@ MAX_SEG_SIZE = 128 * 1024 * 1024
 # Name of the index file
 INDEX_FILE_NAME = "_index.json"
 
+
 #----------------------
 #---- Helper Functions
 
@@ -59,14 +60,14 @@ def map_arch():
         return "arm64be"
     elif 'armeb' in arch:
         # check for THUMB mode
-        cpsr = get_register('cpsr')
+        cpsr = get_register('$cpsr')
         if (cpsr & (1 << 5)):
             return "armbethumb"
         else:
             return "armbe"
     elif 'arm' in arch:
         # check for THUMB mode
-        cpsr = get_register('cpsr')
+        cpsr = get_register('$cpsr')
         if (cpsr & (1 << 5)):
             return "armlethumb"
         else:
@@ -88,19 +89,15 @@ def dump_regs():
     reg_state = {}
     for reg in current_arch.all_registers:
         reg_val = get_register(reg)
-        # current dumper script looks for register values to be hex strings
-#         reg_str = "0x{:08x}".format(reg_val)
-#         if "64" in get_arch():
-#             reg_str = "0x{:016x}".format(reg_val)
-#         reg_state[reg.strip().strip('$')] = reg_str
         reg_state[reg.strip().strip('$')] = reg_val
+
     return reg_state
 
 
 def dump_process_memory(output_dir):
     # Segment information dictionary
     final_segment_list = []
-    
+
     # GEF:
     vmmap = get_process_maps()
     if not vmmap:
@@ -110,7 +107,7 @@ def dump_process_memory(output_dir):
     for entry in vmmap:
         if entry.page_start == entry.page_end:
             continue
-        
+
         seg_info = {'start': entry.page_start, 'end': entry.page_end, 'name': entry.path, 'permissions': {
             "r": entry.is_readable() > 0,
             "w": entry.is_writable() > 0,
@@ -129,7 +126,7 @@ def dump_process_memory(output_dir):
                     compressed_seg_content = zlib.compress(seg_content)
                     md5_sum = hashlib.md5(compressed_seg_content).hexdigest() + ".bin"
                     seg_info["content_file"] = md5_sum
-                    
+
                     # Write the compressed contents to disk
                     out_file = open(os.path.join(output_dir, md5_sum), 'wb')
                     out_file.write(compressed_seg_content)
@@ -143,12 +140,27 @@ def dump_process_memory(output_dir):
         # Add the segment to the list
         final_segment_list.append(seg_info)
 
-            
+
     return final_segment_list
 
+#---------------------------------------------
+#---- ARM Extention (dump floating point regs)
+
+def dump_float(rge=32):
+    reg_convert = ""
+    if map_arch() == "armbe" or map_arch() == "armle" or map_arch() == "armbethumb" or map_arch() == "armbethumb":
+        reg_state = {}
+        for reg_num in range(32):
+            value = gdb.selected_frame().read_register("d" + str(reg_num))
+            reg_state["d" + str(reg_num)] = int(str(value["u64"]), 16)
+        value = gdb.selected_frame().read_register("fpscr")
+        reg_state["fpscr"] = int(str(value), 16)
+
+        return reg_state
+
 #----------
-#---- Main    
-    
+#---- Main
+
 def main():
     print("----- Unicorn Context Dumper -----")
     print("You must be actively debugging before running this!")
@@ -159,32 +171,32 @@ def main():
         print("!!! GEF not running in GDB.  Please run gef.py by executing:")
         print('\tpython execfile ("<path_to_gef>/gef.py")')
         return
-    
+
     try:
-    
+
         # Create the output directory
         timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y%m%d_%H%M%S')
         output_path = "UnicornContext_" + timestamp
         if not os.path.exists(output_path):
             os.makedirs(output_path)
         print("Process context will be output to {}".format(output_path))
-            
+
         # Get the context
         context = {
             "arch": dump_arch_info(),
-            "regs": dump_regs(), 
+            "regs": dump_regs(),
+            "regs_extended": dump_float(),
             "segments": dump_process_memory(output_path),
         }
 
         # Write the index file
         index_file = open(os.path.join(output_path, INDEX_FILE_NAME), 'w')
         index_file.write(json.dumps(context, indent=4))
-        index_file.close()    
+        index_file.close()
         print("Done.")
-        
+
     except Exception as e:
         print("!!! ERROR:\n\t{}".format(repr(e)))
-        
+
 if __name__ == "__main__":
     main()
-    
diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_ida.py b/unicorn_mode/helper_scripts/unicorn_dumper_ida.py
index 6cf9f30f..3f955a5c 100644
--- a/unicorn_mode/helper_scripts/unicorn_dumper_ida.py
+++ b/unicorn_mode/helper_scripts/unicorn_dumper_ida.py
@@ -206,4 +206,4 @@ def main():
         print("!!! ERROR:\n\t{}".format(str(e)))
         
 if __name__ == "__main__":
-    main()
+    main()
\ No newline at end of file
diff --git a/unicorn_mode/helper_scripts/unicorn_loader.py b/unicorn_mode/helper_scripts/unicorn_loader.py
index adf21b64..1914a83d 100644
--- a/unicorn_mode/helper_scripts/unicorn_loader.py
+++ b/unicorn_mode/helper_scripts/unicorn_loader.py
@@ -1,8 +1,8 @@
 """
     unicorn_loader.py
-    
-    Loads a process context dumped created using a 
-    Unicorn Context Dumper script into a Unicorn Engine 
+
+    Loads a process context dumped created using a
+    Unicorn Context Dumper script into a Unicorn Engine
     instance. Once this is performed emulation can be
     started.
 """
@@ -26,6 +26,13 @@ from unicorn.arm64_const import *
 from unicorn.x86_const import *
 from unicorn.mips_const import *
 
+# If Capstone libraries are availible (only check once)
+try:
+    from capstone import *
+    CAPSTONE_EXISTS = 1
+except:
+    CAPSTONE_EXISTS = 0
+
 # Name of the index file
 INDEX_FILE_NAME = "_index.json"
 
@@ -86,7 +93,7 @@ class UnicornSimpleHeap(object):
         total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE
         # Gross but efficient way to find space for the chunk:
         chunk = None
-        for addr in xrange(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
+        for addr in range(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
             try:
                 self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
                 chunk = self.HeapChunk(addr, total_chunk_size, size)
@@ -97,7 +104,7 @@ class UnicornSimpleHeap(object):
                 continue
         # Something went very wrong
         if chunk == None:
-            return 0    
+            return 0
         self._chunks.append(chunk)
         return chunk.data_addr
 
@@ -112,8 +119,8 @@ class UnicornSimpleHeap(object):
         old_chunk = None
         for chunk in self._chunks:
             if chunk.data_addr == ptr:
-                old_chunk = chunk 
-        new_chunk_addr = self.malloc(new_size) 
+                old_chunk = chunk
+        new_chunk_addr = self.malloc(new_size)
         if old_chunk != None:
             self._uc.mem_write(new_chunk_addr, str(self._uc.mem_read(old_chunk.data_addr, old_chunk.data_size)))
             self.free(old_chunk.data_addr)
@@ -184,39 +191,27 @@ class AflUnicornEngine(Uc):
         # Load the registers
         regs = context['regs']
         reg_map = self.__get_register_map(self._arch_str)
-        for register, value in regs.iteritems():
-            if debug_print:
-                print("Reg {0} = {1}".format(register, value))
-            if not reg_map.has_key(register.lower()):
-                if debug_print:
-                    print("Skipping Reg: {}".format(register))
-            else:
-                reg_write_retry = True
-                try:
-                    self.reg_write(reg_map[register.lower()], value)
-                    reg_write_retry = False
-                except Exception as e:
-                    if debug_print:
-                        print("ERROR writing register: {}, value: {} -- {}".format(register, value, repr(e)))
+        self.__load_registers(regs, reg_map, debug_print)
+        # If we have extra FLOATING POINT regs, load them in!
+        if 'regs_extended' in context:
+		if context['regs_extended']:
+		    regs_extended = context['regs_extended']
+		    reg_map = self.__get_registers_extended(self._arch_str)
+		    self.__load_registers(regs_extended, reg_map, debug_print)
+
+        # For ARM, sometimes the stack pointer is erased ??? (I think I fixed this (issue with ordering of dumper.py, I'll keep the write anyways)
+        if self.__get_arch_and_mode(self.get_arch_str())[0] == UC_ARCH_ARM:
+            self.reg_write(UC_ARM_REG_SP, regs['sp'])
 
-                if reg_write_retry:
-                    if debug_print:
-                        print("Trying to parse value ({}) as hex string".format(value))
-                    try:
-                        self.reg_write(reg_map[register.lower()], int(value, 16))
-                    except Exception as e:
-                        if debug_print:
-                            print("ERROR writing hex string register: {}, value: {} -- {}".format(register, value, repr(e)))
-                        
         # Setup the memory map and load memory content
         self.__map_segments(context['segments'], context_directory, debug_print)
-        
+
         if enable_trace:
             self.hook_add(UC_HOOK_BLOCK, self.__trace_block)
             self.hook_add(UC_HOOK_CODE, self.__trace_instruction)
             self.hook_add(UC_HOOK_MEM_WRITE | UC_HOOK_MEM_READ, self.__trace_mem_access)
             self.hook_add(UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_READ_INVALID, self.__trace_mem_invalid_access)
-            
+
         if debug_print:
             print("Done loading context.")
 
@@ -228,7 +223,7 @@ class AflUnicornEngine(Uc):
 
     def get_arch_str(self):
         return self._arch_str
-                    
+
     def force_crash(self, uc_error):
         """ This function should be called to indicate to AFL that a crash occurred during emulation.
             You can pass the exception received from Uc.emu_start
@@ -253,21 +248,76 @@ class AflUnicornEngine(Uc):
         for reg in sorted(self.__get_register_map(self._arch_str).items(), key=lambda reg: reg[0]):
             print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
 
+    def dump_regs_extended(self):
+        """ Dumps the contents of all the registers to STDOUT """
+        try:
+            for reg in sorted(self.__get_registers_extended(self._arch_str).items(), key=lambda reg: reg[0]):
+                print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
+        except Exception as e:
+            print("ERROR: Are extended registers loaded?")
+
     # TODO: Make this dynamically get the stack pointer register and pointer width for the current architecture
     """
     def dump_stack(self, window=10):
+        arch = self.get_arch()
+        mode = self.get_mode()
+        # Get stack pointers and bit sizes for given architecture
+        if arch == UC_ARCH_X86 and mode == UC_MODE_64:
+            stack_ptr_addr = self.reg_read(UC_X86_REG_RSP)
+            bit_size = 8
+        elif arch == UC_ARCH_X86 and mode == UC_MODE_32:
+            stack_ptr_addr = self.reg_read(UC_X86_REG_ESP)
+            bit_size = 4
+        elif arch == UC_ARCH_ARM64:
+            stack_ptr_addr = self.reg_read(UC_ARM64_REG_SP)
+            bit_size = 8
+        elif arch == UC_ARCH_ARM:
+            stack_ptr_addr = self.reg_read(UC_ARM_REG_SP)
+            bit_size = 4
+        elif arch == UC_ARCH_ARM and mode == UC_MODE_THUMB:
+            stack_ptr_addr = self.reg_read(UC_ARM_REG_SP)
+            bit_size = 4
+        elif arch == UC_ARCH_MIPS:
+            stack_ptr_addr = self.reg_read(UC_MIPS_REG_SP)
+            bit_size = 4
+        print("")
         print(">>> Stack:")
         stack_ptr_addr = self.reg_read(UC_X86_REG_RSP)
         for i in xrange(-window, window + 1):
             addr = stack_ptr_addr + (i*8)
             print("{0}0x{1:016x}: 0x{2:016x}".format( \
-                'SP->' if i == 0 else '    ', addr, \
+               'SP->' if i == 0 else '    ', addr, \
                 struct.unpack('<Q', self.mem_read(addr, 8))[0]))
     """
 
     #-----------------------------
     #---- Loader Helper Functions
 
+    def __load_registers(self, regs, reg_map, debug_print):
+        for register, value in regs.items():
+            if debug_print:
+                print("Reg {0} = {1}".format(register, value))
+            if register.lower() not in reg_map:
+                if debug_print:
+                    print("Skipping Reg: {}".format(register))
+            else:
+                reg_write_retry = True
+                try:
+                    self.reg_write(reg_map[register.lower()], value)
+                    reg_write_retry = False
+                except Exception as e:
+                    if debug_print:
+                        print("ERROR writing register: {}, value: {} -- {}".format(register, value, repr(e)))
+
+                if reg_write_retry:
+                    if debug_print:
+                        print("Trying to parse value ({}) as hex string".format(value))
+                    try:
+                        self.reg_write(reg_map[register.lower()], int(value, 16))
+                    except Exception as e:
+                        if debug_print:
+                            print("ERROR writing hex string register: {}, value: {} -- {}".format(register, value, repr(e)))
+
     def __map_segment(self, name, address, size, perms, debug_print=False):
         # - size is unsigned and must be != 0
         # - starting address must be aligned to 4KB
@@ -289,7 +339,7 @@ class AflUnicornEngine(Uc):
 
     def __map_segments(self, segment_list, context_directory, debug_print=False):
         for segment in segment_list:
-            
+
             # Get the segment information from the index
             name = segment['name']
             seg_start = segment['start']
@@ -297,7 +347,7 @@ class AflUnicornEngine(Uc):
             perms = \
                 (UC_PROT_READ  if segment['permissions']['r'] == True else 0) | \
                 (UC_PROT_WRITE if segment['permissions']['w'] == True else 0) | \
-                (UC_PROT_EXEC  if segment['permissions']['x'] == True else 0)        
+                (UC_PROT_EXEC  if segment['permissions']['x'] == True else 0)
 
             if debug_print:
                 print("Handling segment {}".format(name))
@@ -349,12 +399,12 @@ class AflUnicornEngine(Uc):
                 content_file = open(content_file_path, 'rb')
                 compressed_content = content_file.read()
                 content_file.close()
-                self.mem_write(seg_start, zlib.decompress(compressed_content)) 
+                self.mem_write(seg_start, zlib.decompress(compressed_content))
 
             else:
                 if debug_print:
                     print("No content found for segment {0} @ {1:016x}".format(name, seg_start))
-                self.mem_write(seg_start, '\x00' * (seg_end - seg_start))
+                self.mem_write(seg_start, b'\x00' * (seg_end - seg_start))
 
     def __get_arch_and_mode(self, arch_str):
         arch_map = {
@@ -398,7 +448,6 @@ class AflUnicornEngine(Uc):
                 "r14":    UC_X86_REG_R14,
                 "r15":    UC_X86_REG_R15,
                 "rip":    UC_X86_REG_RIP,
-                "rsp":    UC_X86_REG_RSP,
                 "efl":    UC_X86_REG_EFLAGS,
                 "cs":     UC_X86_REG_CS,
                 "ds":     UC_X86_REG_DS,
@@ -415,13 +464,12 @@ class AflUnicornEngine(Uc):
                 "esi":    UC_X86_REG_ESI,
                 "edi":    UC_X86_REG_EDI,
                 "ebp":    UC_X86_REG_EBP,
-                "esp":    UC_X86_REG_ESP,
                 "eip":    UC_X86_REG_EIP,
                 "esp":    UC_X86_REG_ESP,
-                "efl":    UC_X86_REG_EFLAGS,        
+                "efl":    UC_X86_REG_EFLAGS,
                 # Segment registers removed...
                 # They caused segfaults (from unicorn?) when they were here
-            },        
+            },
             "arm" : {
                 "r0":     UC_ARM_REG_R0,
                 "r1":     UC_ARM_REG_R1,
@@ -476,7 +524,7 @@ class AflUnicornEngine(Uc):
                 "fp":     UC_ARM64_REG_FP,
                 "lr":     UC_ARM64_REG_LR,
                 "nzcv":   UC_ARM64_REG_NZCV,
-                "cpsr": UC_ARM_REG_CPSR, 
+                "cpsr": UC_ARM_REG_CPSR,
             },
             "mips" : {
                 "0" :     UC_MIPS_REG_ZERO,
@@ -499,13 +547,13 @@ class AflUnicornEngine(Uc):
                 "t9":     UC_MIPS_REG_T9,
                 "s0":     UC_MIPS_REG_S0,
                 "s1":     UC_MIPS_REG_S1,
-                "s2":     UC_MIPS_REG_S2,    
+                "s2":     UC_MIPS_REG_S2,
                 "s3":     UC_MIPS_REG_S3,
                 "s4":     UC_MIPS_REG_S4,
                 "s5":     UC_MIPS_REG_S5,
-                "s6":     UC_MIPS_REG_S6,              
+                "s6":     UC_MIPS_REG_S6,
                 "s7":     UC_MIPS_REG_S7,
-                "s8":     UC_MIPS_REG_S8,  
+                "s8":     UC_MIPS_REG_S8,
                 "k0":     UC_MIPS_REG_K0,
                 "k1":     UC_MIPS_REG_K1,
                 "gp":     UC_MIPS_REG_GP,
@@ -517,44 +565,127 @@ class AflUnicornEngine(Uc):
                 "lo":     UC_MIPS_REG_LO
             }
         }
-        return registers[arch]   
+        return registers[arch]
 
+    def __get_registers_extended(self, arch):
+        # Similar to __get_register_map, but for ARM floating point registers
+        if arch == "arm64le" or arch == "arm64be":
+            arch = "arm64"
+        elif arch == "armle" or arch == "armbe" or "thumb" in arch:
+            arch = "arm"
+        elif arch == "mipsel":
+            arch = "mips"
+
+        registers = {
+        "arm": {
+            "d0": UC_ARM_REG_D0,
+            "d1": UC_ARM_REG_D1,
+            "d2": UC_ARM_REG_D2,
+            "d3": UC_ARM_REG_D3,
+            "d4": UC_ARM_REG_D4,
+            "d5": UC_ARM_REG_D5,
+            "d6": UC_ARM_REG_D6,
+            "d7": UC_ARM_REG_D7,
+            "d8": UC_ARM_REG_D8,
+            "d9": UC_ARM_REG_D9,
+            "d10": UC_ARM_REG_D10,
+            "d11": UC_ARM_REG_D11,
+            "d12": UC_ARM_REG_D12,
+            "d13": UC_ARM_REG_D13,
+            "d14": UC_ARM_REG_D14,
+            "d15": UC_ARM_REG_D15,
+            "d16": UC_ARM_REG_D16,
+            "d17": UC_ARM_REG_D17,
+            "d18": UC_ARM_REG_D18,
+            "d19": UC_ARM_REG_D19,
+            "d20": UC_ARM_REG_D20,
+            "d21": UC_ARM_REG_D21,
+            "d22": UC_ARM_REG_D22,
+            "d23": UC_ARM_REG_D23,
+            "d24": UC_ARM_REG_D24,
+            "d25": UC_ARM_REG_D25,
+            "d26": UC_ARM_REG_D26,
+            "d27": UC_ARM_REG_D27,
+            "d28": UC_ARM_REG_D28,
+            "d29": UC_ARM_REG_D29,
+            "d30": UC_ARM_REG_D30,
+            "d31": UC_ARM_REG_D31,
+            "fpscr": UC_ARM_REG_FPSCR
+            }
+        }
+
+        return registers[arch];
     #---------------------------
-    # Callbacks for tracing 
+    # Callbacks for tracing
 
-    # TODO: Make integer-printing fixed widths dependent on bitness of architecture 
-    #       (i.e. only show 4 bytes for 32-bit, 8 bytes for 64-bit)
 
-    # TODO: Figure out how best to determine the capstone mode and architecture here
-    """
-    try:
-        # If Capstone is installed then we'll dump disassembly, otherwise just dump the binary.
-        from capstone import *
-        cs = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN)
-        def __trace_instruction(self, uc, address, size, user_data):
-            mem = uc.mem_read(address, size)
-            for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
-                print("    Instr: {:#016x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
-    except ImportError:
-        def __trace_instruction(self, uc, address, size, user_data):
-            print("    Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))    
-    """
+    # TODO: Extra mode for Capstone (i.e. Cs(cs_arch, cs_mode + cs_extra) not implemented
+
 
     def __trace_instruction(self, uc, address, size, user_data):
-        print("    Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))  
-        
+        if CAPSTONE_EXISTS == 1:
+            # If Capstone is installed then we'll dump disassembly, otherwise just dump the binary.
+            arch = self.get_arch()
+            mode = self.get_mode()
+            bit_size = self.bit_size_arch()
+            # Map current arch to capstone labeling
+            if arch == UC_ARCH_X86 and mode == UC_MODE_64:
+                cs_arch = CS_ARCH_X86
+                cs_mode = CS_MODE_64
+            elif arch == UC_ARCH_X86 and mode == UC_MODE_32:
+                cs_arch = CS_ARCH_X86
+                cs_mode = CS_MODE_32
+            elif arch == UC_ARCH_ARM64:
+                cs_arch = CS_ARCH_ARM64
+                cs_mode = CS_MODE_ARM
+            elif arch == UC_ARCH_ARM and mode == UC_MODE_THUMB:
+                cs_arch = CS_ARCH_ARM
+                cs_mode = CS_MODE_THUMB
+            elif arch == UC_ARCH_ARM:
+                cs_arch = CS_ARCH_ARM
+                cs_mode = CS_MODE_ARM
+            elif arch == UC_ARCH_MIPS:
+                cs_arch = CS_ARCH_MIPS
+                cs_mode = CS_MODE_MIPS32  # No other MIPS supported in program
+
+            cs = Cs(cs_arch, cs_mode)
+            mem = uc.mem_read(address, size)
+            if bit_size == 4:
+                for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
+                    print("    Instr: {:#08x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
+            else:
+                for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
+                    print("    Instr: {:#16x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
+        else:
+            print("    Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))
+
     def __trace_block(self, uc, address, size, user_data):
         print("Basic Block: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))
-      
+
     def __trace_mem_access(self, uc, access, address, size, value, user_data):
         if access == UC_MEM_WRITE:
             print("        >>> Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(address, size, value))
         else:
-            print("        >>> Read: addr=0x{0:016x} size={1}".format(address, size))    
+            print("        >>> Read: addr=0x{0:016x} size={1}".format(address, size))
 
     def __trace_mem_invalid_access(self, uc, access, address, size, value, user_data):
         if access == UC_MEM_WRITE_UNMAPPED:
             print("        >>> INVALID Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(address, size, value))
         else:
-            print("        >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))   
-
+            print("        >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))
+
+    def bit_size_arch(self):
+        arch = self.get_arch()
+        mode = self.get_mode()
+        # Get bit sizes for given architecture
+        if arch == UC_ARCH_X86 and mode == UC_MODE_64:
+            bit_size = 8
+        elif arch == UC_ARCH_X86 and mode == UC_MODE_32:
+            bit_size = 4
+        elif arch == UC_ARCH_ARM64:
+            bit_size = 8
+        elif arch == UC_ARCH_ARM:
+            bit_size = 4
+        elif arch == UC_ARCH_MIPS:
+            bit_size = 4
+        return bit_size
diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl
-Subproject c6d6647161a32bae88785a618fcd828d1711d9e
+Subproject 8cca4801adb767dce7cf72202d7d25bdb420cf7
diff --git a/examples/README.md b/utils/README.md
index 46a92c6e..336b6b6c 100644
--- a/examples/README.md
+++ b/utils/README.md
@@ -39,13 +39,13 @@ Here's a quick overview of the stuff you can find in this directory:
 
   - libpng_no_checksum   - a sample patch for removing CRC checks in libpng.
 
-  - persistent_demo      - an example of how to use the LLVM persistent process
+  - persistent_mode      - an example of how to use the LLVM persistent process
                            mode to speed up certain fuzzing jobs.
 
   - socket_fuzzing       - a LD_PRELOAD library 'redirects' a socket to stdin
                            for fuzzing access with afl++
 
-Note that the minimize_corpus.sh tool has graduated from the examples/
+Note that the minimize_corpus.sh tool has graduated from the utils/
 directory and is now available as ../afl-cmin. The LLVM mode has likewise
 graduated to ../instrumentation/*.
 
diff --git a/examples/afl_frida/GNUmakefile b/utils/afl_frida/GNUmakefile
index c154f3a4..c154f3a4 100644
--- a/examples/afl_frida/GNUmakefile
+++ b/utils/afl_frida/GNUmakefile
diff --git a/examples/afl_frida/Makefile b/utils/afl_frida/Makefile
index 0b306dde..0b306dde 100644
--- a/examples/afl_frida/Makefile
+++ b/utils/afl_frida/Makefile
diff --git a/examples/afl_frida/README.md b/utils/afl_frida/README.md
index 7743479b..7743479b 100644
--- a/examples/afl_frida/README.md
+++ b/utils/afl_frida/README.md
diff --git a/examples/afl_frida/afl-frida.c b/utils/afl_frida/afl-frida.c
index 31bf8f25..31bf8f25 100644
--- a/examples/afl_frida/afl-frida.c
+++ b/utils/afl_frida/afl-frida.c
diff --git a/examples/afl_frida/afl-frida.h b/utils/afl_frida/afl-frida.h
index efa3440f..efa3440f 100644
--- a/examples/afl_frida/afl-frida.h
+++ b/utils/afl_frida/afl-frida.h
diff --git a/examples/afl_frida/libtestinstr.c b/utils/afl_frida/libtestinstr.c
index 96b1cf21..96b1cf21 100644
--- a/examples/afl_frida/libtestinstr.c
+++ b/utils/afl_frida/libtestinstr.c
diff --git a/examples/afl_network_proxy/GNUmakefile b/utils/afl_network_proxy/GNUmakefile
index 25a3df82..25a3df82 100644
--- a/examples/afl_network_proxy/GNUmakefile
+++ b/utils/afl_network_proxy/GNUmakefile
diff --git a/examples/afl_network_proxy/Makefile b/utils/afl_network_proxy/Makefile
index 0b306dde..0b306dde 100644
--- a/examples/afl_network_proxy/Makefile
+++ b/utils/afl_network_proxy/Makefile
diff --git a/examples/afl_network_proxy/README.md b/utils/afl_network_proxy/README.md
index a5ac3578..a5ac3578 100644
--- a/examples/afl_network_proxy/README.md
+++ b/utils/afl_network_proxy/README.md
diff --git a/examples/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c
index a2451fdc..a2451fdc 100644
--- a/examples/afl_network_proxy/afl-network-client.c
+++ b/utils/afl_network_proxy/afl-network-client.c
diff --git a/examples/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c
index 75eb3d20..513dc8f2 100644
--- a/examples/afl_network_proxy/afl-network-server.c
+++ b/utils/afl_network_proxy/afl-network-server.c
@@ -358,8 +358,8 @@ int recv_testcase(int s, void **buf) {
 
   if ((size & 0xff000000) != 0xff000000) {
 
-    *buf = afl_realloc((void **)&buf, size);
-    if (unlikely(!buf)) { PFATAL("Alloc"); }
+    *buf = afl_realloc(buf, size);
+    if (unlikely(!*buf)) { PFATAL("Alloc"); }
     received = 0;
     // fprintf(stderr, "unCOMPRESS (%u)\n", size);
     while (received < size &&
@@ -371,8 +371,8 @@ int recv_testcase(int s, void **buf) {
 #ifdef USE_DEFLATE
     u32 clen;
     size -= 0xff000000;
-    *buf = afl_realloc((void **)&buf, size);
-    if (unlikely(!buf)) { PFATAL("Alloc"); }
+    *buf = afl_realloc(buf, size);
+    if (unlikely(!*buf)) { PFATAL("Alloc"); }
     received = 0;
     while (received < 4 &&
            (ret = recv(s, &clen + received, 4 - received, 0)) > 0)
@@ -636,8 +636,11 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (listen(sock, 1) < 0) { PFATAL("listen() failed"); }
 
-  afl_fsrv_start(fsrv, use_argv, &stop_soon,
-                 get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+  afl_fsrv_start(
+      fsrv, use_argv, &stop_soon,
+      (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+          ? 1
+          : 0);
 
 #ifdef USE_DEFLATE
   compressor = libdeflate_alloc_compressor(1);
diff --git a/examples/afl_proxy/Makefile b/utils/afl_proxy/Makefile
index 4b368f8d..4b368f8d 100644
--- a/examples/afl_proxy/Makefile
+++ b/utils/afl_proxy/Makefile
diff --git a/examples/afl_proxy/README.md b/utils/afl_proxy/README.md
index 3c768a19..3c768a19 100644
--- a/examples/afl_proxy/README.md
+++ b/utils/afl_proxy/README.md
diff --git a/examples/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c
index f2dfeac1..f2dfeac1 100644
--- a/examples/afl_proxy/afl-proxy.c
+++ b/utils/afl_proxy/afl-proxy.c
diff --git a/examples/afl_untracer/Makefile b/utils/afl_untracer/Makefile
index 14a09b41..14a09b41 100644
--- a/examples/afl_untracer/Makefile
+++ b/utils/afl_untracer/Makefile
diff --git a/examples/afl_untracer/README.md b/utils/afl_untracer/README.md
index ada0c916..ada0c916 100644
--- a/examples/afl_untracer/README.md
+++ b/utils/afl_untracer/README.md
diff --git a/examples/afl_untracer/TODO b/utils/afl_untracer/TODO
index fffffacf..fffffacf 100644
--- a/examples/afl_untracer/TODO
+++ b/utils/afl_untracer/TODO
diff --git a/examples/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c
index cb6f948c..cb6f948c 100644
--- a/examples/afl_untracer/afl-untracer.c
+++ b/utils/afl_untracer/afl-untracer.c
diff --git a/examples/afl_untracer/ghidra_get_patchpoints.java b/utils/afl_untracer/ghidra_get_patchpoints.java
index d341bea4..2a93642b 100644
--- a/examples/afl_untracer/ghidra_get_patchpoints.java
+++ b/utils/afl_untracer/ghidra_get_patchpoints.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-// Find patch points for untracer tools (e.g. afl++ examples/afl_untracer)
+// Find patch points for untracer tools (e.g. afl++ utils/afl_untracer)
 //
 //   Copy to ..../Ghidra/Features/Search/ghidra_scripts/
 //   Writes the results to ~/Desktop/patches.txt
diff --git a/examples/afl_untracer/ida_get_patchpoints.py b/utils/afl_untracer/ida_get_patchpoints.py
index 43cf6d89..43cf6d89 100644
--- a/examples/afl_untracer/ida_get_patchpoints.py
+++ b/utils/afl_untracer/ida_get_patchpoints.py
diff --git a/examples/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c
index 96b1cf21..96b1cf21 100644
--- a/examples/afl_untracer/libtestinstr.c
+++ b/utils/afl_untracer/libtestinstr.c
diff --git a/examples/afl_untracer/patches.txt b/utils/afl_untracer/patches.txt
index 7e964249..7e964249 100644
--- a/examples/afl_untracer/patches.txt
+++ b/utils/afl_untracer/patches.txt
diff --git a/examples/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile
index c1a087d7..c1a087d7 100644
--- a/examples/aflpp_driver/GNUmakefile
+++ b/utils/aflpp_driver/GNUmakefile
diff --git a/examples/aflpp_driver/Makefile b/utils/aflpp_driver/Makefile
index 3666a74d..3666a74d 100644
--- a/examples/aflpp_driver/Makefile
+++ b/utils/aflpp_driver/Makefile
diff --git a/examples/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index 017aa72b..017aa72b 100644
--- a/examples/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
diff --git a/examples/aflpp_driver/aflpp_driver_test.c b/utils/aflpp_driver/aflpp_driver_test.c
index b4ff6bc6..b4ff6bc6 100644
--- a/examples/aflpp_driver/aflpp_driver_test.c
+++ b/utils/aflpp_driver/aflpp_driver_test.c
diff --git a/examples/aflpp_driver/aflpp_qemu_driver.c b/utils/aflpp_driver/aflpp_qemu_driver.c
index 4f3e5f71..79de5af6 100644
--- a/examples/aflpp_driver/aflpp_qemu_driver.c
+++ b/utils/aflpp_driver/aflpp_qemu_driver.c
@@ -6,8 +6,8 @@
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
 __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
 
-static const size_t kMaxAflInputSize = 1 * 1024 * 1024;
-static uint8_t      AflInputBuf[kMaxAflInputSize];
+#define kMaxAflInputSize (1 * 1024 * 1024)
+static uint8_t AflInputBuf[kMaxAflInputSize];
 
 void __attribute__((noinline)) afl_qemu_driver_stdin_input(void) {
 
diff --git a/examples/aflpp_driver/aflpp_qemu_driver_hook.c b/utils/aflpp_driver/aflpp_qemu_driver_hook.c
index 823cc42d..823cc42d 100644
--- a/examples/aflpp_driver/aflpp_qemu_driver_hook.c
+++ b/utils/aflpp_driver/aflpp_qemu_driver_hook.c
diff --git a/examples/analysis_scripts/queue2csv.sh b/utils/analysis_scripts/queue2csv.sh
index 2528b438..2528b438 100755
--- a/examples/analysis_scripts/queue2csv.sh
+++ b/utils/analysis_scripts/queue2csv.sh
diff --git a/examples/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile
index 5a0ac6e6..5a0ac6e6 100644
--- a/examples/argv_fuzzing/Makefile
+++ b/utils/argv_fuzzing/Makefile
diff --git a/examples/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md
index fa8cad80..fa8cad80 100644
--- a/examples/argv_fuzzing/README.md
+++ b/utils/argv_fuzzing/README.md
diff --git a/examples/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h
index c15c0271..c15c0271 100644
--- a/examples/argv_fuzzing/argv-fuzz-inl.h
+++ b/utils/argv_fuzzing/argv-fuzz-inl.h
diff --git a/examples/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c
index 4251ca4c..4251ca4c 100644
--- a/examples/argv_fuzzing/argvfuzz.c
+++ b/utils/argv_fuzzing/argvfuzz.c
diff --git a/examples/asan_cgroups/limit_memory.sh b/utils/asan_cgroups/limit_memory.sh
index 1f0f04ad..1f0f04ad 100755
--- a/examples/asan_cgroups/limit_memory.sh
+++ b/utils/asan_cgroups/limit_memory.sh
diff --git a/examples/bash_shellshock/shellshock-fuzz.diff b/utils/bash_shellshock/shellshock-fuzz.diff
index 3fa05bf8..3fa05bf8 100644
--- a/examples/bash_shellshock/shellshock-fuzz.diff
+++ b/utils/bash_shellshock/shellshock-fuzz.diff
diff --git a/examples/canvas_harness/canvas_harness.html b/utils/canvas_harness/canvas_harness.html
index a37b6937..a37b6937 100644
--- a/examples/canvas_harness/canvas_harness.html
+++ b/utils/canvas_harness/canvas_harness.html
diff --git a/examples/clang_asm_normalize/as b/utils/clang_asm_normalize/as
index 45537cae..45537cae 100755
--- a/examples/clang_asm_normalize/as
+++ b/utils/clang_asm_normalize/as
diff --git a/examples/crash_triage/triage_crashes.sh b/utils/crash_triage/triage_crashes.sh
index bf763cba..bf763cba 100755
--- a/examples/crash_triage/triage_crashes.sh
+++ b/utils/crash_triage/triage_crashes.sh
diff --git a/examples/custom_mutators/Makefile b/utils/custom_mutators/Makefile
index 9849f3f4..9849f3f4 100644
--- a/examples/custom_mutators/Makefile
+++ b/utils/custom_mutators/Makefile
diff --git a/examples/custom_mutators/README.md b/utils/custom_mutators/README.md
index 655f7a5e..655f7a5e 100644
--- a/examples/custom_mutators/README.md
+++ b/utils/custom_mutators/README.md
diff --git a/examples/custom_mutators/XmlMutatorMin.py b/utils/custom_mutators/XmlMutatorMin.py
index 4c80a2ba..4c80a2ba 100644
--- a/examples/custom_mutators/XmlMutatorMin.py
+++ b/utils/custom_mutators/XmlMutatorMin.py
diff --git a/examples/custom_mutators/common.py b/utils/custom_mutators/common.py
index 9a1ef0a3..9a1ef0a3 100644
--- a/examples/custom_mutators/common.py
+++ b/utils/custom_mutators/common.py
diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/utils/custom_mutators/custom_mutator_helpers.h
index 62e6efba..62e6efba 100644
--- a/examples/custom_mutators/custom_mutator_helpers.h
+++ b/utils/custom_mutators/custom_mutator_helpers.h
diff --git a/examples/custom_mutators/example.c b/utils/custom_mutators/example.c
index 23add128..23add128 100644
--- a/examples/custom_mutators/example.c
+++ b/utils/custom_mutators/example.c
diff --git a/examples/custom_mutators/example.py b/utils/custom_mutators/example.py
index cf659e5a..cf659e5a 100644
--- a/examples/custom_mutators/example.py
+++ b/utils/custom_mutators/example.py
diff --git a/examples/custom_mutators/post_library_gif.so.c b/utils/custom_mutators/post_library_gif.so.c
index ac10f409..ac10f409 100644
--- a/examples/custom_mutators/post_library_gif.so.c
+++ b/utils/custom_mutators/post_library_gif.so.c
diff --git a/examples/custom_mutators/post_library_png.so.c b/utils/custom_mutators/post_library_png.so.c
index 941f7e55..941f7e55 100644
--- a/examples/custom_mutators/post_library_png.so.c
+++ b/utils/custom_mutators/post_library_png.so.c
diff --git a/examples/custom_mutators/simple-chunk-replace.py b/utils/custom_mutators/simple-chunk-replace.py
index df2f4ca7..df2f4ca7 100644
--- a/examples/custom_mutators/simple-chunk-replace.py
+++ b/utils/custom_mutators/simple-chunk-replace.py
diff --git a/examples/custom_mutators/simple_example.c b/utils/custom_mutators/simple_example.c
index d888ec1f..d888ec1f 100644
--- a/examples/custom_mutators/simple_example.c
+++ b/utils/custom_mutators/simple_example.c
diff --git a/examples/custom_mutators/wrapper_afl_min.py b/utils/custom_mutators/wrapper_afl_min.py
index ecb03b55..ecb03b55 100644
--- a/examples/custom_mutators/wrapper_afl_min.py
+++ b/utils/custom_mutators/wrapper_afl_min.py
diff --git a/examples/defork/Makefile b/utils/defork/Makefile
index e8240dba..e8240dba 100644
--- a/examples/defork/Makefile
+++ b/utils/defork/Makefile
diff --git a/examples/defork/README.md b/utils/defork/README.md
index 7e950323..7e950323 100644
--- a/examples/defork/README.md
+++ b/utils/defork/README.md
diff --git a/examples/defork/defork.c b/utils/defork/defork.c
index f71d1124..f71d1124 100644
--- a/examples/defork/defork.c
+++ b/utils/defork/defork.c
diff --git a/examples/defork/forking_target.c b/utils/defork/forking_target.c
index 628d23c9..628d23c9 100644
--- a/examples/defork/forking_target.c
+++ b/utils/defork/forking_target.c
diff --git a/examples/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh
index b28ff6cd..b28ff6cd 100755
--- a/examples/distributed_fuzzing/sync_script.sh
+++ b/utils/distributed_fuzzing/sync_script.sh
diff --git a/examples/libpng_no_checksum/libpng-nocrc.patch b/utils/libpng_no_checksum/libpng-nocrc.patch
index 0a3793a0..0a3793a0 100644
--- a/examples/libpng_no_checksum/libpng-nocrc.patch
+++ b/utils/libpng_no_checksum/libpng-nocrc.patch
diff --git a/examples/persistent_demo/Makefile b/utils/persistent_mode/Makefile
index 6fa1c30e..6fa1c30e 100644
--- a/examples/persistent_demo/Makefile
+++ b/utils/persistent_mode/Makefile
diff --git a/examples/persistent_demo/persistent_demo.c b/utils/persistent_mode/persistent_demo.c
index 4cedc32c..4cedc32c 100644
--- a/examples/persistent_demo/persistent_demo.c
+++ b/utils/persistent_mode/persistent_demo.c
diff --git a/examples/persistent_demo/persistent_demo_new.c b/utils/persistent_mode/persistent_demo_new.c
index b8b4cda0..0d24a51e 100644
--- a/examples/persistent_demo/persistent_demo_new.c
+++ b/utils/persistent_mode/persistent_demo_new.c
@@ -58,11 +58,11 @@ int main(int argc, char **argv) {
      and similar hiccups. */
 
   __AFL_INIT();
-  buf = __AFL_FUZZ_TESTCASE_BUF;
+  buf = __AFL_FUZZ_TESTCASE_BUF;  // this must be assigned before __AFL_LOOP!
 
   while (__AFL_LOOP(1000)) {  // increase if you have good stability
 
-    len = __AFL_FUZZ_TESTCASE_LEN;
+    len = __AFL_FUZZ_TESTCASE_LEN;  // do not use the macro directly in a call!
 
     fprintf(stderr, "input: %zd \"%s\"\n", len, buf);
 
@@ -86,7 +86,7 @@ int main(int argc, char **argv) {
             if (buf[4] == '!') {
 
               printf("five\n");
-              if (buf[6] == '!') {
+              if (buf[5] == '!') {
 
                 printf("six\n");
                 abort();
diff --git a/examples/persistent_demo/test-instr.c b/utils/persistent_mode/test-instr.c
index a6188b22..a6188b22 100644
--- a/examples/persistent_demo/test-instr.c
+++ b/utils/persistent_mode/test-instr.c
diff --git a/examples/qemu_persistent_hook/Makefile b/utils/qemu_persistent_hook/Makefile
index 85db1b46..85db1b46 100644
--- a/examples/qemu_persistent_hook/Makefile
+++ b/utils/qemu_persistent_hook/Makefile
diff --git a/examples/qemu_persistent_hook/README.md b/utils/qemu_persistent_hook/README.md
index 3f908c22..3f908c22 100644
--- a/examples/qemu_persistent_hook/README.md
+++ b/utils/qemu_persistent_hook/README.md
diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/utils/qemu_persistent_hook/read_into_rdi.c
index f4a8ae59..f4a8ae59 100644
--- a/examples/qemu_persistent_hook/read_into_rdi.c
+++ b/utils/qemu_persistent_hook/read_into_rdi.c
diff --git a/examples/qemu_persistent_hook/test.c b/utils/qemu_persistent_hook/test.c
index afeff202..afeff202 100644
--- a/examples/qemu_persistent_hook/test.c
+++ b/utils/qemu_persistent_hook/test.c
diff --git a/examples/socket_fuzzing/Makefile b/utils/socket_fuzzing/Makefile
index 9476e2d5..9476e2d5 100644
--- a/examples/socket_fuzzing/Makefile
+++ b/utils/socket_fuzzing/Makefile
diff --git a/examples/socket_fuzzing/README.md b/utils/socket_fuzzing/README.md
index 79f28bea..79f28bea 100644
--- a/examples/socket_fuzzing/README.md
+++ b/utils/socket_fuzzing/README.md
diff --git a/examples/socket_fuzzing/socketfuzz.c b/utils/socket_fuzzing/socketfuzz.c
index 3ec8383b..3ec8383b 100644
--- a/examples/socket_fuzzing/socketfuzz.c
+++ b/utils/socket_fuzzing/socketfuzz.c