about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-04-20 11:38:09 +0200
committerGitHub <noreply@github.com>2021-04-20 11:38:09 +0200
commit48cef3c74727407f82c44800d382737265fe65b4 (patch)
tree07338ec82703c20cc1f78a235ac3ad16e2465bf1
parentf7179e44f6c46fef318b6413d9c00693c1af4602 (diff)
parent3b5fa3632b0e482b2915709d7fbec827e1d997b9 (diff)
downloadafl++-48cef3c74727407f82c44800d382737265fe65b4.tar.gz
Merge pull request #871 from AFLplusplus/dev
push to stable
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--.gitignore3
-rw-r--r--Android.bp143
-rw-r--r--GNUmakefile52
-rw-r--r--GNUmakefile.gcc_plugin12
-rw-r--r--GNUmakefile.llvm21
-rw-r--r--README.md59
-rw-r--r--TODO.md6
-rwxr-xr-xafl-cmin13
-rwxr-xr-xafl-cmin.bash9
-rwxr-xr-xafl-system-config4
-rwxr-xr-xafl-whatsup49
-rw-r--r--custom_mutators/Android.bp6
-rw-r--r--custom_mutators/grammar_mutator/GRAMMAR_VERSION2
-rwxr-xr-xcustom_mutators/grammar_mutator/build_grammar_mutator.sh16
m---------custom_mutators/grammar_mutator/grammar_mutator0
-rw-r--r--custom_mutators/libprotobuf-mutator-example/Android.bp6
-rw-r--r--docs/Changelog.md29
-rw-r--r--docs/PATCHES.md43
-rw-r--r--docs/custom_mutators.md2
-rw-r--r--docs/env_variables.md67
-rw-r--r--docs/ideas.md43
-rw-r--r--docs/notes_for_asan.md7
-rw-r--r--docs/perf_tips.md3
-rw-r--r--docs/status_screen.md11
-rw-r--r--dynamic_list.txt1
-rw-r--r--frida_mode/.gitignore5
-rw-r--r--frida_mode/Makefile348
-rw-r--r--frida_mode/README.md135
-rw-r--r--frida_mode/include/instrument.h7
-rw-r--r--frida_mode/include/interceptor.h4
-rw-r--r--frida_mode/include/prefetch.h5
-rw-r--r--frida_mode/include/ranges.h6
-rw-r--r--frida_mode/src/instrument.c271
-rw-r--r--frida_mode/src/interceptor.c16
-rw-r--r--frida_mode/src/main.c149
-rw-r--r--frida_mode/src/prefetch.c121
-rw-r--r--frida_mode/src/ranges.c394
-rw-r--r--frida_mode/test/testinstr.c112
-rwxr-xr-xfrida_mode/test/testinstr.py49
-rw-r--r--include/afl-fuzz.h8
-rw-r--r--include/android-ashmem.h25
-rw-r--r--include/config.h16
-rw-r--r--include/envs.h11
-rw-r--r--include/forkserver.h13
-rw-r--r--instrumentation/LLVMInsTrim.so.cc599
-rw-r--r--instrumentation/MarkNodes.cc481
-rw-r--r--instrumentation/MarkNodes.h12
-rw-r--r--instrumentation/README.instrim.md30
-rw-r--r--instrumentation/README.llvm.md19
-rw-r--r--instrumentation/README.snapshot.md2
-rw-r--r--instrumentation/afl-compiler-rt.o.c28
-rw-r--r--instrumentation/afl-llvm-common.cc3
-rw-r--r--instrumentation/afl-llvm-lto-instrumentation.so.cc4
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
-rw-r--r--qemu_mode/README.md2
-rwxr-xr-xqemu_mode/build_qemu_support.sh2
-rw-r--r--qemu_mode/libcompcov/compcovtest.cc163
m---------qemu_mode/qemuafl0
-rw-r--r--src/afl-analyze.c67
-rw-r--r--src/afl-as.c7
-rw-r--r--src/afl-cc.c88
-rw-r--r--src/afl-common.c63
-rw-r--r--src/afl-forkserver.c124
-rw-r--r--src/afl-fuzz-init.c30
-rw-r--r--src/afl-fuzz-mutators.c8
-rw-r--r--src/afl-fuzz-one.c666
-rw-r--r--src/afl-fuzz-queue.c6
-rw-r--r--src/afl-fuzz-redqueen.c26
-rw-r--r--src/afl-fuzz-run.c1
-rw-r--r--src/afl-fuzz-state.c16
-rw-r--r--src/afl-fuzz-stats.c138
-rw-r--r--src/afl-fuzz.c158
-rw-r--r--src/afl-ld-lto.c27
-rw-r--r--src/afl-showmap.c101
-rw-r--r--src/afl-tmin.c66
-rwxr-xr-xtest/test-llvm.sh25
-rwxr-xr-xtest/test-pre.sh1
-rw-r--r--unicorn_mode/helper_scripts/ida_context_loader.py84
-rw-r--r--utils/afl_frida/afl-frida.c4
-rw-r--r--utils/afl_network_proxy/afl-network-server.c5
-rw-r--r--utils/aflpp_driver/GNUmakefile10
-rw-r--r--utils/aflpp_driver/README.md30
-rw-r--r--utils/aflpp_driver/aflpp_qemu_driver_hook.c21
-rw-r--r--utils/autodict_ql/autodict-ql.py146
-rw-r--r--utils/autodict_ql/build-codeql.sh17
-rw-r--r--utils/autodict_ql/litan.py112
-rw-r--r--utils/autodict_ql/litool.ql10
-rw-r--r--utils/autodict_ql/memcmp-str.ql8
-rw-r--r--utils/autodict_ql/memcmp-strings.py83
-rw-r--r--utils/autodict_ql/qlpack.yml3
-rw-r--r--utils/autodict_ql/readme.md100
-rw-r--r--utils/autodict_ql/stan-strings.py83
-rw-r--r--utils/autodict_ql/strcmp-str.ql8
-rw-r--r--utils/autodict_ql/strcmp-strings.py83
-rw-r--r--utils/autodict_ql/strncmp-str.ql8
-rw-r--r--utils/autodict_ql/strncmp-strings.py83
-rw-r--r--utils/autodict_ql/strtool.ql24
-rwxr-xr-xutils/crash_triage/triage_crashes.sh11
-rw-r--r--utils/qemu_persistent_hook/read_into_rdi.c2
100 files changed, 4172 insertions, 2032 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 31cfceaf..a5f3429e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,6 +16,8 @@ jobs:
       - uses: actions/checkout@v2
       - name: debug
         run: apt-cache search plugin-dev | grep gcc- ; echo ; apt-cache search clang-format- | grep clang-format-
+      - name: update
+        run: sudo apt-get update && sudo apt-get upgrade -y
       - name: install packages
         run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools
       - name: compiler installed
diff --git a/.gitignore b/.gitignore
index 3f440730..c8d29e50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,3 +82,6 @@ libAFLDriver.a
 libAFLQemuDriver.a
 test/.afl_performance
 gmon.out
+afl-frida-trace.so
+utils/afl_network_proxy/afl-network-client
+utils/afl_network_proxy/afl-network-server
diff --git a/Android.bp b/Android.bp
index ee076d1e..bf37757d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,8 +1,5 @@
 cc_defaults {
   name: "afl-defaults",
-  sanitize: {
-    never: true,
-  },
 
   local_include_dirs: [
     "include",
@@ -23,18 +20,44 @@ cc_defaults {
     "-DBIN_PATH=\"out/host/linux-x86/bin\"",
     "-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
     "-D__USE_GNU",
-    "-D__aarch64__",
     "-DDEBUG_BUILD",
     "-U_FORTIFY_SOURCE",
     "-ggdb3",
     "-g",
     "-O0",
     "-fno-omit-frame-pointer",
+    "-fPIC",
   ],
+
+  target: {
+    android_arm64: {
+      cflags: [
+        "-D__ANDROID__",
+      ],
+    },
+    android_arm: {
+      cflags: [
+        "-D__ANDROID__",
+      ],
+    },
+    android_x86_64: {
+      cflags: [
+        "-D__ANDROID__",
+      ],
+    },
+    android_x86: {
+      cflags: [
+        "-D__ANDROID__",
+      ],
+    },
+  },
 }
 
 cc_binary {
   name: "afl-fuzz",
+  sanitize: {
+    never: true,
+  },
   host_supported: true,
   compile_multilib: "64",
 
@@ -128,7 +151,6 @@ cc_binary_host {
   ],
 
   cflags: [
-    "-D__ANDROID__",
     "-DAFL_PATH=\"out/host/linux-x86/lib64\"",
     "-DAFL_CLANG_FLTO=\"-flto=full\"",
     "-DUSE_BINDIR=1",
@@ -199,6 +221,7 @@ cc_library_headers {
 
   export_include_dirs: [
     "include",
+    "instrumentation",
   ],
 }
 
@@ -268,6 +291,116 @@ cc_binary {
   ],
 }
 
+cc_binary {
+  name: "afl-fuzz-32",
+  sanitize: {
+    never: true,
+  },
+  host_supported: true,
+  compile_multilib: "32",
+
+  defaults: [
+    "afl-defaults",
+  ],
+
+  srcs: [
+    "src/afl-fuzz*.c",
+    "src/afl-common.c",
+    "src/afl-sharedmem.c",
+    "src/afl-forkserver.c",
+    "src/afl-performance.c",
+  ],
+}
+
+cc_binary_host {
+  name: "afl-cc-32",
+  compile_multilib: "32",
+  static_executable: true,
+
+  defaults: [
+    "afl-defaults",
+  ],
+
+  cflags: [
+    "-DAFL_PATH=\"out/host/linux-x86/lib64\"",
+    "-DAFL_CLANG_FLTO=\"-flto=full\"",
+    "-DUSE_BINDIR=1",
+    "-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
+    "-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
+    "-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
+    "-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
+    "-DLLVM_LTO=1",
+    "-DLLVM_MAJOR=11",
+    "-DLLVM_MINOR=2",
+  ],
+
+  srcs: [
+    "src/afl-cc.c",
+    "src/afl-common.c",
+  ],
+
+  symlinks: [
+    "afl-clang-fast-32",
+    "afl-clang-fast++-32",
+  ],
+}
+
+cc_library_static {
+  name: "afl-llvm-rt-32",
+  compile_multilib: "32",
+  vendor_available: true,
+  host_supported: true,
+  recovery_available: true,
+  sdk_version: "9",
+
+  apex_available: [
+    "com.android.adbd",
+    "com.android.appsearch",
+    "com.android.art",
+    "com.android.bluetooth.updatable",
+    "com.android.cellbroadcast",
+    "com.android.conscrypt",
+    "com.android.extservices",
+    "com.android.cronet",
+    "com.android.neuralnetworks",
+    "com.android.media",
+    "com.android.media.swcodec",
+    "com.android.mediaprovider",
+    "com.android.permission",
+    "com.android.runtime",
+    "com.android.resolv",
+    "com.android.tethering",
+    "com.android.wifi",
+    "com.android.sdkext",
+    "com.android.os.statsd",
+    "//any",
+  ],
+
+  defaults: [
+    "afl-defaults",
+  ],
+
+  srcs: [
+    "instrumentation/afl-compiler-rt.o.c",
+  ],
+}
+
+cc_prebuilt_library_static {
+  name: "libfrida-gum-32",
+  compile_multilib: "32",
+  strip: {
+    none: true,
+  },
+
+  srcs: [
+    "utils/afl_frida/android/arm/libfrida-gum.a",
+  ],
+
+  export_include_dirs: [
+    "utils/afl_frida/android/arm",
+  ],
+}
+
 subdirs = [
   "custom_mutators",
 ]
diff --git a/GNUmakefile b/GNUmakefile
index ac8fe796..9d98aa00 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -36,6 +36,11 @@ SH_PROGS    = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
 MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
 ASAN_OPTIONS=detect_leaks=0
 
+SYS = $(shell uname -s)
+ARCH = $(shell uname -m)
+
+$(info [*] Compiling afl++ for OS $(SYS) on ARCH $(ARCH))
+
 ifdef NO_SPLICING
   override CFLAGS += -DNO_SPLICING
 endif
@@ -82,7 +87,7 @@ endif
 #  endif
 #endif
 
-ifneq "$(shell uname)" "Darwin"
+ifneq "$(SYS)" "Darwin"
   #ifeq "$(HAVE_MARCHNATIVE)" "1"
   #  SPECIAL_PERFORMANCE += -march=native
   #endif
@@ -92,7 +97,7 @@ ifneq "$(shell uname)" "Darwin"
   endif
 endif
 
-ifeq "$(shell uname)" "SunOS"
+ifeq "$(SYS)" "SunOS"
   CFLAGS_OPT += -Wno-format-truncation
   LDFLAGS = -lkstat -lrt
 endif
@@ -119,11 +124,10 @@ ifdef INTROSPECTION
   CFLAGS_OPT += -DINTROSPECTION=1
 endif
 
-
-ifneq "$(shell uname -m)" "x86_64"
- ifneq "$(patsubst i%86,i386,$(shell uname -m))" "i386"
-  ifneq "$(shell uname -m)" "amd64"
-   ifneq "$(shell uname -m)" "i86pc"
+ifneq "$(ARCH)" "x86_64"
+ ifneq "$(patsubst i%86,i386,$(ARCH))" "i386"
+  ifneq "$(ARCH)" "amd64"
+   ifneq "$(ARCH)" "i86pc"
 	AFL_NO_X86=1
    endif
   endif
@@ -141,30 +145,30 @@ override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpoi
 			  -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
 			  -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
 
-ifeq "$(shell uname -s)" "FreeBSD"
+ifeq "$(SYS)" "FreeBSD"
   override CFLAGS  += -I /usr/local/include/
   LDFLAGS += -L /usr/local/lib/
 endif
 
-ifeq "$(shell uname -s)" "DragonFly"
+ifeq "$(SYS)" "DragonFly"
   override CFLAGS  += -I /usr/local/include/
   LDFLAGS += -L /usr/local/lib/
 endif
 
-ifeq "$(shell uname -s)" "OpenBSD"
+ifeq "$(SYS)" "OpenBSD"
   override CFLAGS  += -I /usr/local/include/ -mno-retpoline
   LDFLAGS += -Wl,-z,notext -L /usr/local/lib/
 endif
 
-ifeq "$(shell uname -s)" "NetBSD"
+ifeq "$(SYS)" "NetBSD"
   override CFLAGS  += -I /usr/pkg/include/
   LDFLAGS += -L /usr/pkg/lib/
 endif
 
-ifeq "$(shell uname -s)" "Haiku"
+ifeq "$(SYS)" "Haiku"
   SHMAT_OK=0
   override CFLAGS  += -DUSEMMAP=1 -Wno-error=format -fPIC
-  LDFLAGS += -Wno-deprecated-declarations -lgnu
+  LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
   SPECIAL_PERFORMANCE += -DUSEMMAP=1
 endif
 
@@ -236,24 +240,24 @@ else
     BUILD_DATE ?= $(shell date "+%Y-%m-%d")
 endif
 
-ifneq "$(filter Linux GNU%,$(shell uname))" ""
+ifneq "$(filter Linux GNU%,$(SYS))" ""
  ifndef DEBUG
   override CFLAGS += -D_FORTIFY_SOURCE=2
  endif
   LDFLAGS += -ldl -lrt -lm
 endif
 
-ifneq "$(findstring FreeBSD, $(shell uname))" ""
+ifneq "$(findstring FreeBSD, $(SYS))" ""
   override CFLAGS  += -pthread
   LDFLAGS += -lpthread
 endif
 
-ifneq "$(findstring NetBSD, $(shell uname))" ""
+ifneq "$(findstring NetBSD, $(SYS))" ""
   override CFLAGS  += -pthread
   LDFLAGS += -lpthread
 endif
 
-ifneq "$(findstring OpenBSD, $(shell uname))" ""
+ifneq "$(findstring OpenBSD, $(SYS))" ""
   override CFLAGS  += -pthread
   LDFLAGS += -lpthread
 endif
@@ -485,7 +489,7 @@ unit_clean:
 	@rm -f ./test/unittests/unit_preallocable ./test/unittests/unit_list ./test/unittests/unit_maybe_alloc test/unittests/*.o
 
 .PHONY: unit
-ifneq "$(shell uname)" "Darwin"
+ifneq "$(SYS)" "Darwin"
 unit:	unit_maybe_alloc unit_preallocable unit_list unit_clean unit_rand unit_hash
 else
 unit:
@@ -509,6 +513,9 @@ code-format:
 	./.custom-format.py -i qemu_mode/libcompcov/*.h
 	./.custom-format.py -i qemu_mode/libqasan/*.c
 	./.custom-format.py -i qemu_mode/libqasan/*.h
+	./.custom-format.py -i frida_mode/src/*.c
+	./.custom-format.py -i frida_mode/include/*.h
+	-./.custom-format.py -i frida_mode/src/*/*.c
 	./.custom-format.py -i *.h
 	./.custom-format.py -i *.c
 
@@ -517,7 +524,7 @@ code-format:
 ifndef AFL_NO_X86
 test_build: afl-cc afl-gcc afl-as afl-showmap
 	@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
-	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
+	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 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
@@ -525,7 +532,7 @@ test_build: afl-cc afl-gcc afl-as afl-showmap
 	@echo
 	@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
 #	@echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
-#	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
+#	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
 #	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
@@ -546,7 +553,7 @@ all_done: test_build
 	@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc'  failed to build, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
 	@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc'  failed to build, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
 	@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
-	@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
+	@if [ "$(SYS)" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD for fuzzing software not\nspecifically for MacOS.\n\n"; fi
 	@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
 
 .NOTPARALLEL: clean all
@@ -593,6 +600,7 @@ distrib: all
 	$(MAKE) -C utils/afl_network_proxy
 	$(MAKE) -C utils/socket_fuzzing
 	$(MAKE) -C utils/argv_fuzzing
+	-$(MAKE) -C frida_mode
 	-cd qemu_mode && sh ./build_qemu_support.sh
 	-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
 
@@ -603,6 +611,7 @@ binary-only: test_shm test_python ready $(PROGS)
 	$(MAKE) -C utils/afl_network_proxy
 	$(MAKE) -C utils/socket_fuzzing
 	$(MAKE) -C utils/argv_fuzzing
+	-$(MAKE) -C frida_mode
 	-cd qemu_mode && sh ./build_qemu_support.sh
 	-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
 
@@ -648,6 +657,7 @@ install: all $(MANPAGES)
 	@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 utils/socket_fuzzing install; fi
 	@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
+	@if [ -f afl-frida-trace.so ]; then install -m 755 afl-frida-trace.so $${DESTDIR}$(HELPER_PATH); 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
diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin
index aa93c688..b0f90f1b 100644
--- a/GNUmakefile.gcc_plugin
+++ b/GNUmakefile.gcc_plugin
@@ -41,6 +41,8 @@ CXXEFLAGS   := $(CXXFLAGS) -Wall -std=c++11
 CC          ?= gcc
 CXX         ?= g++
 
+SYS = $(shell uname -s)
+
 ifeq "clang" "$(CC)"
         CC  = gcc
         CXX = g++
@@ -75,25 +77,25 @@ ifeq "$(TEST_MMAP)" "1"
 	override CFLAGS_SAFE += -DUSEMMAP=1
 endif
 
-ifneq "$(shell uname -s)" "Haiku"
-ifneq "$(shell uname -s)" "OpenBSD"
+ifneq "$(SYS)" "Haiku"
+ifneq "$(SYS)" "OpenBSD"
   	LDFLAGS += -lrt
 endif
 else
 	CFLAGS_SAFE += -DUSEMMAP=1
 endif
 
-ifeq "$(shell uname -s)" "OpenBSD"
+ifeq "$(SYS)" "OpenBSD"
     CC  = egcc
     CXX = eg++
     PLUGIN_FLAGS += -I/usr/local/include
 endif
 
-ifeq "$(shell uname -s)" "DragonFly"
+ifeq "$(SYS)" "DragonFly"
   	PLUGIN_FLAGS += -I/usr/local/include
 endif
 
-ifeq "$(shell uname -s)" "SunOS"
+ifeq "$(SYS)" "SunOS"
   	PLUGIN_FLAGS += -I/usr/include/gmp
 endif
 
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index 111a847d..2d50badc 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -30,11 +30,13 @@ BUILD_DATE  ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/nul
 
 VERSION     = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
 
-ifeq "$(shell uname)" "OpenBSD"
+SYS = $(shell uname -s)
+
+ifeq "$(SYS)" "OpenBSD"
   LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
   HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
   ifeq "$(HAS_OPT)" "1"
-    $(warning 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 6.0 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
   endif
 else
   LLVM_CONFIG ?= llvm-config
@@ -43,7 +45,7 @@ endif
 LLVMVER  = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
 LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
 LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
-LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^[0-2]\.' && echo 1 || echo 0 )
+LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^[0-5]\.' && echo 1 || echo 0 )
 LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[3-9]' && echo 1 || echo 0 )
 LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
 LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
@@ -59,7 +61,7 @@ ifeq "$(LLVMVER)" ""
 endif
 
 ifeq "$(LLVM_UNSUPPORTED)" "1"
-  $(error llvm_mode only supports llvm from version 3.4 onwards)
+  $(error llvm_mode only supports llvm from version 6.0 onwards)
 endif
 
 ifeq "$(LLVM_TOO_NEW)" "1"
@@ -275,13 +277,13 @@ CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
 
 
 # User teor2345 reports that this is required to make things work on MacOS X.
-ifeq "$(shell uname)" "Darwin"
+ifeq "$(SYS)" "Darwin"
   CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
 else
   CLANG_CPPFL += -Wl,-znodelete
 endif
 
-ifeq "$(shell uname)" "OpenBSD"
+ifeq "$(SYS)" "OpenBSD"
   CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
   CLANG_CPPFL += -mno-retpoline
   CFLAGS += -mno-retpoline
@@ -304,7 +306,7 @@ ifeq "$(TEST_MMAP)" "1"
 endif
 
 PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o 
-PROGS        = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./libLLVMInsTrim.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so
+PROGS        = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so
 
 # If prerequisites are not given, warn, do not build anything, and exit with code 0
 ifeq "$(LLVMVER)" ""
@@ -344,7 +346,7 @@ no_build:
 test_deps:
 	@echo "[*] Checking for working 'llvm-config'..."
  ifneq "$(LLVM_APPLE_XCODE)" "1"
-	@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo "    (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
+	@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo "    (Sometimes, the binary will be named llvm-config-11 or something like that.)"; exit 1 )
  endif
 	@echo "[*] Checking for working '$(CC)'..."
 	@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
@@ -382,9 +384,6 @@ endif
 instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
 	$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@ 
 
-./libLLVMInsTrim.so: instrumentation/LLVMInsTrim.so.cc instrumentation/MarkNodes.cc instrumentation/afl-llvm-common.o | test_deps
-	-$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< instrumentation/MarkNodes.cc -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
-
 ./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
 ifeq "$(LLVM_MIN_4_0_1)" "0"
 	$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
diff --git a/README.md b/README.md
index 084971f3..4a0f3574 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,11 @@
   For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast`
   with `AFL_LLVM_CMPLOG=1`.
 
-## Major changes in afl++ 3.00 + 3.10
+## Major changes in afl++ 3.00 onwards:
+
+With afl++ 3.13-3.20 we introduce frida_mode (-O) to have an alternative for
+binary-only fuzzing. It is slower than Qemu mode but works on MacOS, Android,
+iOS etc.
 
 With afl++ 3.10 we introduced the following changes from previous behaviours:
   * The '+' feature of the '-t' option now means to  auto-calculate the timeout
@@ -80,30 +84,30 @@ behaviours and defaults:
 
 ## Important features of afl++
 
-  afl++ supports llvm up to version 12, very fast binary fuzzing with QEMU 5.1
-  with laf-intel and redqueen, unicorn mode, gcc plugin, full *BSD, Solaris and
-  Android support and much, much, much more.
-
-  | Feature/Instrumentation  | afl-gcc | llvm      | gcc_plugin | qemu_mode        | unicorn_mode |
-  | -------------------------|:-------:|:---------:|:----------:|:----------------:|:------------:|
-  | NeverZero                | x86[_64]|     x(1)  |     x      |         x        |       x      |
-  | Persistent Mode          |         |     x     |     x      | x86[_64]/arm[64] |       x      |
-  | LAF-Intel / CompCov      |         |     x     |            | x86[_64]/arm[64] | x86[_64]/arm |
-  | CmpLog                   |         |     x     |            | x86[_64]/arm[64] |              |
-  | Selective Instrumentation|         |     x     |     x      |         x        |              |
-  | Non-Colliding Coverage   |         |     x(4)  |            |        (x)(5)    |              |
-  | Ngram prev_loc Coverage  |         |     x(6)  |            |                  |              |
-  | Context Coverage         |         |     x(6)  |            |                  |              |
-  | Auto Dictionary          |         |     x(7)  |            |                  |              |
-  | Snapshot LKM Support     |         |     x(8)  |     x(8)   |        (x)(5)    |              |
-
-  1. default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8
+  afl++ supports llvm from 6.0 up to version 12, very fast binary fuzzing with QEMU 5.1
+  with laf-intel and redqueen, frida mode, unicorn mode, gcc plugin, full *BSD,
+  Mac OS, Solaris and Android support and much, much, much more.
+
+  | Feature/Instrumentation  | afl-gcc | llvm      | gcc_plugin | frida_mode | qemu_mode        |unicorn_mode |
+  | -------------------------|:-------:|:---------:|:----------:|:----------:|:----------------:|:------------:|
+  | NeverZero                | x86[_64]|     x(1)  |     x      |            |         x        |       x      |
+  | Persistent Mode          |         |     x     |     x      |            | x86[_64]/arm[64] |       x      |
+  | LAF-Intel / CompCov      |         |     x     |            |            | x86[_64]/arm[64] | x86[_64]/arm |
+  | CmpLog                   |         |     x     |            |            | x86[_64]/arm[64] |              |
+  | Selective Instrumentation|         |     x     |     x      |     x      |         x        |              |
+  | Non-Colliding Coverage   |         |     x(4)  |            |            |        (x)(5)    |              |
+  | Ngram prev_loc Coverage  |         |     x(6)  |            |            |                  |              |
+  | Context Coverage         |         |     x(6)  |            |            |                  |              |
+  | Auto Dictionary          |         |     x(7)  |            |            |                  |              |
+  | Snapshot LKM Support     |         |    (x)(8) |    (x)(8)  |            |        (x)(5)    |              |
+
+  1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions
   2. GCC creates non-performant code, hence it is disabled in gcc_plugin
   3. (currently unassigned)
-  4. with pcguard mode and LTO mode for LLVM >= 11
+  4. with pcguard mode and LTO mode for LLVM 11 and newer
   5. upcoming, development in the branch
-  6. not compatible with LTO instrumentation and needs at least LLVM >= 4.1
-  7. automatic in LTO mode with LLVM >= 11, an extra pass for all LLVM version that writes to a file to use with afl-fuzz' `-x`
+  6. not compatible with LTO instrumentation and needs at least LLVM v4.1
+  7. automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM version that writes to a file to use with afl-fuzz' `-x`
   8. the snapshot LKM is currently unmaintained due to too many kernel changes coming too fast :-(
 
   Among others, the following features and patches have been integrated:
@@ -140,6 +144,7 @@ behaviours and defaults:
     time when we are satisfied with its stability
   * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev) : development state of afl++ - bleeding edge and you might catch a
     checkout which does not compile or has a bug. *We only accept PRs in dev!!*
+  * [release](https://github.com/AFLplusplus/AFLplusplus/tree/release) : the latest release
   * (any other) : experimental branches to work on specific features or testing
     new functionality or changes.
 
@@ -180,7 +185,7 @@ sudo apt-get install -y build-essential python3-dev automake git flex bison libg
 # try to install llvm 11 and install the distro default if that fails
 sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang 
 sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
-git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
+git clone https://github.com/AFLplusplus/AFLplusplus
 cd AFLplusplus
 make distrib
 sudo make install
@@ -288,7 +293,7 @@ anything below 9 is not recommended.
     |
     v
 +---------------------------------+
-| clang/clang++ 3.3+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
+| clang/clang++ 6.0+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
 +---------------------------------+     see [instrumentation/README.llvm.md](instrumentation/README.llvm.md)
     |
     | if not, or if the target fails with LLVM afl-clang-fast/++
@@ -370,7 +375,6 @@ There are many more options and modes available however these are most of the
 time less effective. See:
  * [instrumentation/README.ctx.md](instrumentation/README.ctx.md)
  * [instrumentation/README.ngram.md](instrumentation/README.ngram.md)
- * [instrumentation/README.instrim.md](instrumentation/README.instrim.md)
 
 afl++ performs "never zero" counting in its bitmap. You can read more about this
 here:
@@ -601,8 +605,9 @@ Every -M/-S entry needs a unique name (that can be whatever), however the same
 For every secondary fuzzer there should be a variation, e.g.:
  * one should fuzz the target that was compiled differently: with sanitizers
    activated (`export AFL_USE_ASAN=1 ; export AFL_USE_UBSAN=1 ;
-   export AFL_USE_CFISAN=1 ; `
- * one should fuzz the target with CMPLOG/redqueen (see above)
+   export AFL_USE_CFISAN=1 ; export AFL_USE_LSAN=1`)
+ * one or two should fuzz the target with CMPLOG/redqueen (see above), at
+   least one cmplog instance should follow transformations (`-l AT`)
  * one to three fuzzers should fuzz a target compiled with laf-intel/COMPCOV
    (see above). Important note: If you run more than one laf-intel/COMPCOV
    fuzzer and you want them to share their intermediate results, the main
diff --git a/TODO.md b/TODO.md
index b8a091ff..5a5e7c4e 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,6 +2,7 @@
 
 ## Roadmap 3.00+
 
+ - align map to 64 bytes but keep real IDs
  - Update afl->pending_not_fuzzed for MOpt
  - CPU affinity for many cores? There seems to be an issue > 96 cores
  - afl-plot to support multiple plot_data
@@ -10,7 +11,7 @@
  - intel-pt tracer
  - better autodetection of shifting runtime timeout values
  - cmplog: use colorization input for havoc?
- - cmplog: too much tainted bytes, directly add to dict and skip?
+ - parallel builds for source-only targets
 
 
 ## Further down the road
@@ -35,4 +36,5 @@ qemu_mode:
    up edge numbers that both following cmp paths have been found and then
    disable working on this edge id -> cmplog_intelligence branch
  - use cmplog colorization taint result for havoc locations?
-
+ - new instrumentation option for a thread-safe variant of feedback to shared mem.
+   The user decides, if this is needed (eg the target is multithreaded).
diff --git a/afl-cmin b/afl-cmin
index 778d7487..3f3a7517 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -106,6 +106,7 @@ function usage() {
 "  -f file       - location read by the fuzzed program (stdin)\n" \
 "  -m megs       - memory limit for child process ("mem_limit" MB)\n" \
 "  -t msec       - run time limit for child process (none)\n" \
+"  -O            - use binary-only instrumentation (FRIDA mode)\n" \
 "  -Q            - use binary-only instrumentation (QEMU mode)\n" \
 "  -U            - use unicorn-based instrumentation (unicorn mode)\n" \
 "\n" \
@@ -140,7 +141,7 @@ BEGIN {
   # process options
   Opterr = 1    # default is to diagnose
   Optind = 1    # skip ARGV[0]
-  while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCQU?")) != -1) {
+  while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCOQU?")) != -1) {
     if (_go_c == "i") {
       if (!Optarg) usage()
       if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@@ -180,6 +181,12 @@ BEGIN {
       extra_par = extra_par " -e"
       continue
     } else 
+    if (_go_c == "O") {
+      if (frida_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
+      extra_par = extra_par " -O"
+      frida_mode = 1
+      continue
+    } else 
     if (_go_c == "Q") {
       if (qemu_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
       extra_par = extra_par " -Q"
@@ -243,7 +250,7 @@ BEGIN {
   if (!stdin_file) {
     found_atat = 0
     for (prog_args_ind in prog_args) {
-      if ("@@" == prog_args[prog_args_ind]) {
+      if (match(prog_args[prog_args_ind], "@@") != 0) {
         found_atat = 1
         break
       }
@@ -275,7 +282,7 @@ BEGIN {
     target_bin = tnew
   }
 
-  if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !unicorn_mode) {
+  if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) {
     if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
       print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
       exit 1
diff --git a/afl-cmin.bash b/afl-cmin.bash
index 5b2c3894..f4bd269d 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -53,7 +53,7 @@ unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
 
 export AFL_QUIET=1
 
-while getopts "+i:o:f:m:t:eQUCh" opt; do
+while getopts "+i:o:f:m:t:eOQUCh" opt; do
 
   case "$opt" in 
 
@@ -83,6 +83,10 @@ while getopts "+i:o:f:m:t:eQUCh" opt; do
     "C")
          export AFL_CMIN_CRASHES_ONLY=1
          ;;
+    "O")
+         EXTRA_PAR="$EXTRA_PAR -O"
+         FRIDA_MODE=1
+         ;;         
     "Q")
          EXTRA_PAR="$EXTRA_PAR -Q"
          QEMU_MODE=1
@@ -118,6 +122,7 @@ Execution control settings:
   -f file       - location read by the fuzzed program (stdin)
   -m megs       - memory limit for child process ($MEM_LIMIT MB)
   -t msec       - run time limit for child process (none)
+  -O            - use binary-only instrumentation (FRIDA mode)
   -Q            - use binary-only instrumentation (QEMU mode)
   -U            - use unicorn-based instrumentation (Unicorn mode)
   
@@ -209,7 +214,7 @@ if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
 
 fi
 
-if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
+if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
 
   if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then
     echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2
diff --git a/afl-system-config b/afl-system-config
index ae37a062..5ad9d937 100755
--- a/afl-system-config
+++ b/afl-system-config
@@ -98,7 +98,9 @@ if [ "$PLATFORM" = "Darwin" ] ; then
   DONE=1
 fi
 if [ "$PLATFORM" = "Haiku" ] ; then
-  SETTINGS=~/config/settings/system/debug_server/settings
+  DEBUG_SERVER_DIR=~/config/settings/system/debug_server
+  [ ! -d ${DEBUG_SERVER_DIR} ] && mkdir -p ${DEBUG_SERVER_DIR}
+  SETTINGS=${DEBUG_SERVER_DIR}/settings
   [ -r ${SETTINGS} ] && grep -qE "default_action\s+kill" ${SETTINGS} && { echo "Nothing to do"; } || { \
     echo We change the debug_server default_action from user to silently kill; \
     [ ! -r ${SETTINGS} ] && echo "default_action kill" >${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
diff --git a/afl-whatsup b/afl-whatsup
index e92b24bd..be259829 100755
--- a/afl-whatsup
+++ b/afl-whatsup
@@ -21,29 +21,37 @@
 echo "$0 status check tool for afl-fuzz by Michal Zalewski"
 echo
 test "$1" = "-h" -o "$1" = "-hh" && {
-  echo $0 [-s] output_directory
+  echo "$0 [-s] [-d] output_directory"
   echo
   echo Options:
   echo   -s  -  skip details and output summary results only
+  echo   -d  -  include dead fuzzer stats
   echo
   exit 1
 }
 
-if [ "$1" = "-s" ]; then
+unset SUMMARY_ONLY
+unset PROCESS_DEAD
 
-  SUMMARY_ONLY=1
-  DIR="$2"
+while [ "$1" = "-s" -o "$1" = "-d" ]; do
 
-else
+  if [ "$1" = "-s" ]; then
+    SUMMARY_ONLY=1
+  fi
 
-  unset SUMMARY_ONLY
-  DIR="$1"
+  if [ "$1" = "-d" ]; then
+    PROCESS_DEAD=1
+  fi
+  
+  shift
 
-fi
+done
+
+DIR="$1"
 
 if [ "$DIR" = "" ]; then
 
-  echo "Usage: $0 [ -s ] afl_sync_dir" 1>&2
+  echo "Usage: $0 [-s] [-d] afl_sync_dir" 1>&2
   echo 1>&2
   echo "The -s option causes the tool to skip all the per-fuzzer trivia and show" 1>&2
   echo "just the summary results. See docs/parallel_fuzzing.md for additional tips." 1>&2
@@ -133,7 +141,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
   sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
   . "$TMP"
 
-  RUN_UNIX=$((CUR_TIME - start_time))
+  RUN_UNIX=$run_time
   RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24))
   RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24))
 
@@ -160,7 +168,13 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
     fi
 
     DEAD_CNT=$((DEAD_CNT + 1))
-    continue
+    last_path=0
+
+    if [ "$PROCESS_DEAD" = "" ]; then
+
+      continue
+
+    fi
 
   fi
 
@@ -252,13 +266,24 @@ fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING
 
 test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
 
+if [ "$PROCESS_DEAD" = "" ]; then
+
+  TXT="excluded from stats"
+
+else
+
+  TXT="included in stats"
+  ALIVE_CNT=$(($ALIVE_CNT - $DEAD_CNT))
+
+fi
+
 echo "Summary stats"
 echo "============="
 echo
 echo "       Fuzzers alive : $ALIVE_CNT"
 
 if [ ! "$DEAD_CNT" = "0" ]; then
-  echo "      Dead or remote : $DEAD_CNT (excluded from stats)"
+  echo "      Dead or remote : $DEAD_CNT ($TXT)"
 fi
 
 echo "      Total run time : $FMT_TIME"
diff --git a/custom_mutators/Android.bp b/custom_mutators/Android.bp
index 89abc3e9..5c7e06e3 100644
--- a/custom_mutators/Android.bp
+++ b/custom_mutators/Android.bp
@@ -10,6 +10,8 @@ cc_library_shared {
     "-fPIC",
     "-fpermissive",
     "-std=c++11",
+    "-Wno-unused-parameter",
+    "-Wno-unused-variable",
   ],
 
   srcs: [
@@ -77,6 +79,8 @@ cc_library_shared {
     "-O0",
     "-funroll-loops",
     "-fPIC",
+    "-Wno-unused-parameter",
+    "-Wno-unused-function",
   ],
 
   srcs: [
@@ -99,6 +103,8 @@ cc_library_shared {
     "-O0",
     "-funroll-loops",
     "-fPIC",
+    "-Wno-unused-parameter",
+    "-Wno-pointer-sign",
   ],
 
   srcs: [
diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION
index a3fe6bb1..c7c1948d 100644
--- a/custom_mutators/grammar_mutator/GRAMMAR_VERSION
+++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION
@@ -1 +1 @@
-b3c4fcf
+a2d4e4a
diff --git a/custom_mutators/grammar_mutator/build_grammar_mutator.sh b/custom_mutators/grammar_mutator/build_grammar_mutator.sh
index ef145dfe..b6cef66f 100755
--- a/custom_mutators/grammar_mutator/build_grammar_mutator.sh
+++ b/custom_mutators/grammar_mutator/build_grammar_mutator.sh
@@ -106,23 +106,23 @@ 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
+  git submodule update ./grammar_mutator 2>/dev/null # ignore errors
 else
   echo "[*] cloning grammar mutator"
-  test -d 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)"
+    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 ; }
+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
+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
@@ -134,7 +134,7 @@ echo
 echo
 echo "[+] All successfully prepared!"
 echo "[!] To build for your grammar just do:"
-echo "      cd grammar-mutator"
+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 "[+] 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
-Subproject b3c4fcfa6ae28918bc410f7747135eafd4fb726
+Subproject a2d4e4ab966f0581219fbb282f5ac8c89e85ead
diff --git a/custom_mutators/libprotobuf-mutator-example/Android.bp b/custom_mutators/libprotobuf-mutator-example/Android.bp
index 01f1c23e..4f579735 100644
--- a/custom_mutators/libprotobuf-mutator-example/Android.bp
+++ b/custom_mutators/libprotobuf-mutator-example/Android.bp
@@ -8,6 +8,7 @@ cc_library_shared {
     "-O0",
     "-fPIC",
     "-Wall",
+    "-Wno-unused-parameter",
   ],
 
   srcs: [
@@ -29,4 +30,9 @@ cc_binary {
   srcs: [
     "vuln.c",
   ],
+
+  cflags: [
+    "-Wno-unused-result",
+    "-Wno-unused-parameter",
+  ],
 }
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 5b7d6ab6..520b13b1 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -8,6 +8,35 @@
 Want to stay in the loop on major new features? Join our mailing list by
 sending a mail to <afl-users+subscribe@googlegroups.com>.
 
+### Version ++3.13a (development)
+  - frida_mode - new mode that uses frida to fuzz binary-only targets,
+    thanks to @WorksButNotTested!
+  - create a fuzzing dictionary with the help of CodeQL thanks to
+    @microsvuln! see utils/autodict_ql
+  - afl-fuzz:
+    - added patch by @realmadsci to support @@ as part of command line
+      options, e.g. `afl-fuzz ... -- ./target --infile=@@`
+    - add recording of previous fuzz attempts for persistent mode
+      to allow replay of non-reproducable crashes, see
+      AFL_PERSISTENT_RECORD in config.h and docs/envs.h
+    - default cmplog level (-l) is now 2, better efficiency.
+    - cmplog level 3 (-l 3) now performs redqueen on everything.
+      use with care.
+    - better fuzzing strategy yields for enabled options
+    - ensure one fuzzer sync per cycle
+    - fix afl_custom_queue_new_entry original file name when syncing
+      from fuzzers
+    - added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in
+      -i dir crashes the target or results in a timeout. By default
+      afl++ ignores these and uses them for splicing instead.
+  - afl-cc:
+    - We do not support llvm versions prior 6.0 anymore
+    - Leak Sanitizer (AFL_USE_LSAN) added by Joshua Rogers, thanks!
+    - Removed InsTrim instrumentation as it is not as good as PCGUARD
+    - Removed automatic linking with -lc++ for LTO mode
+  - utils/aflpp_driver/aflpp_qemu_driver_hook fixed to work with qemu mode
+  - add -d (add dead fuzzer stats) to afl-whatsup
+
 ### Version ++3.12c (release)
   - afl-fuzz:
     - added AFL_TARGET_ENV variable to pass extra env vars to the target
diff --git a/docs/PATCHES.md b/docs/PATCHES.md
deleted file mode 100644
index b2cff43a..00000000
--- a/docs/PATCHES.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Applied Patches
-
-The following patches from https://github.com/vanhauser-thc/afl-patches
-have been installed or not installed:
-
-
-## INSTALLED
-```
-afl-llvm-fix.diff			by kcwu(at)csie(dot)org
-afl-sort-all_uniq-fix.diff		by legarrec(dot)vincent(at)gmail(dot)com
-laf-intel.diff				by heiko(dot)eissfeldt(at)hexco(dot)de
-afl-llvm-optimize.diff			by mh(at)mh-sec(dot)de
-afl-fuzz-tmpdir.diff			by mh(at)mh-sec(dot)de
-afl-fuzz-79x24.diff			by heiko(dot)eissfeldt(at)hexco(dot)de
-afl-fuzz-fileextensionopt.diff		tbd
-afl-as-AFL_INST_RATIO.diff		by legarrec(dot)vincent(at)gmail(dot)com
-afl-qemu-ppc64.diff			by william(dot)barsse(at)airbus(dot)com
-afl-qemu-optimize-entrypoint.diff	by mh(at)mh-sec(dot)de
-afl-qemu-speed.diff			by abiondo on github
-afl-qemu-optimize-map.diff		by mh(at)mh-sec(dot)de
-```
-
-+ llvm_mode ngram prev_loc coverage (github.com/adrianherrera/afl-ngram-pass)
-+ Custom mutator (native library) (by kyakdan)
-+ unicorn_mode (modernized and updated by domenukk)
-+ instrim (https://github.com/csienslab/instrim) was integrated
-+ MOpt (github.com/puppet-meteor/MOpt-AFL) was imported
-+ AFLfast additions (github.com/mboehme/aflfast) were incorporated.
-+ Qemu 3.1 upgrade with enhancement patches (github.com/andreafioraldi/afl)
-+ Python mutator modules support (github.com/choller/afl)
-+ Instrument file list in LLVM mode (github.com/choller/afl)
-+ forkserver patch for afl-tmin (github.com/nccgroup/TriforceAFL)
-
-
-## NOT INSTALLED
-
-```
-afl-fuzz-context_sensitive.diff	- changes too much of the behaviour
-afl-tmpfs.diff - same as afl-fuzz-tmpdir.diff but more complex
-afl-cmin-reduce-dataset.diff - unsure of the impact
-afl-llvm-fix2.diff - not needed with the other patches
-```
-
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 61d711e4..62e01f83 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -89,10 +89,10 @@ def queue_get(filename):
 
 def queue_new_entry(filename_new_queue, filename_orig_queue):
     pass
-```
 
 def introspection():
     return string
+```
 
 ### Custom Mutation
 
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 409425f1..0100ffac 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -55,7 +55,7 @@ make fairly broad use of environmental variables instead:
     overridden.
 
   - Setting `AFL_USE_ASAN` automatically enables ASAN, provided that your
-    compiler supports that. Note that fuzzing with ASAN is mildly challenging
+    compiler supports it. Note that fuzzing with ASAN is mildly challenging
     - see [notes_for_asan.md](notes_for_asan.md).
 
     (You can also enable MSAN via `AFL_USE_MSAN`; ASAN and MSAN come with the
@@ -64,6 +64,13 @@ make fairly broad use of environmental variables instead:
     there is the Control Flow Integrity sanitizer that can be activated by
     `AFL_USE_CFISAN=1`)
 
+  - Setting `AFL_USE_LSAN` automatically enables Leak-Sanitizer, provided
+    that your compiler supports it. To perform a leak check within your
+    program at a certain point (such as at the end of an __AFL_LOOP),
+    you can run the macro __AFL_LEAK_CHECK(); which will cause
+    an abort if any memory is leaked (you can combine this with the
+    LSAN_OPTIONS=suppressions option to supress some known leaks).
+
   - Setting `AFL_CC`, `AFL_CXX`, and `AFL_AS` lets you use alternate downstream
     compilation tools, rather than the default 'clang', 'gcc', or 'as' binaries
     in your `$PATH`.
@@ -130,16 +137,15 @@ Then there are a few specific features that are only available in instrumentatio
         PCGUARD - our own pcgard based instrumentation (default)
         NATIVE - clang's original pcguard based instrumentation
         CLASSIC - classic AFL (map[cur_loc ^ prev_loc >> 1]++) (default)
-        CFG - InsTrim instrumentation (see below)
         LTO - LTO instrumentation (see below)
         CTX - context sensitive instrumentation (see below)
         NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16)
         GCC - outdated gcc instrumentation
         CLANG - outdated clang instrumentation
-      In CLASSIC (default) and CFG/INSTRIM you can also specify CTX and/or
-      NGRAM, seperate the options with a comma "," then, e.g.:
-        `AFL_LLVM_INSTRUMENT=CFG,CTX,NGRAM-4`
-      Not that this is a good idea to use both CTX and NGRAM :)
+      In CLASSIC you can also specify CTX and/or NGRAM, seperate the options
+      with a comma "," then, e.g.:
+        `AFL_LLVM_INSTRUMENT=CLASSIC,CTX,NGRAM-4`
+      Note that this is actually not a good idea to use both CTX and NGRAM :)
 
 ### LTO
 
@@ -173,24 +179,6 @@ Then there are a few specific features that are only available in instrumentatio
 
   See [instrumentation/README.lto.md](../instrumentation/README.lto.md) for more information.
 
-### INSTRIM
-
-  This feature increases the speed by ~15% without any disadvantages to the
-    classic instrumentation.
-
-  Note that there is also an LTO version (if you have llvm 11 or higher) -
-    that is the best instrumentation we have. Use `afl-clang-lto` to activate.
-    The InsTrim LTO version additionally has all the options and features of
-    LTO (see above).
-
-   - Setting `AFL_LLVM_INSTRIM` or `AFL_LLVM_INSTRUMENT=CFG` activates this mode
-
-   - Setting `AFL_LLVM_INSTRIM_LOOPHEAD=1` expands on INSTRIM to optimize loops.
-      afl-fuzz will only be able to see the path the loop took, but not how
-      many times it was called (unless it is a complex loop).
-
-  See [instrumentation/README.instrim.md](../instrumentation/README.instrim.md)
-
 ### NGRAM
 
    - Setting `AFL_LLVM_NGRAM_SIZE` or `AFL_LLVM_INSTRUMENT=NGRAM-{value}`
@@ -296,6 +284,9 @@ checks or alter some of the more exotic semantics of the tool:
     normally indicated by the cycle counter in the UI turning green. May be
     convenient for some types of automated jobs.
 
+  - `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behaviour
+    which does not allow crashes or timeout seeds in the initial -i corpus.
+
   - `AFL_MAP_SIZE` sets the size of the shared map that afl-fuzz, afl-showmap,
     afl-tmin and afl-analyze create to gather instrumentation data from
     the target. This must be equal or larger than the size the target was
@@ -391,7 +382,8 @@ checks or alter some of the more exotic semantics of the tool:
     may complain of high load prematurely, especially on systems with low core
     counts. To avoid the alarming red color, you can set `AFL_NO_CPU_RED`.
 
-  - In QEMU mode (-Q), `AFL_PATH` will be searched for afl-qemu-trace.
+  - In QEMU mode (-Q) and Frida mode (-O), `AFL_PATH` will
+    be searched for afl-qemu-trace and afl-frida-trace.so.
 
   - In QEMU mode (-Q), setting `AFL_QEMU_CUSTOM_BIN` cause afl-fuzz to skip
     prepending `afl-qemu-trace` to your command line. Use this if you wish to use a
@@ -424,6 +416,16 @@ checks or alter some of the more exotic semantics of the tool:
   - Setting `AFL_FORCE_UI` will force painting the UI on the screen even if
     no valid terminal was detected (for virtual consoles)
 
+  - If you are using persistent mode (you should, see [instrumentation/README.persistent_mode.md](instrumentation/README.persistent_mode.md))
+    some targets keep inherent state due which a detected crash testcase does
+    not crash the target again when the testcase is given. To be able to still
+    re-trigger these crashes you can use the `AFL_PERSISTENT_RECORD` variable
+    with a value of how many previous fuzz cases to keep prio a crash.
+    if set to e.g. 10, then the 9 previous inputs are written to
+    out/default/crashes as RECORD:000000,cnt:000000 to RECORD:000000,cnt:000008
+    and RECORD:000000,cnt:000009 being the crash case.
+    NOTE: This option needs to be enabled in config.h first!
+
   - If you are Jakub, you may need `AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES`.
     Others need not apply, unless they also want to disable the
     `/proc/sys/kernel/core_pattern` check.
@@ -614,7 +616,7 @@ optimal values if not already present in the environment:
     override this by setting `LD_BIND_LAZY` beforehand, but it is almost
     certainly pointless.
 
-  - By default, `ASAN_OPTIONS` are set to:
+  - By default, `ASAN_OPTIONS` are set to (among others):
 ```
     abort_on_error=1
     detect_leaks=0
@@ -635,7 +637,14 @@ optimal values if not already present in the environment:
     msan_track_origins=0
     allocator_may_return_null=1
 ```
-  Be sure to include the first one when customizing anything, since some
-    MSAN versions don't call `abort()` on error, and we need a way to detect
-    faults.
+  - Similarly, the default `LSAN_OPTIONS` are set to:
+```
+    exit_code=23
+    fast_unwind_on_malloc=0
+    symbolize=0
+    print_suppressions=0
+```
+  Be sure to include the first ones for LSAN and MSAN when customizing
+     anything, since some MSAN and LSAN versions don't call `abort()` on
+     error, and we need a way to detect faults.
 
diff --git a/docs/ideas.md b/docs/ideas.md
index 0130cf61..e25d3ba6 100644
--- a/docs/ideas.md
+++ b/docs/ideas.md
@@ -3,42 +3,6 @@
 In the following, we describe a variety of ideas that could be implemented
 for future AFL++ versions.
 
-# GSoC 2021
-
-All GSoC 2021 projects will be in the Rust development language!
-
-## UI for libaflrs
-
-Write a user interface to libaflrs, the upcoming backend of afl++.
-This might look like the afl-fuzz UI, but you can improve on it - and should!
-
-## Schedulers for libaflrs
-
-Schedulers is a mechanism that selects items from the fuzzing corpus based
-on strategy and randomness. One scheduler might focus on long paths,
-another on rarity of edges disocvered, still another on a combination on
-things. Some of the schedulers in afl++ have to be ported, but you are free
-to come up with your own if you want to - and see how it performs.
-
-## Forkserver support for libaflrs
-
-The current libaflrs implementation fuzzes in-memory, however obviously we
-want to support afl instrumented binaries as well.
-Hence a forkserver support needs to be implemented - forking off the target
-and talking to the target via a socketpair and the communication protocol
-within.
-
-## More Observers for libaflrs
-
-An observer is measuring functionality that looks at the target being fuzzed
-and documents something about it. In traditional fuzzing this is the coverage
-in the target, however we want to add various more observers, e.g. stack depth,
-heap usage, etc. - this is a topic for an experienced Rust developer.
-
-# Generic ideas and wishlist - NOT PART OF GSoC 2021 !
-
-The below list is not part of GSoC 2021.
-
 ## Analysis software
 
 Currently analysis is done by using afl-plot, which is rather outdated.
@@ -65,6 +29,13 @@ the current Unicorn instrumentation.
 
 Mentor: any
 
+## Support other programming languages
+
+Other programming languages also use llvm hence they could (easily?) supported
+for fuzzing, e.g. mono, swift, go, kotlin native, fortran, ...
+
+Mentor: vanhauser-thc
+
 ## Machine Learning
 
 Something with machine learning, better than [NEUZZ](https://github.com/dongdongshe/neuzz) :-)
diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md
index 2b3bc028..f55aeaf2 100644
--- a/docs/notes_for_asan.md
+++ b/docs/notes_for_asan.md
@@ -28,6 +28,13 @@ Note that ASAN is incompatible with -static, so be mindful of that.
 
 (You can also use AFL_USE_MSAN=1 to enable MSAN instead.)
 
+When compiling with AFL_USE_LSAN, the leak sanitizer will normally run
+when the program exits. In order to utilize this check at different times,
+such as at the end of a loop, you may use the macro __AFL_LEAK_CHECK();.
+This macro will report a crash in afl-fuzz if any memory is left leaking
+at this stage. You can also use LSAN_OPTIONS and a supressions file
+for more fine-tuned checking, however make sure you keep exitcode=23.
+
 NOTE: if you run several secondary instances, only one should run the target
 compiled with ASAN (and UBSAN, CFISAN), the others should run the target with
 no sanitizers compiled in.
diff --git a/docs/perf_tips.md b/docs/perf_tips.md
index fbcb4d8d..c5968206 100644
--- a/docs/perf_tips.md
+++ b/docs/perf_tips.md
@@ -69,9 +69,6 @@ If you are only interested in specific parts of the code being fuzzed, you can
 instrument_files the files that are actually relevant. This improves the speed and
 accuracy of afl. See instrumentation/README.instrument_list.md
 
-Also use the InsTrim mode on larger binaries, this improves performance and
-coverage a lot.
-
 ## 4. Profile and optimize the binary
 
 Check for any parameters or settings that obviously improve performance. For
diff --git a/docs/status_screen.md b/docs/status_screen.md
index 0329d960..e3abcc5f 100644
--- a/docs/status_screen.md
+++ b/docs/status_screen.md
@@ -251,8 +251,9 @@ exceed it by a margin sufficient to be classified as hangs.
   | arithmetics : 53/2.54M, 0/537k, 0/55.2k             |
   |  known ints : 8/322k, 12/1.32M, 10/1.70M            |
   |  dictionary : 9/52k, 1/53k, 1/24k                   |
-  |       havoc : 1903/20.0M, 0/0                       |
-  |        trim : 20.31%/9201, 17.05%                   |
+  |havoc/splice : 1903/20.0M, 0/0                       |
+  |py/custom/rq : unused, 53/2.54M, unused              |
+  |    trim/eff : 20.31%/9201, 17.05%                   |
   +-----------------------------------------------------+
 ```
 
@@ -268,6 +269,12 @@ goal. Finally, the third number shows the proportion of bytes that, although
 not possible to remove, were deemed to have no effect and were excluded from
 some of the more expensive deterministic fuzzing steps.
 
+Note that when deterministic mutation mode is off (which is the default
+because it is not very efficient) the first five lines display
+"disabled (default, enable with -D)".
+
+Only what is activated will have counter shown.
+
 ### Path geometry
 
 ```
diff --git a/dynamic_list.txt b/dynamic_list.txt
index f0e54d92..d1905d43 100644
--- a/dynamic_list.txt
+++ b/dynamic_list.txt
@@ -21,6 +21,7 @@
   "__afl_coverage_interesting";
   "__afl_fuzz_len";
   "__afl_fuzz_ptr";
+  "__afl_sharedmem_fuzzing";
   "__sanitizer_cov_trace_pc_guard";
   "__sanitizer_cov_trace_pc_guard_init";
   "__cmplog_ins_hook1";
diff --git a/frida_mode/.gitignore b/frida_mode/.gitignore
new file mode 100644
index 00000000..956b9911
--- /dev/null
+++ b/frida_mode/.gitignore
@@ -0,0 +1,5 @@
+build/
+frida_test.dat
+qemu_test.dat
+frida_out/**
+qemu_out/**
diff --git a/frida_mode/Makefile b/frida_mode/Makefile
new file mode 100644
index 00000000..822f1c6a
--- /dev/null
+++ b/frida_mode/Makefile
@@ -0,0 +1,348 @@
+PWD:=$(shell pwd)/
+INC_DIR:=$(PWD)include/
+SRC_DIR:=$(PWD)src/
+INCLUDES:=$(wildcard $(INC_DIR)*.h)
+SOURCES:=$(wildcard $(SRC_DIR)*.c)
+BUILD_DIR:=$(PWD)build/
+CFLAGS+=-fPIC -D_GNU_SOURCE
+
+FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
+FRIDA_TRACE:=$(FRIDA_BUILD_DIR)afl-frida-trace.so
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+ TESTINSTR_BASE:=0x0000aaaaaaaaa000
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ TESTINSTR_BASE:=0x0000555555554000
+endif
+
+ifeq "$(shell uname)" "Darwin"
+ OS:=macos
+ AFL_FRIDA_INST_RANGES=0x0000000000001000-0xFFFFFFFFFFFFFFFF
+ CFLAGS:=$(CFLAGS) -Wno-deprecated-declarations
+ TEST_LDFLAGS:=-undefined dynamic_lookup
+endif
+ifeq "$(shell uname)" "Linux"
+ OS:=linux
+ AFL_FRIDA_INST_RANGES=$(shell $(PWD)test/testinstr.py -f $(BUILD_DIR)testinstr -s .testinstr -b $(TESTINSTR_BASE))
+ CFLAGS:=$(CFLAGS) -Wno-prio-ctor-dtor
+ TEST_LDFLAGS:=
+endif
+
+ifndef OS
+ $(error "Operating system unsupported")
+endif
+
+VERSION=14.2.13
+GUM_DEVKIT_FILENAME=frida-gum-devkit-$(VERSION)-$(OS)-$(ARCH).tar.xz
+GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(VERSION)/$(GUM_DEVKIT_FILENAME)"
+GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
+GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gum.a
+GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gum.h
+
+TEST_BUILD_DIR:=$(BUILD_DIR)test/
+
+LIBPNG_FILE:=$(TEST_BUILD_DIR)libpng-1.2.56.tar.gz
+LIBPNG_URL:=https://downloads.sourceforge.net/project/libpng/libpng12/older-releases/1.2.56/libpng-1.2.56.tar.gz
+LIBPNG_DIR:=$(TEST_BUILD_DIR)libpng-1.2.56/
+LIBPNG_MAKEFILE:=$(LIBPNG_DIR)Makefile
+LIBPNG_LIB:=$(LIBPNG_DIR).libs/libpng12.a
+
+HARNESS_FILE:=$(TEST_BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(TEST_BUILD_DIR)StandaloneFuzzTargetMain.o
+HARNESS_URL:="https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c"
+
+PNGTEST_FILE:=$(TEST_BUILD_DIR)target.cc
+PNGTEST_OBJ:=$(TEST_BUILD_DIR)target.o
+PNGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libpng-1.2.56/target.cc"
+
+TEST_BIN:=$(TEST_BUILD_DIR)pngtest
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)test/testinstr.c
+
+TEST_DATA_DIR:=$(PWD)build/test/libpng-1.2.56/contrib/pngsuite/
+
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)testinstr_in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)test.dat
+FRIDA_OUT:=$(PWD)frida_out
+QEMU_OUT:=$(PWD)qemu_out
+
+.PHONY: all frida test clean format test_frida test_qemu compare testinstr test_testinstr standalone
+
+all: $(FRIDA_TRACE)
+
+frida: $(FRIDA_TRACE)
+
+$(BUILD_DIR):
+	mkdir -p $(BUILD_DIR)
+
+############################# FRIDA ############################################
+$(FRIDA_BUILD_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR)
+	wget -O $@ $(GUM_DEVKIT_URL)
+
+$(GUM_DEVIT_LIBRARY): | $(GUM_DEVKIT_TARBALL)
+	tar Jxvf $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
+
+$(GUM_DEVIT_HEADER): | $(GUM_DEVKIT_TARBALL)
+	tar Jxvf $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
+
+$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(SOURCES) Makefile | $(FRIDA_BUILD_DIR)
+	$(CC) -shared \
+		$(CFLAGS) \
+		-o $@ $(SOURCES) \
+		$(GUM_DEVIT_LIBRARY) \
+		-I $(FRIDA_BUILD_DIR) \
+		-I .. \
+		-I ../include \
+		-I $(INC_DIR) \
+		../instrumentation/afl-compiler-rt.o.c \
+		-lpthread -ldl -lresolv
+
+	cp -v $(FRIDA_TRACE) ../
+
+############################# TEST #############################################
+
+test: $(TEST_BIN)
+
+$(TEST_BUILD_DIR): $(BUILD_DIR)
+	mkdir -p $@
+
+$(HARNESS_FILE): | $(TEST_BUILD_DIR)
+	wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_FILE)
+	$(CC) -o $@ -c $<
+
+$(PNGTEST_FILE): | $(TEST_BUILD_DIR)
+	wget -O $@ $(PNGTEST_URL)
+
+$(PNGTEST_OBJ): $(PNGTEST_FILE) | $(LIBPNG_DIR)
+	$(CXX) -std=c++11 -I $(LIBPNG_DIR) -o $@ -c $<
+
+$(LIBPNG_FILE): | $(TEST_BUILD_DIR)
+	wget -O $@ $(LIBPNG_URL)
+
+$(LIBPNG_DIR): $(LIBPNG_FILE)
+	tar zxvf $(LIBPNG_FILE) -C $(TEST_BUILD_DIR)
+
+$(LIBPNG_MAKEFILE): | $(LIBPNG_DIR)
+	cd $(LIBPNG_DIR) && ./configure
+
+$(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
+	make -C $(LIBPNG_DIR)
+
+$(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB)
+	$(CXX) \
+		-o $@ \
+		$(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \
+		-lz \
+		$(TEST_LDFLAGS)
+
+############################# TESTINSR #########################################
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+	echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+	$(CC) -o $@ $<
+
+testinstr: $(TESTINSTBIN)
+
+############################# CLEAN ############################################
+clean:
+	rm -rf $(BUILD_DIR)
+
+############################# FORMAT ###########################################
+format:
+	cd .. && echo $(SOURCES) | xargs -L1 ./.custom-format.py -i
+	cd .. && echo $(INCLUDES) | xargs -L1 ./.custom-format.py -i
+	cd .. && ./.custom-format.py -i $(TESTINSTSRC)
+
+############################# RUN #############################################
+
+# Add the environment variable AFL_DEBUG_CHILD=1 to show printf's from the target
+
+png_frida: $(FRIDA_TRACE) $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-fuzz \
+			-O \
+			-i $(TEST_DATA_DIR) \
+			-o $(FRIDA_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+png_qemu: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-fuzz \
+			-Q \
+			-i $(TEST_DATA_DIR) \
+			-o $(QEMU_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+compare: $(FRIDA_TRACE) $(TEST_BIN)
+	cd .. && \
+		./afl-fuzz \
+			-V30 \
+			-O \
+			-i $(TEST_DATA_DIR) \
+			-o $(FRIDA_OUT) \
+			-- \
+				$(TEST_BIN) @@
+	cd .. && \
+		./afl-fuzz \
+			-V30 \
+			-Q \
+			-i $(TEST_DATA_DIR) \
+			-o $(QEMU_OUT) \
+				-- \
+					$(TEST_BIN) @@
+	cat frida_out/default/fuzzer_stats
+	cat qemu_out/default/fuzzer_stats
+
+testinstr_qemu: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+	make -C ..
+	cd .. && \
+			AFL_QEMU_INST_RANGES=$(AFL_FRIDA_INST_RANGES) \
+			./afl-fuzz \
+				-Q \
+				-i $(TESTINSTR_DATA_DIR) \
+				-o $(QEMU_OUT) \
+				-- \
+					$(TESTINSTBIN) @@
+
+testinstr_frida: $(FRIDA_TRACE) $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+	make -C ..
+	cd .. && \
+			AFL_FRIDA_INST_RANGES=$(AFL_FRIDA_INST_RANGES) \
+			AFL_FRIDA_INST_NO_OPTIMIZE=1 \
+			AFL_FRIDA_INST_NO_PREFETCH=1 \
+			AFL_FRIDA_INST_STRICT=1 \
+			./afl-fuzz \
+				-O \
+				-i $(TESTINSTR_DATA_DIR) \
+				-o $(FRIDA_OUT) \
+				-- \
+					$(TESTINSTBIN) @@
+
+standalone: $(FRIDA_TRACE) $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+	cd .. && \
+			AFL_FRIDA_INST_RANGES=$(AFL_FRIDA_INST_RANGES) \
+			AFL_DEBUG_CHILD=1 \
+			AFL_FRIDA_DEBUG_MAPS=1 \
+			AFL_FRIDA_INST_NO_OPTIMIZE=1 \
+			AFL_FRIDA_INST_NO_PREFETCH=1 \
+			AFL_FRIDA_INST_TRACE=1 \
+			AFL_FRIDA_INST_STRICT=1 \
+			LD_PRELOAD=$(FRIDA_TRACE) \
+			DYLD_INSERT_LIBRARIES=$(FRIDA_TRACE) \
+			$(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+
+tmin_qemu: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-tmin \
+			-Q \
+			-i $(TEST_DATA_DIR)basn0g01.png \
+			-o $(QEMU_OUT)/qemu-min-basn0g01.png \
+			-- \
+				$(TEST_BIN) @@
+
+tmin_frida: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-tmin \
+			-O \
+			-i $(TEST_DATA_DIR)basn0g01.png \
+			-o $(FRIDA_OUT)/qemu-min-basn0g01.png \
+			-- \
+				$(TEST_BIN)
+
+showmap_qemu: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-showmap \
+			-Q \
+			-i $(TEST_DATA_DIR) \
+			-o $(QEMU_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+showmap_frida: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-showmap \
+			-O \
+			-i $(TEST_DATA_DIR) \
+			-o $(FRIDA_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+analyze_qemu: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-analyze \
+			-Q \
+			-i $(TEST_DATA_DIR)basn0g01.png \
+			-- \
+				$(TEST_BIN) @@
+
+analyze_frida: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-analyze \
+			-O \
+			-i $(TEST_DATA_DIR)basn0g01.png \
+			-- \
+				$(TEST_BIN) @@
+
+cmin_qemu: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-cmin \
+			-Q \
+			-i $(TEST_DATA_DIR) \
+			-o $(QEMU_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+cmin_frida: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-cmin \
+			-O \
+			-i $(TEST_DATA_DIR) \
+			-o $(FRIDA_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+cmin_bash_qemu: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-cmin.bash \
+			-Q \
+			-i $(TEST_DATA_DIR) \
+			-o $(QEMU_OUT) \
+			-- \
+				$(TEST_BIN) @@
+
+cmin_bash_frida: $(TEST_BIN)
+	make -C ..
+	cd .. && \
+		./afl-cmin.bash \
+			-O \
+			-i $(TEST_DATA_DIR) \
+			-o $(FRIDA_OUT) \
+			-- \
+				$(TEST_BIN) @@
diff --git a/frida_mode/README.md b/frida_mode/README.md
new file mode 100644
index 00000000..8abee0dd
--- /dev/null
+++ b/frida_mode/README.md
@@ -0,0 +1,135 @@
+# FRIDA MODE
+The purpose of FRIDA mode is to provide an alternative binary only fuzzer for AFL
+just like that provided by QEMU mode. The intention is to provide a very similar
+user experience, right down to the options provided through environment variables.
+
+Whilst AFLplusplus already has some support for running on FRIDA [here](https://github.com/AFLplusplus/AFLplusplus/tree/stable/utils/afl_frida)
+this requires the code to be fuzzed to be provided as a shared library, it
+cannot be used to fuzz executables. Additionally, it requires the user to write
+a small harness around their target code of interest, FRIDA mode instead takes a
+different approach to avoid these limitations.
+
+# Current Progress
+As FRIDA mode is new, it is missing a lot of features. Most importantly,
+persistent mode. The design is such that it should be possible to add these
+features in a similar manner to QEMU mode and perhaps leverage some of its
+design and implementation.
+
+  | Feature/Instrumentation  | frida-mode |
+  | -------------------------|:----------:|
+  | NeverZero                |            |
+  | Persistent Mode          |            |
+  | LAF-Intel / CompCov      |            |
+  | CmpLog                   |            |
+  | Selective Instrumentation|     x      |
+  | Non-Colliding Coverage   |            |
+  | Ngram prev_loc Coverage  |            |
+  | Context Coverage         |            |
+  | Auto Dictionary          |            |
+  | Snapshot LKM Support     |            |
+
+# Compatibility
+Currently FRIDA mode supports Linux and macOS targets on both x86/x64
+architecture and aarch64. Later releases may add support for aarch32 and Windows
+targets as well as embedded linux environments.
+
+FRIDA has been used on various embedded targets using both uClibc and musl C
+runtime libraries, so porting should be possible. However, the current build
+system does not support cross compilation.
+
+## Getting Started
+To build everything run `make`.
+
+To run the benchmark sample with qemu run `make png_qemu`.
+To run the benchmark sample with frida run `make png_frida`.
+
+## Usage
+FRIDA mode requires some small modifications to `afl-fuzz` and similar tools
+in AFLplusplus. The intention is that it behaves identically to QEMU, but uses
+the 'O' switch rather than 'Q'. Whilst the options 'f', 'F', 's' or 'S' may have
+made more sense for a mode powered by FRIDA Stalker, they were all taken, so
+instead we use 'O' in hommage to the [author](https://github.com/oleavr) of
+FRIDA.
+
+Similarly, the intention is to mimic the use of environment variables used by
+QEMU where possible (although replacing `s/QEMU/FRIDA/g`). Accodingly, the
+following options are currently supported.
+
+* `AFL_FRIDA_DEBUG_MAPS` - See `AFL_QEMU_DEBUG_MAPS`
+* `AFL_FRIDA_EXCLUDE_RANGES` - See `AFL_QEMU_EXCLUDE_RANGES`
+* `AFL_FRIDA_INST_RANGES` - See `AFL_QEMU_INST_RANGES`
+
+# Performance
+
+Additionally, the intention is to be able to make a direct performance
+comparison between the two approaches. Accordingly, FRIDA mode includes a test
+target based on the [libpng](https://libpng.sourceforge.io/) benchmark used by
+[fuzzbench](https://google.github.io/fuzzbench/) and integrated with the
+[StandaloneFuzzTargetMain](https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c)
+from the llvm project. This is built and linked without any special
+modifications to suit FRIDA or QEMU. We use the test data provided with libpng
+as our corpus.
+
+Whilst not much performance tuning has been completed to date, performance is
+around 30-50% of that of QEMU mode, however, this gap may reduce with the 
+introduction of persistent mode. Performance can be tested by running 
+`make compare`, albeit a longer time measurement may be required for more 
+accurate results. 
+
+Whilst [afl_frida](https://github.com/AFLplusplus/AFLplusplus/tree/stable/utils/afl_frida)
+claims a 5-10x performance increase over QEMU, it has not been possible to
+reproduce these claims. However, the number of executions per second can vary
+dramatically as a result of the randomization of the fuzzer input. Some inputs
+may traverse relatively few paths before being rejected as invalid whilst others
+may be valid inputs or be subject to much more processing before rejection.
+Accordingly, it is recommended that testing be carried out over prolongued
+periods to gather timings which are more than indicative.
+
+# Design
+FRIDA mode is supported by using `LD_PRELOAD` (`DYLD_INSERT_LIBRARIES` on macOS)
+to inject a shared library (`afl-frida-trace.so`) into the target. This shared
+library is built using the [frida-gum](https://github.com/frida/frida-gum)
+devkit from the [FRIDA](https://github.com/frida/frida) project. One of the
+components of frida-gum is [Stalker](https://medium.com/@oleavr/anatomy-of-a-code-tracer-b081aadb0df8),
+this allows the dynamic instrumentation of running code for AARCH32, AARCH64,
+x86 and x64 architectures. Implementation details can be found
+[here](https://frida.re/docs/stalker/).
+
+Dynamic instrumentation is used to augment the target application with similar
+coverage information to that inserted by `afl-gcc` or `afl-clang`. The shared
+library is also linked to the `compiler-rt` component of AFLplusplus to feedback
+this coverage information to AFL++ and also provide a fork server. It also makes
+use of the FRIDA [prefetch](https://github.com/frida/frida-gum/blob/56dd9ba3ee9a5511b4b0c629394bf122775f1ab7/gum/gumstalker.h#L115)
+support to feedback instrumented blocks from the child to the parent using a
+shared memory region to avoid the need to regenerate instrumented blocks on each
+fork. 
+
+Whilst FRIDA allows for a normal C function to be used to augment instrumented
+code, to minimize the costs of storing and restoring all of the registers, FRIDA
+mode instead makes use of optimized assembly instead on AARCH64 and x86/64
+targets.
+
+# Advanced configuration options
+* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
+instrumentation (the default where available). Required to use
+`AFL_FRIDA_INST_TRACE`.
+* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default the child will
+report instrumented blocks back to the parent so that it can also instrument
+them and they be inherited by the next child on fork.
+* `AFL_FRIDA_INST_STRICT` - Under certain conditions, Stalker may encroach into
+excluded regions and generate both instrumented blocks and coverage data (e.g.
+indirect calls on x86). The excluded block is generally honoured as soon as
+another function is called within the excluded region and so such encroachment
+is usually of little consequence. This detail may however, hinder you when
+checking that the correct number of paths are found for testing purposes or
+similar. There is a performance penatly for this option during block compilation
+where we check the block isn't in a list of excluded ranges.
+* `AFL_FRIDA_INST_TRACE` - Generate some logging when running instrumented code.
+Requires `AFL_FRIDA_INST_NO_OPTIMIZE`.
+
+# TODO
+As can be seen from the progress section above, there are a number of features
+which are missing in its currently form. Chief amongst which is persistent mode.
+The intention is to achieve feature parity with QEMU mode in due course.
+Contributions are welcome, but please get in touch to ensure that efforts are
+deconflicted.
diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h
new file mode 100644
index 00000000..ff71bed4
--- /dev/null
+++ b/frida_mode/include/instrument.h
@@ -0,0 +1,7 @@
+#include "frida-gum.h"
+
+void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output,
+                       gpointer user_data);
+
+void instrument_init();
+
diff --git a/frida_mode/include/interceptor.h b/frida_mode/include/interceptor.h
new file mode 100644
index 00000000..5ed3cf49
--- /dev/null
+++ b/frida_mode/include/interceptor.h
@@ -0,0 +1,4 @@
+#include "frida-gum.h"
+
+void intercept(void *address, gpointer replacement, gpointer user_data);
+
diff --git a/frida_mode/include/prefetch.h b/frida_mode/include/prefetch.h
new file mode 100644
index 00000000..b7f25a97
--- /dev/null
+++ b/frida_mode/include/prefetch.h
@@ -0,0 +1,5 @@
+void prefetch_init();
+void prefetch_start(GumStalker *stalker);
+void prefetch_write(void *addr);
+void prefetch_read(GumStalker *stalker);
+
diff --git a/frida_mode/include/ranges.h b/frida_mode/include/ranges.h
new file mode 100644
index 00000000..b9394dbc
--- /dev/null
+++ b/frida_mode/include/ranges.h
@@ -0,0 +1,6 @@
+#include "frida-gum.h"
+
+void ranges_init(GumStalker *stalker);
+
+gboolean range_is_excluded(gpointer address);
+
diff --git a/frida_mode/src/instrument.c b/frida_mode/src/instrument.c
new file mode 100644
index 00000000..22910062
--- /dev/null
+++ b/frida_mode/src/instrument.c
@@ -0,0 +1,271 @@
+#include "frida-gum.h"
+#include "config.h"
+#include "debug.h"
+#include "prefetch.h"
+#include "ranges.h"
+#include "unistd.h"
+
+extern uint8_t *__afl_area_ptr;
+extern u32      __afl_map_size;
+
+uint64_t __thread previous_pc = 0;
+GumAddress current_log_impl = GUM_ADDRESS(0);
+
+static gboolean tracing = false;
+static gboolean optimize = false;
+static gboolean strict = false;
+
+#if defined(__x86_64__)
+static const guint8 afl_log_code[] = {
+
+    0x9c,                                                         /* pushfq */
+    0x50,                                                       /* push rax */
+    0x51,                                                       /* push rcx */
+    0x52,                                                       /* push rdx */
+
+    0x48, 0x8d, 0x05, 0x27,
+    0x00, 0x00, 0x00,                     /* lea rax, sym._afl_area_ptr_ptr */
+    0x48, 0x8b, 0x00,                               /* mov rax, qword [rax] */
+    0x48, 0x8b, 0x00,                               /* mov rax, qword [rax] */
+    0x48, 0x8d, 0x0d, 0x22,
+    0x00, 0x00, 0x00,                       /* lea rcx, sym.previous_pc     */
+    0x48, 0x8b, 0x11,                               /* mov rdx, qword [rcx] */
+    0x48, 0x8b, 0x12,                               /* mov rdx, qword [rdx] */
+    0x48, 0x31, 0xfa,                                       /* xor rdx, rdi */
+    0xfe, 0x04, 0x10,                               /* inc byte [rax + rdx] */
+    0x48, 0xd1, 0xef,                                         /* shr rdi, 1 */
+    0x48, 0x8b, 0x01,                               /* mov rax, qword [rcx] */
+    0x48, 0x89, 0x38,                               /* mov qword [rax], rdi */
+
+    0x5a,                                                        /* pop rdx */
+    0x59,                                                        /* pop rcx */
+    0x58,                                                        /* pop rax */
+    0x9d,                                                          /* popfq */
+
+    0xc3,                                                            /* ret */
+
+    /* Read-only data goes here: */
+    /* uint8_t** afl_area_ptr_ptr */
+    /* uint64_t* afl_prev_loc_ptr */
+
+};
+
+void instrument_coverage_optimize(const cs_insn *   instr,
+                                  GumStalkerOutput *output) {
+
+  guint64 current_pc = instr->address;
+  guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
+  area_offset &= MAP_SIZE - 1;
+  GumX86Writer *cw = output->writer.x86;
+
+  if (current_log_impl == 0 ||
+      !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
+      !gum_x86_writer_can_branch_directly_between(cw->pc + 128,
+                                                  current_log_impl)) {
+
+    gconstpointer after_log_impl = cw->code + 1;
+
+    gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
+
+    current_log_impl = cw->pc;
+    gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+
+    uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
+    uint64_t *afl_prev_loc_ptr = &previous_pc;
+    gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
+                             sizeof(afl_area_ptr_ptr));
+    gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
+                             sizeof(afl_prev_loc_ptr));
+
+    gum_x86_writer_put_label(cw, after_log_impl);
+
+  }
+
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+                                        -GUM_RED_ZONE_SIZE);
+  gum_x86_writer_put_push_reg(cw, GUM_REG_RDI);
+  gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, area_offset);
+  gum_x86_writer_put_call_address(cw, current_log_impl);
+  gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI);
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+                                        GUM_RED_ZONE_SIZE);
+
+}
+
+#elif defined(__aarch64__)
+static const guint8 afl_log_code[] = {
+
+    // __afl_area_ptr[current_pc ^ previous_pc]++;
+    // previous_pc = current_pc >> 1;
+    0xE1, 0x0B, 0xBF, 0xA9,  // stp x1, x2, [sp, -0x10]!
+    0xE3, 0x13, 0xBF, 0xA9,  // stp x3, x4, [sp, -0x10]!
+
+    // x0 = current_pc
+    0xc1, 0x01, 0x00, 0x58,  // ldr x1, #0x38, =&__afl_area_ptr
+    0x21, 0x00, 0x40, 0xf9,  // ldr x1, [x1] (=__afl_area_ptr)
+
+    0xc2, 0x01, 0x00, 0x58,  // ldr x2, #0x38, =&previous_pc
+    0x42, 0x00, 0x40, 0xf9,  // ldr x2, [x2] (=previous_pc)
+
+    // __afl_area_ptr[current_pc ^ previous_pc]++;
+    0x42, 0x00, 0x00, 0xca,  // eor x2, x2, x0
+    0x23, 0x68, 0x62, 0xf8,  // ldr x3, [x1, x2]
+    0x63, 0x04, 0x00, 0x91,  // add x3, x3, #1
+    0x23, 0x68, 0x22, 0xf8,  // str x3, [x1, x2]
+
+    // previous_pc = current_pc >> 1;
+    0xe0, 0x07, 0x40, 0x8b,  // add x0, xzr, x0, LSR #1
+    0xe2, 0x00, 0x00, 0x58,  // ldr x2, #0x1c, =&previous_pc
+    0x40, 0x00, 0x00, 0xf9,  // str x0, [x2]
+
+    0xE3, 0x13, 0xc1, 0xA8,  // ldp x3, x4, [sp], #0x10
+    0xE1, 0x0B, 0xc1, 0xA8,  // ldp x1, x2, [sp], #0x10
+    0xC0, 0x03, 0x5F, 0xD6,  // ret
+
+    // &afl_area_ptr_ptr
+    // &afl_prev_loc_ptr
+
+};
+
+void instrument_coverage_optimize(const cs_insn *   instr,
+                                  GumStalkerOutput *output) {
+
+  guint64 current_pc = instr->address;
+  guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
+  area_offset &= MAP_SIZE - 1;
+  GumArm64Writer *cw = output->writer.arm64;
+
+  if (current_log_impl == 0 ||
+      !gum_arm64_writer_can_branch_directly_between(cw, cw->pc,
+                                                    current_log_impl) ||
+      !gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128,
+                                                    current_log_impl)) {
+
+    gconstpointer after_log_impl = cw->code + 1;
+
+    gum_arm64_writer_put_b_label(cw, after_log_impl);
+
+    current_log_impl = cw->pc;
+    gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+
+    uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
+    uint64_t *afl_prev_loc_ptr = &previous_pc;
+    gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
+                               sizeof(afl_area_ptr_ptr));
+    gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
+                               sizeof(afl_prev_loc_ptr));
+
+    gum_arm64_writer_put_label(cw, after_log_impl);
+
+  }
+
+  gum_arm64_writer_put_stp_reg_reg_reg_offset(
+      cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE),
+      GUM_INDEX_PRE_ADJUST);
+  gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset);
+  gum_arm64_writer_put_bl_imm(cw, current_log_impl);
+  gum_arm64_writer_put_ldp_reg_reg_reg_offset(
+      cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE,
+      GUM_INDEX_POST_ADJUST);
+
+}
+
+#endif
+
+static void on_basic_block(GumCpuContext *context, gpointer user_data) {
+
+  /*
+   * This function is performance critical as it is called to instrument every
+   * basic block. By moving our print buffer to a global, we avoid it affecting
+   * the critical path with additional stack adjustments if tracing is not
+   * enabled. If tracing is enabled, then we're printing a load of diagnostic
+   * information so this overhead is unlikely to be noticeable.
+   */
+  static char buffer[200];
+  int         len;
+  guint64     current_pc = (guint64)user_data;
+  if (tracing) {
+
+    /* Avoid any functions which may cause an allocation since the target app
+     * may already be running inside malloc and it isn't designed to be
+     * re-entrant on a single thread */
+    len = snprintf(buffer, sizeof(buffer),
+                   "current_pc: 0x%016" G_GINT64_MODIFIER
+                   "x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n",
+                   current_pc, previous_pc);
+
+    write(STDOUT_FILENO, buffer, len + 1);
+
+  }
+
+  current_pc = (current_pc >> 4) ^ (current_pc << 8);
+  current_pc &= MAP_SIZE - 1;
+
+  __afl_area_ptr[current_pc ^ previous_pc]++;
+  previous_pc = current_pc >> 1;
+
+}
+
+void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output,
+                       gpointer user_data) {
+
+  const cs_insn *instr;
+  gboolean       begin = TRUE;
+  while (gum_stalker_iterator_next(iterator, &instr)) {
+
+    if (begin) {
+
+      prefetch_write((void *)instr->address);
+      if (!strict || !range_is_excluded((void *)instr->address)) {
+
+        if (optimize) {
+
+          instrument_coverage_optimize(instr, output);
+
+        } else {
+
+          gum_stalker_iterator_put_callout(iterator, on_basic_block,
+                                           (gpointer)instr->address, NULL);
+
+        }
+
+      }
+
+      begin = FALSE;
+
+    }
+
+    gum_stalker_iterator_keep(iterator);
+
+  }
+
+}
+
+void instrument_init() {
+
+  optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
+  tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
+  strict = (getenv("AFL_FRIDA_INST_STRICT") != NULL);
+
+#if !defined(__x86_64__) && !defined(__aarch64__)
+  optimize = false;
+#endif
+
+  OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' ');
+  OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' ');
+  OKF("Instrumentation - strict [%c]", strict ? 'X' : ' ');
+
+  if (tracing && optimize) {
+
+    FATAL("AFL_FRIDA_INST_OPTIMIZE and AFL_FRIDA_INST_TRACE are incompatible");
+
+  }
+
+  if (__afl_map_size != 0x10000) {
+
+    FATAL("Bad map size: 0x%08x", __afl_map_size);
+
+  }
+
+}
+
diff --git a/frida_mode/src/interceptor.c b/frida_mode/src/interceptor.c
new file mode 100644
index 00000000..ba05a80a
--- /dev/null
+++ b/frida_mode/src/interceptor.c
@@ -0,0 +1,16 @@
+#include "frida-gum.h"
+#include "debug.h"
+
+#include "interceptor.h"
+
+void intercept(void *address, gpointer replacement, gpointer user_data) {
+
+  GumInterceptor *interceptor = gum_interceptor_obtain();
+  gum_interceptor_begin_transaction(interceptor);
+  GumReplaceReturn ret =
+      gum_interceptor_replace(interceptor, address, replacement, user_data);
+  if (ret != GUM_ATTACH_OK) { FATAL("gum_interceptor_attach: %d", ret); }
+  gum_interceptor_end_transaction(interceptor);
+
+}
+
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
new file mode 100644
index 00000000..7505c2f9
--- /dev/null
+++ b/frida_mode/src/main.c
@@ -0,0 +1,149 @@
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef __APPLE__
+  #include <mach/mach.h>
+  #include <mach-o/dyld_images.h>
+#else
+  #include <sys/wait.h>
+  #include <sys/personality.h>
+#endif
+
+#include "frida-gum.h"
+#include "config.h"
+#include "debug.h"
+
+#include "interceptor.h"
+#include "instrument.h"
+#include "prefetch.h"
+#include "ranges.h"
+
+#ifdef __APPLE__
+extern mach_port_t mach_task_self();
+extern GumAddress  gum_darwin_find_entrypoint(mach_port_t task);
+#else
+extern int  __libc_start_main(int *(main)(int, char **, char **), int argc,
+                              char **ubp_av, void (*init)(void),
+                              void (*fini)(void), void (*rtld_fini)(void),
+                              void(*stack_end));
+#endif
+
+typedef int *(*main_fn_t)(int argc, char **argv, char **envp);
+
+static main_fn_t      main_fn = NULL;
+static GumStalker *   stalker = NULL;
+static GumMemoryRange code_range = {0};
+
+extern void              __afl_manual_init();
+extern __thread uint64_t previous_pc;
+
+static int on_fork() {
+
+  prefetch_read(stalker);
+  return fork();
+
+}
+
+#ifdef __APPLE__
+static void on_main_os(int argc, char **argv, char **envp) {
+
+}
+
+#else
+static void on_main_os(int argc, char **argv, char **envp) {
+
+  /* Personality doesn't affect the current process, it only takes effect on
+   * evec */
+  int persona = personality(ADDR_NO_RANDOMIZE);
+  if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
+
+  GumInterceptor *interceptor = gum_interceptor_obtain();
+
+  gum_interceptor_begin_transaction(interceptor);
+  gum_interceptor_revert(interceptor, __libc_start_main);
+  gum_interceptor_end_transaction(interceptor);
+  gum_interceptor_flush(interceptor);
+
+}
+
+#endif
+
+static int *on_main(int argc, char **argv, char **envp) {
+
+  on_main_os(argc, argv, envp);
+
+  stalker = gum_stalker_new();
+  if (stalker == NULL) { FATAL("Failed to initialize stalker"); }
+
+  gum_stalker_set_trust_threshold(stalker, 0);
+
+  GumStalkerTransformer *transformer =
+      gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL);
+
+  instrument_init();
+  prefetch_init();
+  ranges_init(stalker);
+
+  intercept(fork, on_fork, stalker);
+
+  gum_stalker_follow_me(stalker, transformer, NULL);
+  gum_stalker_deactivate(stalker);
+
+  __afl_manual_init();
+
+  /* Child here */
+  previous_pc = 0;
+  prefetch_start(stalker);
+  main_fn(argc, argv, envp);
+  _exit(0);
+
+}
+
+#ifdef __APPLE__
+static void intercept_main() {
+
+  mach_port_t task = mach_task_self();
+  OKF("Task Id: %u", task);
+  GumAddress entry = gum_darwin_find_entrypoint(task);
+  OKF("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry);
+  void *main = GSIZE_TO_POINTER(entry);
+  main_fn = main;
+  intercept(main, on_main, NULL);
+
+}
+
+#else
+static int on_libc_start_main(int *(main)(int, char **, char **), int argc,
+                              char **ubp_av, void (*init)(void),
+                              void (*fini)(void), void (*rtld_fini)(void),
+                              void(*stack_end)) {
+
+  main_fn = main;
+  intercept(main, on_main, NULL);
+  return __libc_start_main(main, argc, ubp_av, init, fini, rtld_fini,
+                           stack_end);
+
+}
+
+static void intercept_main() {
+
+  intercept(__libc_start_main, on_libc_start_main, NULL);
+
+}
+
+#endif
+
+__attribute__((constructor)) static void init() {
+
+  gum_init_embedded();
+  if (!gum_stalker_is_supported()) {
+
+    gum_deinit_embedded();
+    FATAL("Failed to initialize embedded");
+
+  }
+
+  intercept_main();
+
+}
+
diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c
new file mode 100644
index 00000000..64633c1c
--- /dev/null
+++ b/frida_mode/src/prefetch.c
@@ -0,0 +1,121 @@
+#include <errno.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+
+#include "frida-gum.h"
+#include "prefetch.h"
+#include "debug.h"
+
+#define TRUST 0
+#define PREFETCH_SIZE 65536
+#define PREFETCH_ENTRIES ((PREFETCH_SIZE - sizeof(size_t)) / sizeof(void *))
+
+typedef struct {
+
+  size_t count;
+  void * entry[PREFETCH_ENTRIES];
+
+} prefetch_data_t;
+
+static prefetch_data_t *prefetch_data = NULL;
+
+static int prefetch_shm_id = -1;
+
+/*
+ * We do this from the transformer since we need one anyway for coverage, this
+ * saves the need to use an event sink.
+ */
+void prefetch_write(void *addr) {
+
+  /* Bail if we aren't initialized */
+  if (prefetch_data == NULL) return;
+
+  /*
+   * Our shared memory IPC is large enough for about 1000 entries, we can fine
+   * tune this if we need to. But if we have more new blocks that this in a
+   * single run then we ignore them and we'll pick them up next time.
+   */
+  if (prefetch_data->count >= PREFETCH_ENTRIES) return;
+
+  /*
+   * Write the block address to the SHM IPC and increment the number of entries.
+   */
+
+  prefetch_data->entry[prefetch_data->count] = addr;
+  prefetch_data->count++;
+
+}
+
+/*
+ * Read the IPC region one block at the time and prefetch it
+ */
+void prefetch_read(GumStalker *stalker) {
+
+  if (prefetch_data == NULL) return;
+
+  for (size_t i = 0; i < prefetch_data->count; i++) {
+
+    void *addr = prefetch_data->entry[i];
+    gum_stalker_prefetch(stalker, addr, 1);
+
+  }
+
+  /*
+   * Reset the entry count to indicate we have finished with it and it can be
+   * refilled by the child.
+   */
+  prefetch_data->count = 0;
+
+}
+
+void prefetch_init() {
+
+  g_assert_cmpint(sizeof(prefetch_data_t), ==, PREFETCH_SIZE);
+  gboolean prefetch = (getenv("AFL_FRIDA_INST_NO_PREFETCH") == NULL);
+
+  OKF("Instrumentation - prefetch [%c]", prefetch ? 'X' : ' ');
+
+  if (!prefetch) { return; }
+  /*
+   * Make our shared memory, we can attach before we fork, just like AFL does
+   * with the coverage bitmap region and fork will take care of ensuring both
+   * the parent and child see the same consistent memory region.
+   */
+  prefetch_shm_id =
+      shmget(IPC_PRIVATE, sizeof(prefetch_data_t), IPC_CREAT | IPC_EXCL | 0600);
+  if (prefetch_shm_id < 0) {
+
+    FATAL("prefetch_shm_id < 0 - errno: %d\n", errno);
+
+  }
+
+  prefetch_data = shmat(prefetch_shm_id, NULL, 0);
+  g_assert(prefetch_data != MAP_FAILED);
+
+  /*
+   * Configure the shared memory region to be removed once the process dies.
+   */
+  if (shmctl(prefetch_shm_id, IPC_RMID, NULL) < 0) {
+
+    FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
+
+  }
+
+  /* Clear it, not sure it's necessary, just seems like good practice */
+  memset(prefetch_data, '\0', sizeof(prefetch_data_t));
+
+}
+
+__attribute__((noinline)) static void prefetch_activation() {
+
+  asm volatile("");
+
+}
+
+void prefetch_start(GumStalker *stalker) {
+
+  gum_stalker_activate(stalker, prefetch_activation);
+  prefetch_activation();
+
+}
+
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
new file mode 100644
index 00000000..49ef5a62
--- /dev/null
+++ b/frida_mode/src/ranges.c
@@ -0,0 +1,394 @@
+// 0x123-0x321
+// module.so
+
+#include "ranges.h"
+#include "debug.h"
+
+#define MAX_RANGES 20
+
+typedef struct {
+
+  gchar *         suffix;
+  GumMemoryRange *range;
+  gboolean        done;
+
+} convert_name_ctx_t;
+
+typedef struct {
+
+  GumStalker *stalker;
+  GArray *    array;
+
+} include_range_ctx_t;
+
+GArray * ranges = NULL;
+gboolean exclude_ranges = false;
+
+static void convert_address_token(gchar *token, GumMemoryRange *range) {
+
+  gchar **tokens;
+  int     token_count;
+  tokens = g_strsplit(token, "-", 2);
+  for (token_count = 0; tokens[token_count] != NULL; token_count++) {}
+
+  if (token_count != 2) {
+
+    FATAL("Invalid range (should have two addresses seperated by a '-'): %s\n",
+          token);
+
+  }
+
+  gchar *from_str = tokens[0];
+  gchar *to_str = tokens[1];
+
+  if (!g_str_has_prefix(from_str, "0x")) {
+
+    FATAL("Invalid range: %s - Start address should have 0x prefix: %s\n",
+          token, from_str);
+
+  }
+
+  if (!g_str_has_prefix(to_str, "0x")) {
+
+    FATAL("Invalid range: %s - End address should have 0x prefix: %s\n", token,
+          to_str);
+
+  }
+
+  from_str = &from_str[2];
+  to_str = &to_str[2];
+
+  for (char *c = from_str; *c != '\0'; c++) {
+
+    if (!g_ascii_isxdigit(*c)) {
+
+      FATAL("Invalid range: %s - Start address not formed of hex digits: %s\n",
+            token, from_str);
+
+    }
+
+  }
+
+  for (char *c = to_str; *c != '\0'; c++) {
+
+    if (!g_ascii_isxdigit(*c)) {
+
+      FATAL("Invalid range: %s - End address not formed of hex digits: %s\n",
+            token, to_str);
+
+    }
+
+  }
+
+  guint64 from = g_ascii_strtoull(from_str, NULL, 16);
+  if (from == 0) {
+
+    FATAL("Invalid range: %s - Start failed hex conversion: %s\n", token,
+          from_str);
+
+  }
+
+  guint64 to = g_ascii_strtoull(to_str, NULL, 16);
+  if (to == 0) {
+
+    FATAL("Invalid range: %s - End failed hex conversion: %s\n", token, to_str);
+
+  }
+
+  if (from >= to) {
+
+    FATAL("Invalid range: %s - Start (0x%016" G_GINT64_MODIFIER
+          "x) must be less than end "
+          "(0x%016" G_GINT64_MODIFIER "x)\n",
+          token, from, to);
+
+  }
+
+  range->base_address = from;
+  range->size = to - from;
+
+  g_strfreev(tokens);
+
+}
+
+static gboolean convert_name_token_for_module(const GumModuleDetails *details,
+                                              gpointer user_data) {
+
+  convert_name_ctx_t *ctx = (convert_name_ctx_t *)user_data;
+  if (details->path == NULL) { return true; };
+
+  if (!g_str_has_suffix(details->path, ctx->suffix)) { return true; };
+
+  OKF("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
+      "x-0x%016" G_GINT64_MODIFIER "x %s",
+      ctx->suffix, details->range->base_address,
+      details->range->base_address + details->range->size, details->path);
+
+  *ctx->range = *details->range;
+  ctx->done = true;
+  return false;
+
+}
+
+static void convert_name_token(gchar *token, GumMemoryRange *range) {
+
+  gchar *            suffix = g_strconcat("/", token, NULL);
+  convert_name_ctx_t ctx = {.suffix = suffix, .range = range, .done = false};
+
+  gum_process_enumerate_modules(convert_name_token_for_module, &ctx);
+  if (!ctx.done) { FATAL("Failed to resolve module: %s\n", token); }
+  g_free(suffix);
+
+}
+
+static void convert_token(gchar *token, GumMemoryRange *range) {
+
+  if (g_strrstr(token, "-")) {
+
+    convert_address_token(token, range);
+
+  } else {
+
+    convert_name_token(token, range);
+
+  }
+
+  OKF("Converted token: %s -> 0x%016" G_GINT64_MODIFIER
+      "x-0x%016" G_GINT64_MODIFIER "x\n",
+      token, range->base_address, range->base_address + range->size);
+
+}
+
+static gboolean include_ranges(const GumRangeDetails *details,
+                               gpointer               user_data) {
+
+  include_range_ctx_t *ctx = (include_range_ctx_t *)user_data;
+  GArray *             array = (GArray *)ctx->array;
+  GumAddress           base = details->range->base_address;
+  GumAddress limit = details->range->base_address + details->range->size;
+
+  OKF("Range for inclusion 0x%016" G_GINT64_MODIFIER
+      "x-0x%016" G_GINT64_MODIFIER "x",
+      base, limit);
+
+  for (int i = 0; i < array->len; i++) {
+
+    GumMemoryRange *range = &g_array_index(array, GumMemoryRange, i);
+    GumAddress      range_base = range->base_address;
+    GumAddress      range_limit = range->base_address + range->size;
+
+    /* Before the region */
+    if (range_limit < base) { continue; }
+
+    /* After the region */
+    if (range_base > limit) {
+
+      GumMemoryRange exclude = {.base_address = base, .size = limit - base};
+      OKF("\t Excluding 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
+          "x",
+          base, limit);
+      gum_stalker_exclude(ctx->stalker, &exclude);
+      return true;
+
+    }
+
+    /* Overlap the start of the region */
+    if (range_base < base) {
+
+      /* Range contains the region */
+      if (range_limit > limit) {
+
+        return true;
+
+      } else {
+
+        base = range_limit;
+        continue;
+
+      }
+
+      /* Overlap the end of the region */
+
+    } else {
+
+      GumMemoryRange exclude = {.base_address = base,
+                                .size = range_base - base};
+      OKF("\t Excluding 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
+          "x",
+          base, range_base);
+      gum_stalker_exclude(ctx->stalker, &exclude);
+      /* Extend past the end of the region */
+      if (range_limit >= limit) {
+
+        return true;
+
+        /* Contained within the region */
+
+      } else {
+
+        base = range_limit;
+        continue;
+
+      }
+
+    }
+
+  }
+
+  GumMemoryRange exclude = {.base_address = base, .size = limit - base};
+  OKF("\t Excluding 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "x",
+      base, limit);
+  gum_stalker_exclude(ctx->stalker, &exclude);
+  return true;
+
+}
+
+gint range_sort(gconstpointer a, gconstpointer b) {
+
+  return ((GumMemoryRange *)a)->base_address -
+         ((GumMemoryRange *)b)->base_address;
+
+}
+
+static gboolean print_ranges(const GumRangeDetails *details,
+                             gpointer               user_data) {
+
+  if (details->file == NULL) {
+
+    OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER "X",
+        details->range->base_address,
+        details->range->base_address + details->range->size);
+
+  } else {
+
+    OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER
+        "X %s(0x%016" G_GINT64_MODIFIER "x)",
+        details->range->base_address,
+        details->range->base_address + details->range->size,
+        details->file->path, details->file->offset);
+
+  }
+
+  return true;
+
+}
+
+void ranges_init(GumStalker *stalker) {
+
+  char *         showmaps;
+  char *         include;
+  char *         exclude;
+  char *         list;
+  gchar **       tokens;
+  int            token_count;
+  GumMemoryRange range;
+
+  int i;
+
+  showmaps = getenv("AFL_FRIDA_DEBUG_MAPS");
+  include = getenv("AFL_FRIDA_INST_RANGES");
+  exclude = getenv("AFL_FRIDA_EXCLUDE_RANGES");
+
+  if (showmaps) {
+
+    gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges, NULL);
+
+  }
+
+  if (include != NULL && exclude != NULL) {
+
+    FATAL(
+        "Cannot specifify both AFL_FRIDA_INST_RANGES and "
+        "AFL_FRIDA_EXCLUDE_RANGES");
+
+  }
+
+  if (include == NULL && exclude == NULL) { return; }
+
+  list = include == NULL ? exclude : include;
+  exclude_ranges = include == NULL ? true : false;
+
+  tokens = g_strsplit(list, ",", MAX_RANGES);
+
+  for (token_count = 0; tokens[token_count] != NULL; token_count++)
+    ;
+
+  ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), token_count);
+
+  for (i = 0; i < token_count; i++) {
+
+    convert_token(tokens[i], &range);
+    g_array_append_val(ranges, range);
+
+  }
+
+  g_array_sort(ranges, range_sort);
+
+  /* Check for overlaps */
+  for (i = 1; i < token_count; i++) {
+
+    GumMemoryRange *prev = &g_array_index(ranges, GumMemoryRange, i - 1);
+    GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i);
+    GumAddress      prev_limit = prev->base_address + prev->size;
+    GumAddress      curr_limit = curr->base_address + curr->size;
+    if (prev_limit > curr->base_address) {
+
+      FATAL("OVerlapping ranges 0x%016" G_GINT64_MODIFIER
+            "x-0x%016" G_GINT64_MODIFIER "x 0x%016" G_GINT64_MODIFIER
+            "x-0x%016" G_GINT64_MODIFIER "x",
+            prev->base_address, prev_limit, curr->base_address, curr_limit);
+
+    }
+
+  }
+
+  for (i = 0; i < token_count; i++) {
+
+    GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i);
+    GumAddress      curr_limit = curr->base_address + curr->size;
+    OKF("Range %3d - 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "x",
+        i, curr->base_address, curr_limit);
+
+  }
+
+  if (include == NULL) {
+
+    for (i = 0; i < token_count; i++) {
+
+      gum_stalker_exclude(stalker, &g_array_index(ranges, GumMemoryRange, i));
+
+    }
+
+  } else {
+
+    include_range_ctx_t ctx = {.stalker = stalker, .array = ranges};
+    gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, include_ranges, &ctx);
+
+  }
+
+  g_strfreev(tokens);
+
+}
+
+gboolean range_is_excluded(gpointer address) {
+
+  int        i;
+  GumAddress test = GUM_ADDRESS(address);
+
+  if (ranges == NULL) { return false; }
+
+  for (i = 0; i < ranges->len; i++) {
+
+    GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i);
+    GumAddress      curr_limit = curr->base_address + curr->size;
+
+    if (test < curr->base_address) { return !exclude_ranges; }
+
+    if (test < curr_limit) { return exclude_ranges; }
+
+  }
+
+  return !exclude_ranges;
+
+}
+
diff --git a/frida_mode/test/testinstr.c b/frida_mode/test/testinstr.c
new file mode 100644
index 00000000..37d47f91
--- /dev/null
+++ b/frida_mode/test/testinstr.c
@@ -0,0 +1,112 @@
+/*
+   american fuzzy lop++ - a trivial program to test the build
+   --------------------------------------------------------
+   Originally written by Michal Zalewski
+   Copyright 2014 Google Inc. All rights reserved.
+   Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+     http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __APPLE__
+  #define TESTINSTR_SECTION
+#else
+  #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+TESTINSTR_SECTION void testinstr(char *buf, int len) {
+
+  if (len < 1) return;
+  buf[len] = 0;
+
+  // we support three input cases
+  if (buf[0] == '0')
+    printf("Looks like a zero to me!\n");
+  else if (buf[0] == '1')
+    printf("Pretty sure that is a one!\n");
+  else
+    printf("Neither one or zero? How quaint!\n");
+
+}
+
+int main(int argc, char **argv) {
+
+  char * file;
+  int    fd = -1;
+  off_t  len;
+  char * buf = NULL;
+  size_t n_read;
+  int    result = -1;
+
+  if (argc != 2) { return 1; }
+
+  do {
+
+    file = argv[1];
+
+    dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0) {
+
+      perror("open");
+      break;
+
+    }
+
+    len = lseek(fd, 0, SEEK_END);
+    if (len < 0) {
+
+      perror("lseek (SEEK_END)");
+      break;
+
+    }
+
+    if (lseek(fd, 0, SEEK_SET) != 0) {
+
+      perror("lseek (SEEK_SET)");
+      break;
+
+    }
+
+    buf = malloc(len);
+    if (buf == NULL) {
+
+      perror("malloc");
+      break;
+
+    }
+
+    n_read = read(fd, buf, len);
+    if (n_read != len) {
+
+      perror("read");
+      break;
+
+    }
+
+    dprintf(STDERR_FILENO, "Running:    %s: (%zd bytes)\n", file, n_read);
+
+    testinstr(buf, len);
+    dprintf(STDERR_FILENO, "Done:    %s: (%zd bytes)\n", file, n_read);
+
+    result = 0;
+
+  } while (false);
+
+  if (buf != NULL) { free(buf); }
+
+  if (fd != -1) { close(fd); }
+
+  return result;
+
+}
+
diff --git a/frida_mode/test/testinstr.py b/frida_mode/test/testinstr.py
new file mode 100755
index 00000000..f648808b
--- /dev/null
+++ b/frida_mode/test/testinstr.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+
+def process_file(file, section, base):
+    with open(file, "rb") as f:
+        for sect in ELFFile(f).iter_sections():
+            if sect.name == section:
+                start = base + sect.header["sh_offset"]
+                end = start + sect.header["sh_size"]
+                print("0x%016x-0x%016x" % (start, end))
+                return
+
+    print("Section '%s' not found in '%s'" % (section, file))
+
+
+def hex_value(x):
+    return int(x, 16)
+
+
+def main():
+    parser = argparse.ArgumentParser(description="Process some integers.")
+    parser.add_argument(
+        "-f", "--file", dest="file", type=str, help="elf file name", required=True
+    )
+    parser.add_argument(
+        "-s",
+        "--section",
+        dest="section",
+        type=str,
+        help="elf section name",
+        required=True,
+    )
+    parser.add_argument(
+        "-b",
+        "--base",
+        dest="base",
+        type=hex_value,
+        help="elf base address",
+        required=True,
+    )
+
+    args = parser.parse_args()
+    process_file(args.file, args.section, args.base)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 565e9afd..f201782a 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -384,13 +384,15 @@ typedef struct afl_env_vars {
       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, afl_autoresume, afl_cal_fast,
-      afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new;
+      afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
+      afl_exit_on_seed_issues;
 
   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_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
-      *afl_testcache_entries, *afl_kill_signal, *afl_target_env;
+      *afl_testcache_entries, *afl_kill_signal, *afl_target_env,
+      *afl_persistent_record;
 
 } afl_env_vars_t;
 
@@ -482,7 +484,6 @@ typedef struct afl_state {
       no_unlink,                        /* do not unlink cur_input          */
       debug,                            /* Debug mode                       */
       custom_only,                      /* Custom mutator only mode         */
-      python_only,                      /* Python-only mode                 */
       is_main_node,                     /* if this is the main node         */
       is_secondary_node;                /* if this is a secondary instance  */
 
@@ -571,6 +572,7 @@ typedef struct afl_state {
       blocks_eff_select,                /* Blocks selected as fuzzable      */
       start_time,                       /* Unix start time (ms)             */
       last_sync_time,                   /* Time of last sync                */
+      last_sync_cycle,                  /* Cycle no. of the last sync       */
       last_path_time,                   /* Time for most recent path (ms)   */
       last_crash_time,                  /* Time for most recent crash (ms)  */
       last_hang_time;                   /* Time for most recent hang (ms)   */
diff --git a/include/android-ashmem.h b/include/android-ashmem.h
index 91699b27..1bfd3220 100644
--- a/include/android-ashmem.h
+++ b/include/android-ashmem.h
@@ -2,26 +2,27 @@
   #ifndef _ANDROID_ASHMEM_H
     #define _ANDROID_ASHMEM_H
 
+    #define _GNU_SOURCE
+    #include <sys/syscall.h>
+    #include <unistd.h>
     #include <fcntl.h>
     #include <linux/ashmem.h>
     #include <sys/ioctl.h>
     #include <sys/mman.h>
-
-    #if __ANDROID_API__ >= 26
-      #define shmat bionic_shmat
-      #define shmctl bionic_shmctl
-      #define shmdt bionic_shmdt
-      #define shmget bionic_shmget
-    #endif
     #include <sys/shm.h>
-    #undef shmat
-    #undef shmctl
-    #undef shmdt
-    #undef shmget
     #include <stdio.h>
-
     #define ASHMEM_DEVICE "/dev/ashmem"
 
+int shmdt(const void *address) {
+
+    #if defined(SYS_shmdt)
+  return syscall(SYS_shmdt, address);
+    #else
+  return syscall(SYS_ipc, SHMDT, 0, 0, 0, address, 0);
+    #endif
+
+}
+
 int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
 
   int ret = 0;
diff --git a/include/config.h b/include/config.h
index c93a6d51..aa24ea6c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -26,7 +26,7 @@
 /* Version string: */
 
 // c = release, a = volatile github dev, e = experimental branch
-#define VERSION "++3.12c"
+#define VERSION "++3.13a"
 
 /******************************************************
  *                                                    *
@@ -71,7 +71,17 @@
 /* Maximum allowed fails per CMP value. Default: 128 */
 #define CMPLOG_FAIL_MAX 96
 
+/* -------------------------------------*/
 /* Now non-cmplog configuration options */
+/* -------------------------------------*/
+
+/* If a persistent target keeps state and found crashes are not reproducable
+   then enable this option and set the AFL_PERSISTENT_RECORD env variable
+   to a number. These number of testcases prior and including the crash case
+   will be kept and written to the crash/ directory as RECORD:... files.
+   Note that every crash will be written, not only unique ones! */
+
+//#define AFL_PERSISTENT_RECORD
 
 /* console output colors: There are three ways to configure its behavior
  * 1. default: colored outputs fixed on: defined USE_COLOR && defined
@@ -396,6 +406,10 @@
 
 #define MSAN_ERROR 86
 
+/* Distinctive exit code used to indicate LSAN trip condition: */
+
+#define LSAN_ERROR 23
+
 /* Designated file descriptors for forkserver commands (the application will
    use FORKSRV_FD and FORKSRV_FD + 1): */
 
diff --git a/include/envs.h b/include/envs.h
index d7578045..ebe98257 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -26,6 +26,7 @@ static char *afl_environment_variables[] = {
     "AFL_BENCH_UNTIL_CRASH",
     "AFL_CAL_FAST",
     "AFL_CC",
+    "AFL_CC_COMPILER",
     "AFL_CMIN_ALLOW_ANY",
     "AFL_CMIN_CRASHES_ONLY",
     "AFL_CMPLOG_ONLY_NEW",
@@ -48,8 +49,16 @@ static char *afl_environment_variables[] = {
     "AFL_DUMB_FORKSRV",
     "AFL_ENTRYPOINT",
     "AFL_EXIT_WHEN_DONE",
+    "AFL_EXIT_ON_SEED_ISSUES",
     "AFL_FAST_CAL",
     "AFL_FORCE_UI",
+    "AFL_FRIDA_DEBUG_MAPS",
+    "AFL_FRIDA_EXCLUDE_RANGES",
+    "AFL_FRIDA_INST_NO_OPTIMIZE",
+    "AFL_FRIDA_INST_NO_PREFETCH",
+    "AFL_FRIDA_INST_RANGES",
+    "AFL_FRIDA_INST_STRICT",
+    "AFL_FRIDA_INST_TRACE",
     "AFL_FUZZER_ARGS",  // oss-fuzz
     "AFL_GDB",
     "AFL_GCC_ALLOWLIST",
@@ -130,6 +139,7 @@ static char *afl_environment_variables[] = {
     "AFL_PASSTHROUGH",
     "AFL_PATH",
     "AFL_PERFORMANCE_FILE",
+    "AFL_PERSISTENT_RECORD",
     "AFL_PRELOAD",
     "AFL_TARGET_ENV",
     "AFL_PYTHON_MODULE",
@@ -173,6 +183,7 @@ static char *afl_environment_variables[] = {
     "AFL_USE_TRACE_PC",
     "AFL_USE_UBSAN",
     "AFL_USE_CFISAN",
+    "AFL_USE_LSAN",
     "AFL_WINE_PATH",
     "AFL_NO_SNAPSHOT",
     "AFL_EXPAND_HAVOC_NOW",
diff --git a/include/forkserver.h b/include/forkserver.h
index ac027f81..48db94c7 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -77,6 +77,8 @@ typedef struct afl_forkserver {
 
   bool qemu_mode;                       /* if running in qemu mode or not   */
 
+  bool frida_mode;                     /* if running in frida mode or not   */
+
   bool use_stdin;                       /* use stdin for sending data       */
 
   bool no_unlink;                       /* do not unlink cur_input          */
@@ -94,6 +96,17 @@ typedef struct afl_forkserver {
 
   char *cmplog_binary;                  /* the name of the cmplog binary    */
 
+  /* persistent mode replay functionality */
+  u32 persistent_record;                /* persistent replay setting        */
+#ifdef AFL_PERSISTENT_RECORD
+  u32  persistent_record_idx;           /* persistent replay cache ptr      */
+  u32  persistent_record_cnt;           /* persistent replay counter        */
+  u8 * persistent_record_dir;
+  u8 **persistent_record_data;
+  u32 *persistent_record_len;
+  s32  persistent_record_pid;
+#endif
+
   /* Function to kick off the forkserver child */
   void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
 
diff --git a/instrumentation/LLVMInsTrim.so.cc b/instrumentation/LLVMInsTrim.so.cc
deleted file mode 100644
index 62de6ec5..00000000
--- a/instrumentation/LLVMInsTrim.so.cc
+++ /dev/null
@@ -1,599 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-
-#include "llvm/Config/llvm-config.h"
-#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
-typedef long double max_align_t;
-#endif
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#if LLVM_VERSION_MAJOR > 3 || \
-    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
-  #include "llvm/IR/CFG.h"
-  #include "llvm/IR/Dominators.h"
-  #include "llvm/IR/DebugInfo.h"
-#else
-  #include "llvm/Support/CFG.h"
-  #include "llvm/Analysis/Dominators.h"
-  #include "llvm/DebugInfo.h"
-#endif
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/BasicBlock.h"
-#include <unordered_set>
-#include <random>
-#include <list>
-#include <string>
-#include <fstream>
-
-#include "MarkNodes.h"
-#include "afl-llvm-common.h"
-#include "llvm-alternative-coverage.h"
-
-#include "config.h"
-#include "debug.h"
-
-using namespace llvm;
-
-static cl::opt<bool> MarkSetOpt("markset", cl::desc("MarkSet"),
-                                cl::init(false));
-static cl::opt<bool> LoopHeadOpt("loophead", cl::desc("LoopHead"),
-                                 cl::init(false));
-
-namespace {
-
-struct InsTrim : public ModulePass {
-
- protected:
-  uint32_t function_minimum_size = 1;
-  char *   skip_nozero = NULL;
-
- private:
-  std::mt19937 generator;
-  int          total_instr = 0;
-
-  unsigned int genLabel() {
-
-    return generator() & (MAP_SIZE - 1);
-
-  }
-
- public:
-  static char ID;
-
-  InsTrim() : ModulePass(ID), generator(0) {
-
-    initInstrumentList();
-
-  }
-
-  void getAnalysisUsage(AnalysisUsage &AU) const override {
-
-    AU.addRequired<DominatorTreeWrapperPass>();
-
-  }
-
-#if LLVM_VERSION_MAJOR < 4
-  const char *
-#else
-  StringRef
-#endif
-  getPassName() const override {
-
-    return "InstTrim Instrumentation";
-
-  }
-
-#if LLVM_VERSION_MAJOR > 4 || \
-    (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
-  #define AFL_HAVE_VECTOR_INTRINSICS 1
-#endif
-
-  bool runOnModule(Module &M) override {
-
-    setvbuf(stdout, NULL, _IONBF, 0);
-
-    if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
-
-      SAYF(cCYA "LLVMInsTrim" VERSION cRST " by csienslab\n");
-
-    } else
-
-      be_quiet = 1;
-
-    if (getenv("AFL_DEBUG") != NULL) debug = 1;
-
-    LLVMContext &C = M.getContext();
-
-    IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
-    IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
-
-#if LLVM_VERSION_MAJOR < 9
-    char *neverZero_counters_str;
-    if ((neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO")) != NULL)
-      if (!be_quiet) OKF("LLVM neverZero activated (by hexcoder)\n");
-#endif
-    skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
-
-    if (getenv("AFL_LLVM_INSTRIM_LOOPHEAD") != NULL ||
-        getenv("LOOPHEAD") != NULL) {
-
-      LoopHeadOpt = true;
-
-    }
-
-    unsigned int PrevLocSize = 0;
-    char *       ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
-    if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
-    char *caller_str = getenv("AFL_LLVM_CALLER");
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    unsigned int ngram_size = 0;
-    /* Decide previous location vector size (must be a power of two) */
-    VectorType *PrevLocTy = NULL;
-
-    if (ngram_size_str)
-      if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
-          ngram_size > NGRAM_SIZE_MAX)
-        FATAL(
-            "Bad value of AFL_NGRAM_SIZE (must be between 2 and NGRAM_SIZE_MAX "
-            "(%u))",
-            NGRAM_SIZE_MAX);
-
-    if (ngram_size)
-      PrevLocSize = ngram_size - 1;
-    else
-#else
-    if (ngram_size_str)
-  #ifdef LLVM_VERSION_STRING
-      FATAL(
-          "Sorry, NGRAM branch coverage is not supported with llvm version %s!",
-          LLVM_VERSION_STRING);
-  #else
-    #ifndef LLVM_VERSION_PATCH
-      FATAL(
-          "Sorry, NGRAM branch coverage is not supported with llvm version "
-          "%d.%d.%d!",
-          LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, 0);
-    #else
-      FATAL(
-          "Sorry, NGRAM branch coverage is not supported with llvm version "
-          "%d.%d.%d!",
-          LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, LLVM_VERISON_PATCH);
-    #endif
-  #endif
-#endif
-      PrevLocSize = 1;
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    // IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
-    int          PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
-    IntegerType *IntLocTy =
-        IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT);
-    if (ngram_size)
-      PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize
-  #if LLVM_VERSION_MAJOR >= 12
-                                  ,
-                                  false
-  #endif
-      );
-#endif
-
-    /* Get globals for the SHM region and the previous location. Note that
-       __afl_prev_loc is thread-local. */
-
-    GlobalVariable *AFLMapPtr =
-        new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
-                           GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
-    GlobalVariable *AFLPrevLoc;
-    GlobalVariable *AFLContext = NULL;
-    LoadInst *      PrevCaller = NULL;  // for CALLER sensitive coverage
-
-    if (caller_str)
-#if defined(__ANDROID__) || defined(__HAIKU__)
-      AFLContext = new GlobalVariable(
-          M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
-#else
-      AFLContext = new GlobalVariable(
-          M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx",
-          0, GlobalVariable::GeneralDynamicTLSModel, 0, false);
-#endif
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    if (ngram_size)
-  #if defined(__ANDROID__) || defined(__HAIKU__)
-      AFLPrevLoc = new GlobalVariable(
-          M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
-          /* Initializer */ nullptr, "__afl_prev_loc");
-  #else
-      AFLPrevLoc = new GlobalVariable(
-          M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
-          /* Initializer */ nullptr, "__afl_prev_loc",
-          /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel,
-          /* AddressSpace */ 0, /* IsExternallyInitialized */ false);
-  #endif
-    else
-#endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
-      AFLPrevLoc = new GlobalVariable(
-          M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
-#else
-    AFLPrevLoc = new GlobalVariable(
-        M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
-        GlobalVariable::GeneralDynamicTLSModel, 0, false);
-#endif
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    /* Create the vector shuffle mask for updating the previous block history.
-       Note that the first element of the vector will store cur_loc, so just set
-       it to undef to allow the optimizer to do its thing. */
-
-    SmallVector<Constant *, 32> PrevLocShuffle = {UndefValue::get(Int32Ty)};
-
-    for (unsigned I = 0; I < PrevLocSize - 1; ++I)
-      PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
-
-    for (int I = PrevLocSize; I < PrevLocVecSize; ++I)
-      PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
-
-    Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
-#endif
-
-    // this is our default
-    MarkSetOpt = true;
-
-    ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
-    ConstantInt *One = ConstantInt::get(Int8Ty, 1);
-
-    u64 total_rs = 0;
-    u64 total_hs = 0;
-
-    scanForDangerousFunctions(&M);
-
-    for (Function &F : M) {
-
-      if (debug) {
-
-        uint32_t bb_cnt = 0;
-
-        for (auto &BB : F)
-          if (BB.size() > 0) ++bb_cnt;
-        DEBUGF("Function %s size %zu %u\n", F.getName().str().c_str(), F.size(),
-               bb_cnt);
-
-      }
-
-      if (!isInInstrumentList(&F)) continue;
-
-      // if the function below our minimum size skip it (1 or 2)
-      if (F.size() < function_minimum_size) { continue; }
-
-      std::unordered_set<BasicBlock *> MS;
-      if (!MarkSetOpt) {
-
-        for (auto &BB : F) {
-
-          MS.insert(&BB);
-
-        }
-
-        total_rs += F.size();
-
-      } else {
-
-        auto Result = markNodes(&F);
-        auto RS = Result.first;
-        auto HS = Result.second;
-
-        MS.insert(RS.begin(), RS.end());
-        if (!LoopHeadOpt) {
-
-          MS.insert(HS.begin(), HS.end());
-          total_rs += MS.size();
-
-        } else {
-
-          DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeSet;
-          DominatorTreeWrapperPass *                      DTWP =
-              &getAnalysis<DominatorTreeWrapperPass>(F);
-          auto DT = &DTWP->getDomTree();
-
-          total_rs += RS.size();
-          total_hs += HS.size();
-
-          for (BasicBlock *BB : HS) {
-
-            bool Inserted = false;
-            for (auto BI = pred_begin(BB), BE = pred_end(BB); BI != BE; ++BI) {
-
-              auto Edge = BasicBlockEdge(*BI, BB);
-              if (Edge.isSingleEdge() && DT->dominates(Edge, BB)) {
-
-                EdgeSet.insert({*BI, BB});
-                Inserted = true;
-                break;
-
-              }
-
-            }
-
-            if (!Inserted) {
-
-              MS.insert(BB);
-              total_rs += 1;
-              total_hs -= 1;
-
-            }
-
-          }
-
-          for (auto I = EdgeSet.begin(), E = EdgeSet.end(); I != E; ++I) {
-
-            auto PredBB = I->first;
-            auto SuccBB = I->second;
-            auto NewBB =
-                SplitBlockPredecessors(SuccBB, {PredBB}, ".split", DT, nullptr,
-#if LLVM_VERSION_MAJOR >= 8
-                                       nullptr,
-#endif
-                                       false);
-            MS.insert(NewBB);
-
-          }
-
-        }
-
-        for (BasicBlock &BB : F) {
-
-          if (MS.find(&BB) == MS.end()) { continue; }
-          IRBuilder<> IRB(&*BB.getFirstInsertionPt());
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-          if (ngram_size) {
-
-            LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
-            PrevLoc->setMetadata(M.getMDKindID("nosanitize"),
-                                 MDNode::get(C, None));
-
-            Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
-                PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask);
-            Value *UpdatedPrevLoc = IRB.CreateInsertElement(
-                ShuffledPrevLoc, ConstantInt::get(Int32Ty, genLabel()),
-                (uint64_t)0);
-
-            IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc)
-                ->setMetadata(M.getMDKindID("nosanitize"),
-                              MDNode::get(C, None));
-
-          } else
-
-#endif
-          {
-
-            IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), AFLPrevLoc);
-
-          }
-
-        }
-
-      }
-
-      int has_calls = 0;
-      for (BasicBlock &BB : F) {
-
-        auto         PI = pred_begin(&BB);
-        auto         PE = pred_end(&BB);
-        IRBuilder<>  IRB(&*BB.getFirstInsertionPt());
-        Value *      L = NULL;
-        unsigned int cur_loc;
-
-        // Context sensitive coverage
-        if (caller_str && &BB == &F.getEntryBlock()) {
-
-          PrevCaller = IRB.CreateLoad(AFLContext);
-          PrevCaller->setMetadata(M.getMDKindID("nosanitize"),
-                                  MDNode::get(C, None));
-
-          // does the function have calls? and is any of the calls larger than
-          // one basic block?
-          has_calls = 0;
-          for (auto &BB2 : F) {
-
-            if (has_calls) break;
-            for (auto &IN : BB2) {
-
-              CallInst *callInst = nullptr;
-              if ((callInst = dyn_cast<CallInst>(&IN))) {
-
-                Function *Callee = callInst->getCalledFunction();
-                if (!Callee || Callee->size() < function_minimum_size)
-                  continue;
-                else {
-
-                  has_calls = 1;
-                  break;
-
-                }
-
-              }
-
-            }
-
-          }
-
-          // if yes we store a context ID for this function in the global var
-          if (has_calls) {
-
-            ConstantInt *NewCtx = ConstantInt::get(Int32Ty, genLabel());
-            StoreInst *  StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
-            StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
-                                  MDNode::get(C, None));
-
-          }
-
-        }  // END of caller_str
-
-        if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; }
-
-        if (PI == PE) {
-
-          cur_loc = genLabel();
-          L = ConstantInt::get(Int32Ty, cur_loc);
-
-        } else {
-
-          auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
-          DenseMap<BasicBlock *, unsigned> PredMap;
-          for (PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
-
-            BasicBlock *PBB = *PI;
-            auto        It = PredMap.insert({PBB, genLabel()});
-            unsigned    Label = It.first->second;
-            // cur_loc = Label;
-            PN->addIncoming(ConstantInt::get(Int32Ty, Label), PBB);
-
-          }
-
-          L = PN;
-
-        }
-
-        /* Load prev_loc */
-        LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
-        PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-        Value *PrevLocTrans;
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-        /* "For efficiency, we propose to hash the tuple as a key into the
-           hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where
-           prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */
-
-        if (ngram_size)
-          PrevLocTrans =
-              IRB.CreateZExt(IRB.CreateXorReduce(PrevLoc), IRB.getInt32Ty());
-        else
-#endif
-          PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
-
-        if (caller_str)
-          PrevLocTrans =
-              IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCaller), Int32Ty);
-
-        /* Load SHM pointer */
-        LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
-        MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-        Value *MapPtrIdx;
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-        if (ngram_size)
-          MapPtrIdx = IRB.CreateGEP(
-              MapPtr, IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, L), Int32Ty));
-        else
-#endif
-          MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, L));
-
-        /* Update bitmap */
-        LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
-        Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
-        Value *Incr = IRB.CreateAdd(Counter, One);
-
-#if LLVM_VERSION_MAJOR < 9
-        if (neverZero_counters_str !=
-            NULL)  // with llvm 9 we make this the default as the bug in llvm is
-                   // then fixed
-#else
-        if (!skip_nozero)
-#endif
-        {
-
-          /* hexcoder: Realize a counter that skips zero during overflow.
-           * Once this counter reaches its maximum value, it next increments to
-           * 1
-           *
-           * Instead of
-           * Counter + 1 -> Counter
-           * we inject now this
-           * Counter + 1 -> {Counter, OverflowFlag}
-           * Counter + OverflowFlag -> Counter
-           */
-          auto cf = IRB.CreateICmpEQ(Incr, Zero);
-          auto carry = IRB.CreateZExt(cf, Int8Ty);
-          Incr = IRB.CreateAdd(Incr, carry);
-
-        }
-
-        IRB.CreateStore(Incr, MapPtrIdx)
-            ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
-        if (caller_str && has_calls) {
-
-          // in CALLER mode we have to restore the original context for the
-          // caller - she might be calling other functions which need the
-          // correct CALLER
-          Instruction *Inst = BB.getTerminator();
-          if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
-
-            IRBuilder<> Post_IRB(Inst);
-            StoreInst * RestoreCtx =
-                Post_IRB.CreateStore(PrevCaller, AFLContext);
-            RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
-                                    MDNode::get(C, None));
-
-          }
-
-        }
-
-        total_instr++;
-
-      }
-
-    }
-
-    if (!be_quiet) {
-
-      char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
-               getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
-               getenv("AFL_USE_ASAN") ? ", ASAN" : "",
-               getenv("AFL_USE_MSAN") ? ", MSAN" : "",
-               getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
-               getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
-
-      OKF("Instrumented %d locations (%llu, %llu) (%s mode)\n", total_instr,
-          total_rs, total_hs, modeline);
-
-    }
-
-    return false;
-
-  }
-
-};  // end of struct InsTrim
-
-}  // end of anonymous namespace
-
-char InsTrim::ID = 0;
-
-static void registerAFLPass(const PassManagerBuilder &,
-                            legacy::PassManagerBase &PM) {
-
-  PM.add(new InsTrim());
-
-}
-
-static RegisterStandardPasses RegisterAFLPass(
-    PassManagerBuilder::EP_OptimizerLast, registerAFLPass);
-
-static RegisterStandardPasses RegisterAFLPass0(
-    PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);
-
diff --git a/instrumentation/MarkNodes.cc b/instrumentation/MarkNodes.cc
deleted file mode 100644
index b77466d9..00000000
--- a/instrumentation/MarkNodes.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-#include <algorithm>
-#include <map>
-#include <queue>
-#include <set>
-#include <vector>
-
-#include "llvm/Config/llvm-config.h"
-#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
-typedef long double max_align_t;
-#endif
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/BasicBlock.h"
-#if LLVM_VERSION_MAJOR > 3 || \
-    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
-  #include "llvm/IR/CFG.h"
-#else
-  #include "llvm/Support/CFG.h"
-#endif
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-DenseMap<BasicBlock *, uint32_t>    LMap;
-std::vector<BasicBlock *>           Blocks;
-std::set<uint32_t>                  Marked, Markabove;
-std::vector<std::vector<uint32_t> > Succs, Preds;
-
-void reset() {
-
-  LMap.clear();
-  Blocks.clear();
-  Marked.clear();
-  Markabove.clear();
-
-}
-
-uint32_t start_point;
-
-void labelEachBlock(Function *F) {
-
-  // Fake single endpoint;
-  LMap[NULL] = Blocks.size();
-  Blocks.push_back(NULL);
-
-  // Assign the unique LabelID to each block;
-  for (auto I = F->begin(), E = F->end(); I != E; ++I) {
-
-    BasicBlock *BB = &*I;
-    LMap[BB] = Blocks.size();
-    Blocks.push_back(BB);
-
-  }
-
-  start_point = LMap[&F->getEntryBlock()];
-
-}
-
-void buildCFG(Function *F) {
-
-  Succs.resize(Blocks.size());
-  Preds.resize(Blocks.size());
-  for (size_t i = 0; i < Succs.size(); i++) {
-
-    Succs[i].clear();
-    Preds[i].clear();
-
-  }
-
-  for (auto S = F->begin(), E = F->end(); S != E; ++S) {
-
-    BasicBlock *BB = &*S;
-    uint32_t    MyID = LMap[BB];
-
-    for (auto I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
-
-      Succs[MyID].push_back(LMap[*I]);
-
-    }
-
-  }
-
-}
-
-std::vector<std::vector<uint32_t> > tSuccs;
-std::vector<bool>                   tag, indfs;
-
-void DFStree(size_t now_id) {
-
-  if (tag[now_id]) return;
-  tag[now_id] = true;
-  indfs[now_id] = true;
-  for (auto succ : tSuccs[now_id]) {
-
-    if (tag[succ] and indfs[succ]) {
-
-      Marked.insert(succ);
-      Markabove.insert(succ);
-      continue;
-
-    }
-
-    Succs[now_id].push_back(succ);
-    Preds[succ].push_back(now_id);
-    DFStree(succ);
-
-  }
-
-  indfs[now_id] = false;
-
-}
-
-void turnCFGintoDAG() {
-
-  tSuccs = Succs;
-  tag.resize(Blocks.size());
-  indfs.resize(Blocks.size());
-  for (size_t i = 0; i < Blocks.size(); ++i) {
-
-    Succs[i].clear();
-    tag[i] = false;
-    indfs[i] = false;
-
-  }
-
-  DFStree(start_point);
-  for (size_t i = 0; i < Blocks.size(); ++i)
-    if (Succs[i].empty()) {
-
-      Succs[i].push_back(0);
-      Preds[0].push_back(i);
-
-    }
-
-}
-
-uint32_t timeStamp;
-namespace DominatorTree {
-
-std::vector<std::vector<uint32_t> > cov;
-std::vector<uint32_t>               dfn, nfd, par, sdom, idom, mom, mn;
-
-bool Compare(uint32_t u, uint32_t v) {
-
-  return dfn[u] < dfn[v];
-
-}
-
-uint32_t eval(uint32_t u) {
-
-  if (mom[u] == u) return u;
-  uint32_t res = eval(mom[u]);
-  if (Compare(sdom[mn[mom[u]]], sdom[mn[u]])) { mn[u] = mn[mom[u]]; }
-  return mom[u] = res;
-
-}
-
-void DFS(uint32_t now) {
-
-  timeStamp += 1;
-  dfn[now] = timeStamp;
-  nfd[timeStamp - 1] = now;
-  for (auto succ : Succs[now]) {
-
-    if (dfn[succ] == 0) {
-
-      par[succ] = now;
-      DFS(succ);
-
-    }
-
-  }
-
-}
-
-void DominatorTree() {
-
-  if (Blocks.empty()) return;
-  uint32_t s = start_point;
-
-  // Initialization
-  mn.resize(Blocks.size());
-  cov.resize(Blocks.size());
-  dfn.resize(Blocks.size());
-  nfd.resize(Blocks.size());
-  par.resize(Blocks.size());
-  mom.resize(Blocks.size());
-  sdom.resize(Blocks.size());
-  idom.resize(Blocks.size());
-
-  for (uint32_t i = 0; i < Blocks.size(); i++) {
-
-    dfn[i] = 0;
-    nfd[i] = Blocks.size();
-    cov[i].clear();
-    idom[i] = mom[i] = mn[i] = sdom[i] = i;
-
-  }
-
-  timeStamp = 0;
-  DFS(s);
-
-  for (uint32_t i = Blocks.size() - 1; i >= 1u; i--) {
-
-    uint32_t now = nfd[i];
-    if (now == Blocks.size()) { continue; }
-    for (uint32_t pre : Preds[now]) {
-
-      if (dfn[pre]) {
-
-        eval(pre);
-        if (Compare(sdom[mn[pre]], sdom[now])) { sdom[now] = sdom[mn[pre]]; }
-
-      }
-
-    }
-
-    cov[sdom[now]].push_back(now);
-    mom[now] = par[now];
-    for (uint32_t x : cov[par[now]]) {
-
-      eval(x);
-      if (Compare(sdom[mn[x]], par[now])) {
-
-        idom[x] = mn[x];
-
-      } else {
-
-        idom[x] = par[now];
-
-      }
-
-    }
-
-  }
-
-  for (uint32_t i = 1; i < Blocks.size(); i += 1) {
-
-    uint32_t now = nfd[i];
-    if (now == Blocks.size()) { continue; }
-    if (idom[now] != sdom[now]) idom[now] = idom[idom[now]];
-
-  }
-
-}
-
-}  // namespace DominatorTree
-
-std::vector<uint32_t>               Visited, InStack;
-std::vector<uint32_t>               TopoOrder, InDeg;
-std::vector<std::vector<uint32_t> > t_Succ, t_Pred;
-
-void Go(uint32_t now, uint32_t tt) {
-
-  if (now == tt) return;
-  Visited[now] = InStack[now] = timeStamp;
-
-  for (uint32_t nxt : Succs[now]) {
-
-    if (Visited[nxt] == timeStamp and InStack[nxt] == timeStamp) {
-
-      Marked.insert(nxt);
-
-    }
-
-    t_Succ[now].push_back(nxt);
-    t_Pred[nxt].push_back(now);
-    InDeg[nxt] += 1;
-    if (Visited[nxt] == timeStamp) { continue; }
-    Go(nxt, tt);
-
-  }
-
-  InStack[now] = 0;
-
-}
-
-void TopologicalSort(uint32_t ss, uint32_t tt) {
-
-  timeStamp += 1;
-
-  Go(ss, tt);
-
-  TopoOrder.clear();
-  std::queue<uint32_t> wait;
-  wait.push(ss);
-  while (not wait.empty()) {
-
-    uint32_t now = wait.front();
-    wait.pop();
-    TopoOrder.push_back(now);
-    for (uint32_t nxt : t_Succ[now]) {
-
-      InDeg[nxt] -= 1;
-      if (InDeg[nxt] == 0u) { wait.push(nxt); }
-
-    }
-
-  }
-
-}
-
-std::vector<std::set<uint32_t> > NextMarked;
-bool                             Indistinguish(uint32_t node1, uint32_t node2) {
-
-  if (NextMarked[node1].size() > NextMarked[node2].size()) {
-
-    uint32_t _swap = node1;
-    node1 = node2;
-    node2 = _swap;
-
-  }
-
-  for (uint32_t x : NextMarked[node1]) {
-
-    if (NextMarked[node2].find(x) != NextMarked[node2].end()) { return true; }
-
-  }
-
-  return false;
-
-}
-
-void MakeUniq(uint32_t now) {
-
-  if (Marked.find(now) == Marked.end()) {
-
-    for (uint32_t pred1 : t_Pred[now]) {
-
-      bool StopFlag = false;
-      for (uint32_t pred2 : t_Pred[now]) {
-
-        if (pred1 == pred2) continue;
-        if (Indistinguish(pred1, pred2)) {
-
-          Marked.insert(now);
-          StopFlag = true;
-          break;
-
-        }
-
-      }
-
-      if (StopFlag) { break; }
-
-    }
-
-  }
-
-  if (Marked.find(now) != Marked.end()) {
-
-    NextMarked[now].insert(now);
-
-  } else {
-
-    for (uint32_t pred : t_Pred[now]) {
-
-      for (uint32_t x : NextMarked[pred]) {
-
-        NextMarked[now].insert(x);
-
-      }
-
-    }
-
-  }
-
-}
-
-bool MarkSubGraph(uint32_t ss, uint32_t tt) {
-
-  TopologicalSort(ss, tt);
-  if (TopoOrder.empty()) return false;
-
-  for (uint32_t i : TopoOrder) {
-
-    NextMarked[i].clear();
-
-  }
-
-  NextMarked[TopoOrder[0]].insert(TopoOrder[0]);
-  for (uint32_t i = 1; i < TopoOrder.size(); i += 1) {
-
-    MakeUniq(TopoOrder[i]);
-
-  }
-
-  // Check if there is an empty path.
-  if (NextMarked[tt].count(TopoOrder[0]) > 0) return true;
-  return false;
-
-}
-
-void MarkVertice() {
-
-  uint32_t s = start_point;
-
-  InDeg.resize(Blocks.size());
-  Visited.resize(Blocks.size());
-  InStack.resize(Blocks.size());
-  t_Succ.resize(Blocks.size());
-  t_Pred.resize(Blocks.size());
-  NextMarked.resize(Blocks.size());
-
-  for (uint32_t i = 0; i < Blocks.size(); i += 1) {
-
-    Visited[i] = InStack[i] = InDeg[i] = 0;
-    t_Succ[i].clear();
-    t_Pred[i].clear();
-
-  }
-
-  timeStamp = 0;
-  uint32_t t = 0;
-  bool     emptyPathExists = true;
-
-  while (s != t) {
-
-    emptyPathExists &= MarkSubGraph(DominatorTree::idom[t], t);
-    t = DominatorTree::idom[t];
-
-  }
-
-  if (emptyPathExists) {
-
-    // Mark all exit blocks to catch the empty path.
-    Marked.insert(t_Pred[0].begin(), t_Pred[0].end());
-
-  }
-
-}
-
-// return {marked nodes}
-std::pair<std::vector<BasicBlock *>, std::vector<BasicBlock *> > markNodes(
-    Function *F) {
-
-  assert(F->size() > 0 && "Function can not be empty");
-
-  reset();
-  labelEachBlock(F);
-  buildCFG(F);
-  turnCFGintoDAG();
-  DominatorTree::DominatorTree();
-  MarkVertice();
-
-  std::vector<BasicBlock *> Result, ResultAbove;
-  for (uint32_t x : Markabove) {
-
-    auto it = Marked.find(x);
-    if (it != Marked.end()) Marked.erase(it);
-    if (x) ResultAbove.push_back(Blocks[x]);
-
-  }
-
-  for (uint32_t x : Marked) {
-
-    if (x == 0) {
-
-      continue;
-
-    } else {
-
-      Result.push_back(Blocks[x]);
-
-    }
-
-  }
-
-  return {Result, ResultAbove};
-
-}
-
diff --git a/instrumentation/MarkNodes.h b/instrumentation/MarkNodes.h
deleted file mode 100644
index 8ddc978d..00000000
--- a/instrumentation/MarkNodes.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __MARK_NODES__
-#define __MARK_NODES__
-
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/Function.h"
-#include <vector>
-
-std::pair<std::vector<llvm::BasicBlock *>, std::vector<llvm::BasicBlock *>>
-markNodes(llvm::Function *F);
-
-#endif
-
diff --git a/instrumentation/README.instrim.md b/instrumentation/README.instrim.md
deleted file mode 100644
index 99f6477a..00000000
--- a/instrumentation/README.instrim.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# InsTrim
-
-InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing
-
-## Introduction
-
-InsTrim is the work of Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao and Shih-Kun Huang.
-
-It uses a CFG (call flow graph) and markers to instrument just what
-is necessary in the binary (ie less than llvm_mode). As a result the binary is
-about 10-15% faster compared to normal llvm_mode however with some coverage loss.
-It requires at least llvm version 3.8.0 to build.
-If you have LLVM 7+ we recommend PCGUARD instead.
-
-## Usage
-
-Set the environment variable `AFL_LLVM_INSTRUMENT=CFG` or `AFL_LLVM_INSTRIM=1`
-during compilation of the target.
-
-There is also special mode which instruments loops in a way so that
-afl-fuzz can see which loop path has been selected but not being able to
-see how often the loop has been rerun.
-This again is a tradeoff for speed for less path information.
-To enable this mode set `AFL_LLVM_INSTRIM_LOOPHEAD=1`.
-
-## Background
-
-The paper from Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao and Shih-Kun Huang:
-[InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing]
-(https://www.ndss-symposium.org/wp-content/uploads/2018/07/bar2018_14_Hsu_paper.pdf)
diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md
index 2705ce0d..0937a328 100644
--- a/instrumentation/README.llvm.md
+++ b/instrumentation/README.llvm.md
@@ -6,7 +6,7 @@
 
 ## 1) Introduction
 
-! llvm_mode works with llvm versions 3.4 up to 12 !
+! llvm_mode works with llvm versions 6.0 up to 12 !
 
 The code in this directory allows you to instrument programs for AFL using
 true compiler-level instrumentation, instead of the more crude
@@ -101,8 +101,7 @@ instrumentation by either setting `AFL_CC_COMPILER=LLVM` or pass the parameter
 The tool honors roughly the same environmental variables as afl-gcc (see
 [docs/env_variables.md](../docs/env_variables.md)). This includes AFL_USE_ASAN,
 AFL_HARDEN, and AFL_DONT_OPTIMIZE. However AFL_INST_RATIO is not honored
-as it does not serve a good purpose with the more effective PCGUARD, LTO and
- instrim CFG analysis.
+as it does not serve a good purpose with the more effective PCGUARD analysis.
 
 ## 3) Options
 
@@ -116,26 +115,20 @@ For splitting memcmp, strncmp, etc. please see [README.laf-intel.md](README.laf-
 
 Then there are different ways of instrumenting the target:
 
-1. There is an optimized instrumentation strategy that uses CFGs and
-markers to just instrument what is needed. This increases speed by 10-15%
-without any disadvantages
-If you want to use this, set AFL_LLVM_INSTRUMENT=CFG or AFL_LLVM_INSTRIM=1
-See [README.instrim.md](README.instrim.md)
-
-2. An even better instrumentation strategy uses LTO and link time
+1. An better instrumentation strategy uses LTO and link time
 instrumentation. Note that not all targets can compile in this mode, however
 if it works it is the best option you can use.
 Simply use afl-clang-lto/afl-clang-lto++ to use this option.
 See [README.lto.md](README.lto.md)
 
-3. Alternativly you can choose a completely different coverage method:
+2. Alternativly you can choose a completely different coverage method:
 
-3a. N-GRAM coverage - which combines the previous visited edges with the
+2a. N-GRAM coverage - which combines the previous visited edges with the
 current one. This explodes the map but on the other hand has proven to be
 effective for fuzzing.
 See [README.ngram.md](README.ngram.md)
 
-3b. Context sensitive coverage - which combines the visited edges with an
+2b. Context sensitive coverage - which combines the visited edges with an
 individual caller ID (the function that called the current one)
 [README.ctx.md](README.ctx.md)
 
diff --git a/instrumentation/README.snapshot.md b/instrumentation/README.snapshot.md
index c40a956a..c794c2fd 100644
--- a/instrumentation/README.snapshot.md
+++ b/instrumentation/README.snapshot.md
@@ -1,5 +1,7 @@
 # AFL++ snapshot feature
 
+**NOTE:** the snapshot lkm is currently not supported and needs a maintainer :-)
+
 Snapshotting is a feature that makes a snapshot from a process and then
 restores its state, which is faster then forking it again.
 
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index f241447a..552bbea8 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -34,8 +34,10 @@
 #include <errno.h>
 
 #include <sys/mman.h>
-#include <sys/syscall.h>
 #ifndef __HAIKU__
+  #include <sys/syscall.h>
+#endif
+#ifndef USEMMAP
   #include <sys/shm.h>
 #endif
 #include <sys/wait.h>
@@ -76,6 +78,10 @@
   #define MAP_INITIAL_SIZE MAP_SIZE
 #endif
 
+#if defined(__HAIKU__)
+  extern ssize_t _kern_write(int fd, off_t pos, const void *buffer,	size_t bufferSize);
+#endif // HAIKU
+
 u8   __afl_area_initial[MAP_INITIAL_SIZE];
 u8 * __afl_area_ptr_dummy = __afl_area_initial;
 u8 * __afl_area_ptr = __afl_area_initial;
@@ -99,12 +105,10 @@ int __afl_selective_coverage_temp = 1;
 PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
 PREV_LOC_T __afl_prev_caller[CTX_MAX_K];
 u32        __afl_prev_ctx;
-u32        __afl_cmp_counter;
 #else
 __thread PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
 __thread PREV_LOC_T __afl_prev_caller[CTX_MAX_K];
 __thread u32        __afl_prev_ctx;
-__thread u32        __afl_cmp_counter;
 #endif
 
 int __afl_sharedmem_fuzzing __attribute__((weak));
@@ -1140,6 +1144,18 @@ void __afl_manual_init(void) {
 
 __attribute__((constructor())) void __afl_auto_init(void) {
 
+#ifdef __ANDROID__
+  // Disable handlers in linker/debuggerd, check include/debuggerd/handler.h
+  signal(SIGABRT, SIG_DFL);
+  signal(SIGBUS, SIG_DFL);
+  signal(SIGFPE, SIG_DFL);
+  signal(SIGILL, SIG_DFL);
+  signal(SIGSEGV, SIG_DFL);
+  signal(SIGSTKFLT, SIG_DFL);
+  signal(SIGSYS, SIG_DFL);
+  signal(SIGTRAP, SIG_DFL);
+#endif
+
   if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
 
   if (getenv(DEFER_ENV_VAR)) return;
@@ -1738,7 +1754,11 @@ static int area_is_valid(void *ptr, size_t len) {
 
   if (unlikely(!ptr || __asan_region_is_poisoned(ptr, len))) { return 0; }
 
-  long r = syscall(SYS_write, __afl_dummy_fd[1], ptr, len);
+  #ifndef __HAIKU__
+    long r = syscall(SYS_write, __afl_dummy_fd[1], ptr, len);
+  #else
+    long r = _kern_write(__afl_dummy_fd[1], -1, ptr, len);
+  #endif // HAIKU
 
   if (r <= 0 || r > len) return 0;
 
diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc
index 74943fb2..24498f3e 100644
--- a/instrumentation/afl-llvm-common.cc
+++ b/instrumentation/afl-llvm-common.cc
@@ -104,7 +104,8 @@ bool isIgnoreFunction(const llvm::Function *F) {
 
   for (auto const &ignoreListFunc : ignoreSubstringList) {
 
-    if (F->getName().contains(ignoreListFunc)) { return true; }
+    // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
+    if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
 
   }
 
diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc
index 50306224..f6cdbe9e 100644
--- a/instrumentation/afl-llvm-lto-instrumentation.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc
@@ -92,7 +92,7 @@ class AFLLTOPass : public ModulePass {
   uint32_t afl_global_id = 1, autodictionary = 1;
   uint32_t function_minimum_size = 1;
   uint32_t inst_blocks = 0, inst_funcs = 0, total_instr = 0;
-  uint64_t map_addr = 0x10000;
+  unsigned long long int map_addr = 0x10000;
   char *   skip_nozero = NULL;
 
 };
@@ -176,7 +176,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   }
 
-  if (debug) { fprintf(stderr, "map address is 0x%lx\n", map_addr); }
+  if (debug) { fprintf(stderr, "map address is 0x%llx\n", map_addr); }
 
   /* Get/set the globals for the SHM region. */
 
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 8d95c359..0fb33ae2 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-ddc4a9748d
+d73b0336b4
diff --git a/qemu_mode/README.md b/qemu_mode/README.md
index a14cbe64..4aa2133e 100644
--- a/qemu_mode/README.md
+++ b/qemu_mode/README.md
@@ -141,7 +141,7 @@ To enable it you must pass on the command line of afl-fuzz:
 
 ## 9) Wine mode
 
-AFL++ QEMU can use Wine to fuzz WIn32 PE binaries. Use the -W flag of afl-fuzz.
+AFL++ QEMU can use Wine to fuzz Win32 PE binaries. Use the -W flag of afl-fuzz.
 
 Note that some binaries require user interaction with the GUI and must be patched.
 
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index 38085389..6436d43a 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -360,6 +360,8 @@ if ! command -v "$CROSS" > /dev/null ; then
     make -C unsigaction && echo "[+] unsigaction ready"
     echo "[+] Building libqasan ..."
     make -C libqasan && echo "[+] unsigaction ready"
+    echo "[+] Building qemu libfuzzer helpers ..."
+    make -C ../utils/aflpp_driver
   else
     echo "[!] Cross compiler $CROSS could not be found, cannot compile libcompcov libqasan and unsigaction"
   fi
diff --git a/qemu_mode/libcompcov/compcovtest.cc b/qemu_mode/libcompcov/compcovtest.cc
index d70bba91..3c975e15 100644
--- a/qemu_mode/libcompcov/compcovtest.cc
+++ b/qemu_mode/libcompcov/compcovtest.cc
@@ -1,67 +1,98 @@
-/////////////////////////////////////////////////////////////////////////

-//

-// Author: Mateusz Jurczyk (mjurczyk@google.com)

-//

-// Copyright 2019-2020 Google LLC

-//

-// Licensed under the Apache License, Version 2.0 (the "License");

-// you may not use this file except in compliance with the License.

-// You may obtain a copy of the License at

-//

-// https://www.apache.org/licenses/LICENSE-2.0

-//

-// Unless required by applicable law or agreed to in writing, software

-// distributed under the License is distributed on an "AS IS" BASIS,

-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-// See the License for the specific language governing permissions and

-// limitations under the License.

-//

-

-// solution: echo -ne 'The quick brown fox jumps over the lazy

-// dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest

-

-#include <cstdint>

-#include <cstdio>

-#include <cstdlib>

-#include <cstring>

-

-int main() {

-
-  char buffer[44] = {/* zero padding */};

-  fread(buffer, 1, sizeof(buffer) - 1, stdin);

-

-  if (memcmp(&buffer[0], "The quick brown fox ", 20) != 0 ||

-      strncmp(&buffer[20], "jumps over ", 11) != 0 ||

-      strcmp(&buffer[31], "the lazy dog") != 0) {

-
-    return 1;

-
-  }

-

-  uint64_t x = 0;

-  fread(&x, sizeof(x), 1, stdin);

-  if (x != 0xCAFEBABECAFEBABE) { return 2; }

-

-  uint32_t y = 0;

-  fread(&y, sizeof(y), 1, stdin);

-  if (y != 0xDEADC0DE) { return 3; }

-

-  uint16_t z = 0;

-  fread(&z, sizeof(z), 1, stdin);

-

-  switch (z) {

-
-    case 0xBEEF:

-      break;

-

-    default:

-      return 4;

-
-  }

-

-  printf("Puzzle solved, congrats!\n");

-  abort();

-  return 0;

-
-}

+/////////////////////////////////////////////////////////////////////////
+//
+// Author: Mateusz Jurczyk (mjurczyk@google.com)
+//
+// Copyright 2019-2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// solution: echo -ne 'The quick brown fox jumps over the lazy
+// dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest
+
+#include "../../include/config.h"
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+int main(int argc, char **argv) {
+
+  char buffer[44] = {/* zero padding */};
+
+  FILE *file = stdin;
+
+  if (argc > 1) {
+
+    if ((file = fopen(argv[1], "r")) == NULL) {
+
+      perror(argv[1]);
+      exit(-1);
+
+    }
+
+  }
+
+  fread(buffer, 1, sizeof(buffer) - 1, file);
+
+  if (memcmp(&buffer[0], "The quick brown fox ", 20) != 0 ||
+      strncmp(&buffer[20], "jumps over ", 11) != 0 ||
+      strcmp(&buffer[31], "the lazy dog") != 0) {
+
+    if (argc > 1) { fclose(file); }
+    return 1;
+
+  }
+
+  uint64_t x = 0;
+  fread(&x, sizeof(x), 1, file);
+  if (x != 0xCAFEBABECAFEBABE) {
+
+    if (argc > 1) { fclose(file); }
+    return 2;
+
+  }
+
+  uint32_t y = 0;
+  fread(&y, sizeof(y), 1, file);
+  if (y != 0xDEADC0DE) {
+
+    if (argc > 1) { fclose(file); }
+    return 3;
+
+  }
+
+  uint16_t z = 0;
+  fread(&z, sizeof(z), 1, file);
+
+  switch (z) {
+
+    case 0xBEEF:
+      break;
+
+    default:
+      if (argc > 1) { fclose(file); }
+      return 4;
+
+  }
+
+  printf("Puzzle solved, congrats!\n");
+  abort();
+
+  if (argc > 1) { fclose(file); }
+
+  return 0;
+
+}
 
diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl
-Subproject 0fb212daab492411b3e323bc18a3074c1aecfd3
+Subproject d73b0336b451fd034e5f469089fb7ee96c80adf
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index e106cd31..aabdbf1a 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -83,6 +83,7 @@ static volatile u8 stop_soon,          /* Ctrl-C pressed?                   */
     child_timed_out;                   /* Child timed out?                  */
 
 static u8 *target_path;
+static u8  frida_mode;
 static u8  qemu_mode;
 static u32 map_size = MAP_SIZE;
 
@@ -717,9 +718,11 @@ static void handle_stop_sig(int sig) {
 
 /* Do basic preparations - persistent fds, filenames, etc. */
 
-static void set_up_environment(void) {
+static void set_up_environment(char **argv) {
 
-  u8 *x;
+  u8 *  x;
+  char *afl_preload;
+  char *frida_afl_preload = NULL;
 
   dev_null_fd = open("/dev/null", O_RDWR);
   if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@@ -781,6 +784,18 @@ static void set_up_environment(void) {
 
   }
 
+  x = get_afl_env("LSAN_OPTIONS");
+
+  if (x) {
+
+    if (!strstr(x, "symbolize=0")) {
+
+      FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
+
+    }
+
+  }
+
   setenv("ASAN_OPTIONS",
          "abort_on_error=1:"
          "detect_leaks=0:"
@@ -818,12 +833,38 @@ static void set_up_environment(void) {
                          "handle_sigfpe=0:"
                          "handle_sigill=0", 0);
 
+  setenv("LSAN_OPTIONS",
+         "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+         "fast_unwind_on_malloc=0:"
+         "symbolize=0:"
+         "print_suppressions=0",
+         0);
+
   if (get_afl_env("AFL_PRELOAD")) {
 
     if (qemu_mode) {
 
       /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
 
+    } else if (frida_mode) {
+
+      afl_preload = getenv("AFL_PRELOAD");
+      u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+      if (afl_preload) {
+
+        frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+      } else {
+
+        frida_afl_preload = alloc_printf("%s", frida_binary);
+
+      }
+
+      ck_free(frida_binary);
+
+      setenv("LD_PRELOAD", frida_afl_preload, 1);
+      setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
     } else {
 
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -831,8 +872,17 @@ static void set_up_environment(void) {
 
     }
 
+  } else if (frida_mode) {
+
+    u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+    setenv("LD_PRELOAD", frida_binary, 1);
+    setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+    ck_free(frida_binary);
+
   }
 
+  if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
 }
 
 /* Setup signal handlers, duh. */
@@ -872,6 +922,7 @@ static void usage(u8 *argv0) {
       "  -f file       - input file read by the tested program (stdin)\n"
       "  -t msec       - timeout for each run (%u ms)\n"
       "  -m megs       - memory limit for child process (%u MB)\n"
+      "  -O            - use binary-only instrumentation (FRIDA mode)\n"
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
@@ -914,7 +965,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n");
 
-  while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) {
 
     switch (opt) {
 
@@ -1008,6 +1059,14 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
+      case 'O':                                               /* FRIDA mode */
+
+        if (frida_mode) { FATAL("Multiple -O options not supported"); }
+
+        frida_mode = 1;
+
+        break;
+
       case 'Q':
 
         if (qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -1062,7 +1121,7 @@ int main(int argc, char **argv_orig, char **envp) {
   atexit(at_exit_handler);
   setup_signal_handlers();
 
-  set_up_environment();
+  set_up_environment(argv);
 
   target_path = find_binary(argv[optind]);
   detect_file_args(argv + optind, prog_in, &use_stdin);
diff --git a/src/afl-as.c b/src/afl-as.c
index aebd0ac8..7119d630 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -517,11 +517,12 @@ static void add_instrumentation(void) {
     } else {
 
       char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s",
+      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
                getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
                getenv("AFL_USE_ASAN") ? ", ASAN" : "",
                getenv("AFL_USE_MSAN") ? ", MSAN" : "",
-               getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
+               getenv("AFL_USE_UBSAN") ? ", UBSAN" : "",
+               getenv("AFL_USE_LSAN") ? ", LSAN" : "");
 
       OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).", ins_lines,
           use_64bit ? "64" : "32", modeline, inst_ratio);
@@ -585,7 +586,7 @@ int main(int argc, char **argv) {
         "AFL_QUIET: suppress verbose output\n"
         "AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n"
         "AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n"
-        "AFL_HARDEN, AFL_USE_ASAN, AFL_USE_MSAN, AFL_USE_UBSAN:\n"
+        "AFL_HARDEN, AFL_USE_ASAN, AFL_USE_MSAN, AFL_USE_UBSAN, AFL_USE_LSAN:\n"
         "  used in the instrumentation summary message\n",
         argv[0]);
 
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 80fc0742..1f89bac5 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -66,7 +66,6 @@ enum {
   INSTRUMENT_CLASSIC = 1,
   INSTRUMENT_AFL = 1,
   INSTRUMENT_PCGUARD = 2,
-  INSTRUMENT_INSTRIM = 3,
   INSTRUMENT_CFG = 3,
   INSTRUMENT_LTO = 4,
   INSTRUMENT_LLVMNATIVE = 5,
@@ -431,9 +430,6 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
 
-    if (lto_mode && plusplus_mode)
-      cc_params[cc_par_cnt++] = "-lc++";  // needed by fuzzbench, early
-
     if (lto_mode && have_instr_env) {
 
       cc_params[cc_par_cnt++] = "-Xclang";
@@ -588,9 +584,9 @@ 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)
-  #ifdef __ANDROID__
+  #if defined __ANDROID__ || ANDROID
         cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
-        instrument_mode != INSTRUMENT_LLVMNATIVE;
+        instrument_mode = INSTRUMENT_LLVMNATIVE;
   #else
         if (have_instr_list) {
 
@@ -639,12 +635,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
         cc_params[cc_par_cnt++] = "-Xclang";
         cc_params[cc_par_cnt++] = "-load";
         cc_params[cc_par_cnt++] = "-Xclang";
-        if (instrument_mode == INSTRUMENT_CFG)
-          cc_params[cc_par_cnt++] =
-              alloc_printf("%s/libLLVMInsTrim.so", obj_path);
-        else
-          cc_params[cc_par_cnt++] =
-              alloc_printf("%s/afl-llvm-pass.so", obj_path);
+        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
 
       }
 
@@ -825,6 +816,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
   }
 
+  if (getenv("AFL_USE_LSAN")) {
+
+    cc_params[cc_par_cnt++] = "-fsanitize=leak";
+    cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h";
+    cc_params[cc_par_cnt++] = "-D__AFL_LEAK_CHECK()=__lsan_do_leak_check()";
+
+  }
+
   if (getenv("AFL_USE_CFISAN")) {
 
     if (!lto_mode) {
@@ -1252,8 +1251,9 @@ int main(int argc, char **argv, char **envp) {
 
                  strcasecmp(ptr, "CFG") == 0) {
 
-        compiler_mode = LLVM;
-        instrument_mode = INSTRUMENT_CFG;
+        FATAL(
+            "InsTrim instrumentation was removed. Use a modern LLVM and "
+            "PCGUARD (default in afl-cc).\n");
 
       } else if (strcasecmp(ptr, "AFL") == 0 ||
 
@@ -1319,10 +1319,9 @@ int main(int argc, char **argv, char **envp) {
   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 cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
+    FATAL(
+        "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD "
+        "(default in afl-cc).\n");
 
   }
 
@@ -1409,17 +1408,9 @@ int main(int argc, char **argv, char **envp) {
       if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
           strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
 
-        if (instrument_mode == INSTRUMENT_LTO) {
-
-          instrument_mode = INSTRUMENT_CFG;
-          lto_mode = 1;
-
-        } else if (!instrument_mode || instrument_mode == INSTRUMENT_CFG)
-
-          instrument_mode = INSTRUMENT_CFG;
-        else
-          FATAL("main instrumentation mode already set with %s",
-                instrument_mode_string[instrument_mode]);
+        FATAL(
+            "InsTrim instrumentation was removed. Use a modern LLVM and "
+            "PCGUARD (default in afl-cc).\n");
 
       }
 
@@ -1428,7 +1419,7 @@ int main(int argc, char **argv, char **envp) {
         lto_mode = 1;
         if (!instrument_mode || instrument_mode == INSTRUMENT_LTO)
           instrument_mode = INSTRUMENT_LTO;
-        else if (instrument_mode != INSTRUMENT_CFG)
+        else
           FATAL("main instrumentation mode already set with %s",
                 instrument_mode_string[instrument_mode]);
 
@@ -1456,9 +1447,11 @@ int main(int argc, char **argv, char **envp) {
 
       }
 
-      if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0) {
+      if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 ||
+          strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 ||
+          strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) {
 
-        u8 *ptr3 = ptr2 + strlen("ctx-");
+        u8 *ptr3 = ptr2;
         while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9'))
           ptr3++;
 
@@ -1494,7 +1487,7 @@ int main(int argc, char **argv, char **envp) {
 
       }
 
-      if (strncasecmp(ptr2, "ctx", strlen("ctx")) == 0) {
+      if (strcasecmp(ptr2, "ctx") == 0) {
 
         instrument_opt_mode |= INSTRUMENT_OPT_CTX;
         setenv("AFL_LLVM_CTX", "1", 1);
@@ -1642,11 +1635,6 @@ int main(int argc, char **argv, char **envp) {
         "        - CALLER\n"
         "        - CTX\n"
         "        - NGRAM-{2-16}\n"
-        "      INSTRIM                           no  yes     module yes yes "
-        "   yes\n"
-        "        - NORMAL\n"
-        "        - CALLER\n"
-        "        - NGRAM-{2-16}\n"
         "  [GCC_PLUGIN] gcc plugin: %s%s\n"
         "      CLASSIC              DEFAULT      no  yes     no     no  no     "
         "yes\n"
@@ -1697,9 +1685,7 @@ int main(int argc, char **argv, char **envp) {
         "  CTX:     CLASSIC + full callee context "
         "(instrumentation/README.ctx.md)\n"
         "  NGRAM-x: CLASSIC + previous path "
-        "((instrumentation/README.ngram.md)\n"
-        "  INSTRIM: Dominator tree (for LLVM <= 6.0) "
-        "(instrumentation/README.instrim.md)\n\n");
+        "((instrumentation/README.ngram.md)\n\n");
 
 #undef NATIVE_MSG
 
@@ -1749,7 +1735,8 @@ int main(int argc, char **argv, char **envp) {
           "  AFL_USE_ASAN: activate address sanitizer\n"
           "  AFL_USE_CFISAN: activate control flow sanitizer\n"
           "  AFL_USE_MSAN: activate memory sanitizer\n"
-          "  AFL_USE_UBSAN: activate undefined behaviour sanitizer\n");
+          "  AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
+          "  AFL_USE_LSAN: activate leak-checker sanitizer\n");
 
       if (have_gcc_plugin)
         SAYF(
@@ -1791,19 +1778,16 @@ int main(int argc, char **argv, char **envp) {
             "  AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen "
             "mutator)\n"
             "  AFL_LLVM_INSTRUMENT: set instrumentation mode:\n"
-            "    CLASSIC, INSTRIM, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, "
-            "NGRAM-2 ..-16\n"
+            "    CLASSIC, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, NGRAM-2 "
+            "..-16\n"
             " You can also use the old environment variables instead:\n"
             "  AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n"
-            "  AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
-            "  AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed "
-            "(option to INSTRIM)\n"
             "  AFL_LLVM_CALLER: use single context sensitive coverage (for "
             "CLASSIC)\n"
             "  AFL_LLVM_CTX: use full context sensitive coverage (for "
             "CLASSIC)\n"
             "  AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for "
-            "CLASSIC & INSTRIM)\n");
+            "CLASSIC)\n");
 
 #ifdef AFL_CLANG_FLTO
       if (have_lto)
@@ -1951,11 +1935,7 @@ int main(int argc, char **argv, char **envp) {
         "(requires LLVM 11 or higher)");
 #endif
 
-  if (instrument_opt_mode && instrument_mode == INSTRUMENT_CFG &&
-      instrument_opt_mode & INSTRUMENT_OPT_CTX)
-    FATAL("CFG instrumentation mode supports NGRAM and CALLER, but not CTX.");
-  else if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
-    // we will drop CFG/INSTRIM in the future so do not advertise
+  if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
     FATAL(
         "CALLER, CTX and NGRAM instrumentation options can only be used with "
         "the LLVM CLASSIC instrumentation mode.");
@@ -2023,7 +2003,7 @@ int main(int argc, char **argv, char **envp) {
   if (!be_quiet && cmplog_mode)
     printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
 
-#ifndef __ANDROID__
+#if !defined(__ANDROID__) && !defined(ANDROID)
   ptr = find_object("afl-compiler-rt.o", argv[0]);
 
   if (!ptr) {
diff --git a/src/afl-common.c b/src/afl-common.c
index 37b4788c..0fb1462e 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -70,31 +70,26 @@ void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
 
       *use_stdin = false;
 
-      if (prog_in[0] != 0) {  // not afl-showmap special case
+      /* Be sure that we're always using fully-qualified paths. */
 
-        u8 *n_arg;
+      *aa_loc = 0;
 
-        /* Be sure that we're always using fully-qualified paths. */
+      /* Construct a replacement argv value. */
+      u8 *n_arg;
 
-        *aa_loc = 0;
+      if (prog_in[0] == '/') {
 
-        /* Construct a replacement argv value. */
+        n_arg = alloc_printf("%s%s%s", argv[i], prog_in, aa_loc + 2);
 
-        if (prog_in[0] == '/') {
-
-          n_arg = alloc_printf("%s%s%s", argv[i], prog_in, aa_loc + 2);
-
-        } else {
-
-          n_arg = alloc_printf("%s%s/%s%s", argv[i], cwd, prog_in, aa_loc + 2);
-
-        }
+      } else {
 
-        ck_free(argv[i]);
-        argv[i] = n_arg;
+        n_arg = alloc_printf("%s%s/%s%s", argv[i], cwd, prog_in, aa_loc + 2);
 
       }
 
+      ck_free(argv[i]);
+      argv[i] = n_arg;
+
     }
 
     i++;
@@ -287,12 +282,19 @@ u8 *find_binary(u8 *fname) {
 
 u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
 
-  u8 *afl_path = NULL, *target_path, *own_copy;
+  u8 *afl_path = NULL, *target_path, *own_copy, *tmp;
+  int perm = X_OK;
+
+  if ((tmp = strrchr(fname, '.'))) {
+
+    if (!strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; }
+
+  }
 
   if ((afl_path = getenv("AFL_PATH"))) {
 
     target_path = alloc_printf("%s/%s", afl_path, fname);
-    if (!access(target_path, X_OK)) {
+    if (!access(target_path, perm)) {
 
       return target_path;
 
@@ -316,7 +318,7 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
       target_path = alloc_printf("%s/%s", own_copy, fname);
       ck_free(own_copy);
 
-      if (!access(target_path, X_OK)) {
+      if (!access(target_path, perm)) {
 
         return target_path;
 
@@ -334,8 +336,17 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
 
   }
 
-  target_path = alloc_printf("%s/%s", BIN_PATH, fname);
-  if (!access(target_path, X_OK)) {
+  if (perm == X_OK) {
+
+    target_path = alloc_printf("%s/%s", BIN_PATH, fname);
+
+  } else {
+
+    target_path = alloc_printf("%s/%s", AFL_PATH, fname);
+
+  }
+
+  if (!access(target_path, perm)) {
 
     return target_path;
 
@@ -345,7 +356,15 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
 
   }
 
-  return find_binary(fname);
+  if (perm == X_OK) {
+
+    return find_binary(fname);
+
+  } else {
+
+    FATAL("Library '%s' not found", fname);
+
+  }
 
 }
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c2d552cd..727e7f8d 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -42,6 +42,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/resource.h>
@@ -126,7 +127,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->last_run_timed_out = 0;
 
   fsrv_to->init_child_func = from->init_child_func;
-  // Note: do not copy ->add_extra_func
+  // Note: do not copy ->add_extra_func or ->persistent_record*
 
   list_append(&fsrv_list, fsrv_to);
 
@@ -364,6 +365,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
   if (!be_quiet) { ACTF("Spinning up the fork server..."); }
 
+#ifdef AFL_PERSISTENT_RECORD
+  if (unlikely(fsrv->persistent_record)) {
+
+    fsrv->persistent_record_data =
+        (u8 **)ck_alloc(fsrv->persistent_record * sizeof(u8 *));
+    fsrv->persistent_record_len =
+        (u32 *)ck_alloc(fsrv->persistent_record * sizeof(u32));
+
+    if (!fsrv->persistent_record_data || !fsrv->persistent_record_len) {
+
+      FATAL("Unable to allocate memory for persistent replay.");
+
+    }
+
+  }
+
+#endif
+
   if (fsrv->use_fauxsrv) {
 
     /* TODO: Come up with some nice way to initialize this all */
@@ -483,7 +502,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); }
 
-    /* Set sane defaults for ASAN if nothing else specified. */
+    /* Set sane defaults for ASAN if nothing else is specified. */
 
     if (!getenv("ASAN_OPTIONS"))
       setenv("ASAN_OPTIONS",
@@ -500,7 +519,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
              "handle_sigill=0",
              1);
 
-    /* Set sane defaults for UBSAN if nothing else specified. */
+    /* Set sane defaults for UBSAN if nothing else is specified. */
 
     if (!getenv("UBSAN_OPTIONS"))
       setenv("UBSAN_OPTIONS",
@@ -538,6 +557,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
            "handle_sigill=0",
            1);
 
+    /* LSAN, too, does not support abort_on_error=1. */
+
+    if (!getenv("LSAN_OPTIONS"))
+      setenv("LSAN_OPTIONS",
+            "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+            "fast_unwind_on_malloc=0:"
+            "symbolize=0:"
+            "print_suppressions=0",
+            1);
+
     fsrv->init_child_func(fsrv, argv);
 
     /* Use a distinctive bitmap signature to tell the parent about execv()
@@ -792,7 +821,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
   if (fsrv->last_run_timed_out) {
 
-    FATAL("Timeout while initializing fork server (adjusting -t may help)");
+    FATAL(
+        "Timeout while initializing fork server (setting "
+        "AFL_FORKSRV_INIT_TMOUT may help)");
 
   }
 
@@ -1032,6 +1063,32 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
 
 void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
+#ifdef AFL_PERSISTENT_RECORD
+  if (unlikely(fsrv->persistent_record)) {
+
+    fsrv->persistent_record_len[fsrv->persistent_record_idx] = len;
+    fsrv->persistent_record_data[fsrv->persistent_record_idx] = afl_realloc(
+        (void **)&fsrv->persistent_record_data[fsrv->persistent_record_idx],
+        len);
+
+    if (unlikely(!fsrv->persistent_record_data[fsrv->persistent_record_idx])) {
+
+      FATAL("allocating replay memory failed.");
+
+    }
+
+    memcpy(fsrv->persistent_record_data[fsrv->persistent_record_idx], buf, len);
+
+    if (unlikely(++fsrv->persistent_record_idx >= fsrv->persistent_record)) {
+
+      fsrv->persistent_record_idx = 0;
+
+    }
+
+  }
+
+#endif
+
   if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) {
 
     if (unlikely(len > MAX_FILE)) len = MAX_FILE;
@@ -1146,6 +1203,26 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
 
   }
 
+#ifdef AFL_PERSISTENT_RECORD
+  // end of persistent loop?
+  if (unlikely(fsrv->persistent_record &&
+               fsrv->persistent_record_pid != fsrv->child_pid)) {
+
+    fsrv->persistent_record_pid = fsrv->child_pid;
+    u32 idx, val;
+    if (unlikely(!fsrv->persistent_record_idx))
+      idx = fsrv->persistent_record - 1;
+    else
+      idx = fsrv->persistent_record_idx - 1;
+    val = fsrv->persistent_record_len[idx];
+    memset((void *)fsrv->persistent_record_len, 0,
+           fsrv->persistent_record * sizeof(u32));
+    fsrv->persistent_record_len[idx] = val;
+
+  }
+
+#endif
+
   if (fsrv->child_pid <= 0) {
 
     if (*stop_soon_p) { return 0; }
@@ -1238,12 +1315,47 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
   if (unlikely(
           /* A normal crash/abort */
           (WIFSIGNALED(fsrv->child_status)) ||
-          /* special handling for msan */
-          (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
+          /* special handling for msan and lsan */
+          (fsrv->uses_asan &&
+           (WEXITSTATUS(fsrv->child_status) == MSAN_ERROR ||
+            WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) ||
           /* the custom crash_exitcode was returned by the target */
           (fsrv->uses_crash_exitcode &&
            WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
 
+#ifdef AFL_PERSISTENT_RECORD
+    if (unlikely(fsrv->persistent_record)) {
+
+      char fn[PATH_MAX];
+      u32  i, writecnt = 0;
+      for (i = 0; i < fsrv->persistent_record; ++i) {
+
+        u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record;
+        u8 *data = fsrv->persistent_record_data[entry];
+        u32 len = fsrv->persistent_record_len[entry];
+        if (likely(len && data)) {
+
+          snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u",
+                   fsrv->persistent_record_dir, fsrv->persistent_record_cnt,
+                   writecnt++);
+          int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+          if (fd >= 0) {
+
+            ck_write(fd, data, len, fn);
+            close(fd);
+
+          }
+
+        }
+
+      }
+
+      ++fsrv->persistent_record_cnt;
+
+    }
+
+#endif
+
     /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
     fsrv->last_kill_signal =
         WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 70a49a6b..b6bfbc29 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -881,7 +881,7 @@ void perform_dry_run(afl_state_t *afl) {
 
       case FSRV_RUN_TMOUT:
 
-        if (afl->timeout_given) {
+        if (afl->timeout_given && !afl->afl_env.afl_exit_on_seed_issues) {
 
           /* if we have a timeout but a timeout value was given then always
              skip. The '+' meaning has been changed! */
@@ -1036,6 +1036,12 @@ void perform_dry_run(afl_state_t *afl) {
 
         }
 
+        if (afl->afl_env.afl_exit_on_seed_issues) {
+
+          FATAL("As AFL_EXIT_ON_SEED_ISSUES is set, afl-fuzz exits.");
+
+        }
+
         /* Remove from fuzzing queue but keep for splicing */
 
         struct queue_entry *p = afl->queue;
@@ -2490,6 +2496,18 @@ void check_asan_opts(afl_state_t *afl) {
 
   }
 
+  x = get_afl_env("LSAN_OPTIONS");
+
+  if (x) {
+
+    if (!strstr(x, "symbolize=0")) {
+
+      FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
+
+    }
+
+  }
+
 }
 
 /* Handle stop signal (Ctrl-C, etc). */
@@ -2692,7 +2710,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
 #endif                                                       /* ^!__APPLE__ */
 
-  if (!afl->fsrv.qemu_mode && !afl->unicorn_mode &&
+  if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode &&
       !afl->non_instrumented_mode &&
       !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
 
@@ -2720,7 +2738,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if ((afl->fsrv.qemu_mode) &&
+  if ((afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
       memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
 
     SAYF("\n" cLRD "[-] " cRST
@@ -2735,7 +2753,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
   }
 
   if (memmem(f_data, f_len, "__asan_init", 11) ||
-      memmem(f_data, f_len, "__msan_init", 11)) {
+      memmem(f_data, f_len, "__msan_init", 11) ||
+      memmem(f_data, f_len, "__lsan_init", 11)) {
 
     afl->fsrv.uses_asan = 1;
 
@@ -2757,7 +2776,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
+  if (afl->fsrv.frida_mode ||
+      memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
 
     OKF(cPIN "Deferred forkserver binary detected.");
     setenv(DEFER_ENV_VAR, "1", 1);
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index a47b4f5f..c99d9a4d 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -397,8 +397,14 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
 
     if (likely(retlen && cksum == q->exec_cksum)) {
 
-      q->len = retlen;
+      if (afl_realloc((void **)&in_buf, retlen) == NULL) {
+
+        FATAL("can not allocate memory for trim");
+
+      }
+
       memcpy(in_buf, retbuf, retlen);
+      q->len = retlen;
 
       /* Let's save a clean trace, which will be needed by
          update_bitmap_score once we're done with the trimming stuff. */
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 4e8154cd..d72d4145 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1997,16 +1997,19 @@ havoc_stage:
   /* We essentially just do several thousand runs (depending on perf_score)
      where we take the input file and make random stacked tweaks. */
 
+#define MAX_HAVOC_ENTRY 59                                      /* 55 to 60 */
+
   u32 r_max, r;
 
-  r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
+  r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
+          (afl->a_extras_cnt ? 4 : 0);
 
   if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
 
     /* add expensive havoc cases here, they are activated after a full
        cycle without finds happened */
 
-    r_max++;
+    r_max += 4;
 
   }
 
@@ -2015,7 +2018,7 @@ havoc_stage:
 
     /* add expensive havoc cases here if there is no findings in the last 5s */
 
-    r_max++;
+    r_max += 4;
 
   }
 
@@ -2069,7 +2072,7 @@ havoc_stage:
 
       switch ((r = rand_below(afl, r_max))) {
 
-        case 0:
+        case 0 ... 3: {
 
           /* Flip a single bit somewhere. Spooky! */
 
@@ -2080,7 +2083,9 @@ havoc_stage:
           FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
           break;
 
-        case 1:
+        }
+
+        case 4 ... 7: {
 
           /* Set byte to interesting value. */
 
@@ -2092,63 +2097,77 @@ havoc_stage:
               interesting_8[rand_below(afl, sizeof(interesting_8))];
           break;
 
-        case 2:
+        }
+
+        case 8 ... 9: {
 
           /* Set word to interesting value, randomly choosing endian. */
 
           if (temp_len < 2) { break; }
 
-          if (rand_below(afl, 2)) {
-
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
-                interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
+          *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+              interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
 
-          } else {
+          break;
+
+        }
+
+        case 10 ... 11: {
+
+          /* Set word to interesting value, randomly choosing endian. */
+
+          if (temp_len < 2) { break; }
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
-                interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
-
-          }
+          *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
+              interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
 
           break;
 
-        case 3:
+        }
+
+        case 12 ... 13: {
 
           /* Set dword to interesting value, randomly choosing endian. */
 
           if (temp_len < 4) { break; }
 
-          if (rand_below(afl, 2)) {
-
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
-                interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
+          *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+              interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
 
-          } else {
+          break;
+
+        }
+
+        case 14 ... 15: {
+
+          /* Set dword to interesting value, randomly choosing endian. */
+
+          if (temp_len < 4) { break; }
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
-                interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
-
-          }
+          *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
+              interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
 
           break;
 
-        case 4:
+        }
+
+        case 16 ... 19: {
 
           /* Randomly subtract from byte. */
 
@@ -2159,7 +2178,9 @@ havoc_stage:
           out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
           break;
 
-        case 5:
+        }
+
+        case 20 ... 23: {
 
           /* Randomly add to byte. */
 
@@ -2170,139 +2191,165 @@ havoc_stage:
           out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
           break;
 
-        case 6:
+        }
 
-          /* Randomly subtract from word, random endian. */
+        case 24 ... 25: {
 
-          if (temp_len < 2) { break; }
+          /* Randomly subtract from word, little endian. */
 
-          if (rand_below(afl, 2)) {
+          if (temp_len < 2) { break; }
 
-            u32 pos = rand_below(afl, temp_len - 1);
+          u32 pos = rand_below(afl, temp_len - 1);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+          *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
-          } else {
+          break;
 
-            u32 pos = rand_below(afl, temp_len - 1);
-            u16 num = 1 + rand_below(afl, ARITH_MAX);
+        }
+
+        case 26 ... 27: {
+
+          /* Randomly subtract from word, big endian. */
+
+          if (temp_len < 2) { break; }
+
+          u32 pos = rand_below(afl, temp_len - 1);
+          u16 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos,
-                     num);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos,
+                   num);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u16 *)(out_buf + pos) =
-                SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
-
-          }
+          *(u16 *)(out_buf + pos) =
+              SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
 
           break;
 
-        case 7:
+        }
 
-          /* Randomly add to word, random endian. */
+        case 28 ... 29: {
 
-          if (temp_len < 2) { break; }
+          /* Randomly add to word, little endian. */
 
-          if (rand_below(afl, 2)) {
+          if (temp_len < 2) { break; }
 
-            u32 pos = rand_below(afl, temp_len - 1);
+          u32 pos = rand_below(afl, temp_len - 1);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+          *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
-          } else {
+          break;
+
+        }
+
+        case 30 ... 31: {
 
-            u32 pos = rand_below(afl, temp_len - 1);
-            u16 num = 1 + rand_below(afl, ARITH_MAX);
+          /* Randomly add to word, big endian. */
+
+          if (temp_len < 2) { break; }
+
+          u32 pos = rand_below(afl, temp_len - 1);
+          u16 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos,
-                     num);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos,
+                   num);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u16 *)(out_buf + pos) =
-                SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
-
-          }
+          *(u16 *)(out_buf + pos) =
+              SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
 
           break;
 
-        case 8:
+        }
 
-          /* Randomly subtract from dword, random endian. */
+        case 32 ... 33: {
 
-          if (temp_len < 4) { break; }
+          /* Randomly subtract from dword, little endian. */
 
-          if (rand_below(afl, 2)) {
+          if (temp_len < 4) { break; }
 
-            u32 pos = rand_below(afl, temp_len - 3);
+          u32 pos = rand_below(afl, temp_len - 3);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+          *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
-          } else {
+          break;
+
+        }
+
+        case 34 ... 35: {
+
+          /* Randomly subtract from dword, big endian. */
+
+          if (temp_len < 4) { break; }
 
-            u32 pos = rand_below(afl, temp_len - 3);
-            u32 num = 1 + rand_below(afl, ARITH_MAX);
+          u32 pos = rand_below(afl, temp_len - 3);
+          u32 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos,
-                     num);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos,
+                   num);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u32 *)(out_buf + pos) =
-                SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
-
-          }
+          *(u32 *)(out_buf + pos) =
+              SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
 
           break;
 
-        case 9:
+        }
 
-          /* Randomly add to dword, random endian. */
+        case 36 ... 37: {
 
-          if (temp_len < 4) { break; }
+          /* Randomly add to dword, little endian. */
 
-          if (rand_below(afl, 2)) {
+          if (temp_len < 4) { break; }
 
-            u32 pos = rand_below(afl, temp_len - 3);
+          u32 pos = rand_below(afl, temp_len - 3);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+          *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
-          } else {
+          break;
+
+        }
+
+        case 38 ... 39: {
 
-            u32 pos = rand_below(afl, temp_len - 3);
-            u32 num = 1 + rand_below(afl, ARITH_MAX);
+          /* Randomly add to dword, big endian. */
+
+          if (temp_len < 4) { break; }
+
+          u32 pos = rand_below(afl, temp_len - 3);
+          u32 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos,
-                     num);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos,
+                   num);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            *(u32 *)(out_buf + pos) =
-                SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
-
-          }
+          *(u32 *)(out_buf + pos) =
+              SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
 
           break;
 
-        case 10:
+        }
+
+        case 40 ... 43: {
 
           /* Just set a random byte to a random value. Because,
              why not. We use XOR with 1-255 to eliminate the
@@ -2315,67 +2362,64 @@ havoc_stage:
           out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
           break;
 
-        case 11 ... 12: {
-
-          /* Delete bytes. We're making this a bit more likely
-             than insertion (the next option) in hopes of keeping
-             files reasonably small. */
-
-          u32 del_from, del_len;
+        }
 
-          if (temp_len < 2) { break; }
+        case 44 ... 46: {
 
-          /* Don't delete too much. */
+          if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
 
-          del_len = choose_block_len(afl, temp_len - 1);
+            /* Clone bytes. */
 
-          del_from = rand_below(afl, temp_len - del_len + 1);
+            u32 clone_len = choose_block_len(afl, temp_len);
+            u32 clone_from = rand_below(afl, temp_len - clone_len + 1);
+            u32 clone_to = rand_below(afl, temp_len);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from,
-                   del_len);
-          strcat(afl->mutation, afl->m_tmp);
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u",
+                     "clone", clone_from, clone_to, clone_len);
+            strcat(afl->mutation, afl->m_tmp);
 #endif
-          memmove(out_buf + del_from, out_buf + del_from + del_len,
-                  temp_len - del_from - del_len);
+            u8 *new_buf =
+                afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
+            if (unlikely(!new_buf)) { PFATAL("alloc"); }
 
-          temp_len -= del_len;
+            /* Head */
 
-          break;
+            memcpy(new_buf, out_buf, clone_to);
 
-        }
+            /* Inserted part */
 
-        case 13:
+            memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
 
-          if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+            /* Tail */
+            memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
+                   temp_len - clone_to);
 
-            /* Clone bytes (75%) or insert a block of constant bytes (25%). */
+            out_buf = new_buf;
+            afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+            temp_len += clone_len;
 
-            u8  actually_clone = rand_below(afl, 4);
-            u32 clone_from, clone_to, clone_len;
-            u8 *new_buf;
+          }
 
-            if (likely(actually_clone)) {
+          break;
 
-              clone_len = choose_block_len(afl, temp_len);
-              clone_from = rand_below(afl, temp_len - clone_len + 1);
+        }
 
-            } else {
+        case 47: {
 
-              clone_len = choose_block_len(afl, HAVOC_BLK_XL);
-              clone_from = 0;
+          if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
 
-            }
+            /* Insert a block of constant bytes (25%). */
 
-            clone_to = rand_below(afl, temp_len);
+            u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL);
+            u32 clone_to = rand_below(afl, temp_len);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u",
-                     actually_clone ? "clone" : "insert", clone_from, clone_to,
-                     clone_len);
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u",
+                     "insert", clone_to, clone_len);
             strcat(afl->mutation, afl->m_tmp);
 #endif
-            new_buf =
+            u8 *new_buf =
                 afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
             if (unlikely(!new_buf)) { PFATAL("alloc"); }
 
@@ -2385,18 +2429,10 @@ havoc_stage:
 
             /* Inserted part */
 
-            if (likely(actually_clone)) {
-
-              memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
-
-            } else {
-
-              memset(new_buf + clone_to,
-                     rand_below(afl, 2) ? rand_below(afl, 256)
-                                        : out_buf[rand_below(afl, temp_len)],
-                     clone_len);
-
-            }
+            memset(new_buf + clone_to,
+                   rand_below(afl, 2) ? rand_below(afl, 256)
+                                      : out_buf[rand_below(afl, temp_len)],
+                   clone_len);
 
             /* Tail */
             memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
@@ -2410,47 +2446,79 @@ havoc_stage:
 
           break;
 
-        case 14: {
+        }
 
-          /* Overwrite bytes with a randomly selected chunk (75%) or fixed
-             bytes (25%). */
+        case 48 ... 50: {
 
-          u32 copy_from, copy_to, copy_len;
+          /* Overwrite bytes with a randomly selected chunk bytes. */
 
           if (temp_len < 2) { break; }
 
-          copy_len = choose_block_len(afl, temp_len - 1);
+          u32 copy_len = choose_block_len(afl, temp_len - 1);
+          u32 copy_from = rand_below(afl, temp_len - copy_len + 1);
+          u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
+
+          if (likely(copy_from != copy_to)) {
+
+#ifdef INTROSPECTION
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_COPY-%u-%u-%u",
+                     copy_from, copy_to, copy_len);
+            strcat(afl->mutation, afl->m_tmp);
+#endif
+            memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+
+          }
+
+          break;
+
+        }
 
-          copy_from = rand_below(afl, temp_len - copy_len + 1);
-          copy_to = rand_below(afl, temp_len - copy_len + 1);
+        case 51: {
 
-          if (likely(rand_below(afl, 4))) {
+          /* Overwrite bytes with fixed bytes. */
 
-            if (likely(copy_from != copy_to)) {
+          if (temp_len < 2) { break; }
+
+          u32 copy_len = choose_block_len(afl, temp_len - 1);
+          u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
 
 #ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                       " OVERWRITE_COPY-%u-%u-%u", copy_from, copy_to,
-                       copy_len);
-              strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_FIXED-%u-%u",
+                   copy_to, copy_len);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-              memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+          memset(out_buf + copy_to,
+                 rand_below(afl, 2) ? rand_below(afl, 256)
+                                    : out_buf[rand_below(afl, temp_len)],
+                 copy_len);
 
-            }
+          break;
 
-          } else {
+        }
+
+        // increase from 4 up to 8?
+        case 52 ... MAX_HAVOC_ENTRY: {
+
+          /* Delete bytes. We're making this a bit more likely
+             than insertion (the next option) in hopes of keeping
+             files reasonably small. */
+
+          if (temp_len < 2) { break; }
+
+          /* Don't delete too much. */
+
+          u32 del_len = choose_block_len(afl, temp_len - 1);
+          u32 del_from = rand_below(afl, temp_len - del_len + 1);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                     " OVERWRITE_FIXED-%u-%u-%u", copy_from, copy_to, copy_len);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from,
+                   del_len);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            memset(out_buf + copy_to,
-                   rand_below(afl, 2) ? rand_below(afl, 256)
-                                      : out_buf[rand_below(afl, temp_len)],
-                   copy_len);
+          memmove(out_buf + del_from, out_buf + del_from + del_len,
+                  temp_len - del_from - del_len);
 
-          }
+          temp_len -= del_len;
 
           break;
 
@@ -2458,93 +2526,101 @@ havoc_stage:
 
         default:
 
-          if (likely(r <= 16 && (afl->extras_cnt || afl->a_extras_cnt))) {
-
-            /* Values 15 and 16 can be selected only if there are any extras
-               present in the dictionaries. */
+          r -= (MAX_HAVOC_ENTRY + 1);
 
-            if (r == 15) {
+          if (afl->extras_cnt) {
 
-              /* Overwrite bytes with an extra. */
-
-              if (!afl->extras_cnt ||
-                  (afl->a_extras_cnt && rand_below(afl, 2))) {
+            if (r < 2) {
 
-                /* No user-specified extras or odds in our favor. Let's use an
-                   auto-detected one. */
+              /* Use the dictionary. */
 
-                u32 use_extra = rand_below(afl, afl->a_extras_cnt);
-                u32 extra_len = afl->a_extras[use_extra].len;
+              u32 use_extra = rand_below(afl, afl->extras_cnt);
+              u32 extra_len = afl->extras[use_extra].len;
 
-                if (extra_len > temp_len) { break; }
+              if (extra_len > temp_len) { break; }
 
-                u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+              u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
 #ifdef INTROSPECTION
-                snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                         " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
-                strcat(afl->mutation, afl->m_tmp);
+              snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_OVERWRITE-%u-%u",
+                       insert_at, extra_len);
+              strcat(afl->mutation, afl->m_tmp);
 #endif
-                memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
-                       extra_len);
-
-              } else {
+              memcpy(out_buf + insert_at, afl->extras[use_extra].data,
+                     extra_len);
 
-                /* No auto extras or odds in our favor. Use the dictionary. */
+              break;
 
-                u32 use_extra = rand_below(afl, afl->extras_cnt);
-                u32 extra_len = afl->extras[use_extra].len;
+            } else if (r < 4) {
 
-                if (extra_len > temp_len) { break; }
+              u32 use_extra = rand_below(afl, afl->extras_cnt);
+              u32 extra_len = afl->extras[use_extra].len;
+              if (temp_len + extra_len >= MAX_FILE) { break; }
 
-                u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+              u8 *ptr = afl->extras[use_extra].data;
+              u32 insert_at = rand_below(afl, temp_len + 1);
 #ifdef INTROSPECTION
-                snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                         " EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
-                strcat(afl->mutation, afl->m_tmp);
+              snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
+                       insert_at, extra_len);
+              strcat(afl->mutation, afl->m_tmp);
 #endif
-                memcpy(out_buf + insert_at, afl->extras[use_extra].data,
-                       extra_len);
 
-              }
+              out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+              if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+              /* Tail */
+              memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+                      temp_len - insert_at);
+
+              /* Inserted part */
+              memcpy(out_buf + insert_at, ptr, extra_len);
+              temp_len += extra_len;
 
               break;
 
-            } else {  // case 16
+            } else {
 
-              u32 use_extra, extra_len,
-                  insert_at = rand_below(afl, temp_len + 1);
-              u8 *ptr;
+              r -= 4;
 
-              /* Insert an extra. Do the same dice-rolling stuff as for the
-                 previous case. */
+            }
 
-              if (!afl->extras_cnt ||
-                  (afl->a_extras_cnt && rand_below(afl, 2))) {
+          }
 
-                use_extra = rand_below(afl, afl->a_extras_cnt);
-                extra_len = afl->a_extras[use_extra].len;
-                ptr = afl->a_extras[use_extra].data;
-#ifdef INTROSPECTION
-                snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                         " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
-                strcat(afl->mutation, afl->m_tmp);
-#endif
+          if (afl->a_extras_cnt) {
 
-              } else {
+            if (r < 2) {
 
-                use_extra = rand_below(afl, afl->extras_cnt);
-                extra_len = afl->extras[use_extra].len;
-                ptr = afl->extras[use_extra].data;
+              /* Use the dictionary. */
+
+              u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+              u32 extra_len = afl->a_extras[use_extra].len;
+
+              if (extra_len > temp_len) { break; }
+
+              u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
 #ifdef INTROSPECTION
-                snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
-                         insert_at, extra_len);
-                strcat(afl->mutation, afl->m_tmp);
+              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                       " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+              strcat(afl->mutation, afl->m_tmp);
 #endif
+              memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+                     extra_len);
 
-              }
+              break;
+
+            } else if (r < 4) {
 
+              u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+              u32 extra_len = afl->a_extras[use_extra].len;
               if (temp_len + extra_len >= MAX_FILE) { break; }
 
+              u8 *ptr = afl->a_extras[use_extra].data;
+              u32 insert_at = rand_below(afl, temp_len + 1);
+#ifdef INTROSPECTION
+              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                       " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
+              strcat(afl->mutation, afl->m_tmp);
+#endif
+
               out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
               if (unlikely(!out_buf)) { PFATAL("alloc"); }
 
@@ -2554,103 +2630,97 @@ havoc_stage:
 
               /* Inserted part */
               memcpy(out_buf + insert_at, ptr, extra_len);
-
               temp_len += extra_len;
 
               break;
 
-            }
+            } else {
 
-          } else {
+              r -= 4;
 
-            /*
-                        switch (r) {
+            }
 
-                          case 15:  // fall through
-                          case 16:
-                          case 17: {*/
+          }
 
-            /* Overwrite bytes with a randomly selected chunk from another
-               testcase or insert that chunk. */
+          /* Splicing otherwise if we are still here.
+             Overwrite bytes with a randomly selected chunk from another
+             testcase or insert that chunk. */
 
-            /* Pick a random queue entry and seek to it. */
+          /* Pick a random queue entry and seek to it. */
 
-            u32 tid;
-            do {
+          u32 tid;
+          do {
 
-              tid = rand_below(afl, afl->queued_paths);
+            tid = rand_below(afl, afl->queued_paths);
 
-            } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+          } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
 
-            /* Get the testcase for splicing. */
-            struct queue_entry *target = afl->queue_buf[tid];
-            u32                 new_len = target->len;
-            u8 *                new_buf = queue_testcase_get(afl, target);
+          /* Get the testcase for splicing. */
+          struct queue_entry *target = afl->queue_buf[tid];
+          u32                 new_len = target->len;
+          u8 *                new_buf = queue_testcase_get(afl, target);
 
-            if ((temp_len >= 2 && rand_below(afl, 2)) ||
-                temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+          if ((temp_len >= 2 && r % 2) || temp_len + HAVOC_BLK_XL >= MAX_FILE) {
 
-              /* overwrite mode */
+            /* overwrite mode */
 
-              u32 copy_from, copy_to, copy_len;
+            u32 copy_from, copy_to, copy_len;
 
-              copy_len = choose_block_len(afl, new_len - 1);
-              if (copy_len > temp_len) copy_len = temp_len;
+            copy_len = choose_block_len(afl, new_len - 1);
+            if (copy_len > temp_len) copy_len = temp_len;
 
-              copy_from = rand_below(afl, new_len - copy_len + 1);
-              copy_to = rand_below(afl, temp_len - copy_len + 1);
+            copy_from = rand_below(afl, new_len - copy_len + 1);
+            copy_to = rand_below(afl, temp_len - copy_len + 1);
 
 #ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                       " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
-                       copy_len, target->fname);
-              strcat(afl->mutation, afl->m_tmp);
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                     " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
+                     copy_len, target->fname);
+            strcat(afl->mutation, afl->m_tmp);
 #endif
-              memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+            memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
 
-            } else {
+          } else {
 
-              /* insert mode */
+            /* insert mode */
 
-              u32 clone_from, clone_to, clone_len;
+            u32 clone_from, clone_to, clone_len;
 
-              clone_len = choose_block_len(afl, new_len);
-              clone_from = rand_below(afl, new_len - clone_len + 1);
-              clone_to = rand_below(afl, temp_len + 1);
+            clone_len = choose_block_len(afl, new_len);
+            clone_from = rand_below(afl, new_len - clone_len + 1);
+            clone_to = rand_below(afl, temp_len + 1);
 
-              u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
-                                         temp_len + clone_len + 1);
-              if (unlikely(!temp_buf)) { PFATAL("alloc"); }
+            u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+                                       temp_len + clone_len + 1);
+            if (unlikely(!temp_buf)) { PFATAL("alloc"); }
 
 #ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                       " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
-                       clone_len, target->fname);
-              strcat(afl->mutation, afl->m_tmp);
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                     " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
+                     clone_len, target->fname);
+            strcat(afl->mutation, afl->m_tmp);
 #endif
-              /* Head */
-
-              memcpy(temp_buf, out_buf, clone_to);
-
-              /* Inserted part */
+            /* Head */
 
-              memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
+            memcpy(temp_buf, out_buf, clone_to);
 
-              /* Tail */
-              memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
-                     temp_len - clone_to);
+            /* Inserted part */
 
-              out_buf = temp_buf;
-              afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
-              temp_len += clone_len;
+            memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
 
-            }
+            /* Tail */
+            memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
+                   temp_len - clone_to);
 
-            break;
+            out_buf = temp_buf;
+            afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+            temp_len += clone_len;
 
           }
 
-          // end of default:
+          break;
+
+          // end of default
 
       }
 
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index e5f51a6c..811e805c 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -478,7 +478,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
         u8 *fname_orig = NULL;
 
         /* At the initialization stage, queue_cur is NULL */
-        if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
+        if (afl->queue_cur && !afl->syncing_party) {
+
+          fname_orig = afl->queue_cur->fname;
+
+        }
 
         el->afl_custom_queue_new_entry(el->data, fname, fname_orig);
 
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 9bfbf95b..cf1e5ea5 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -437,7 +437,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
 
   if (taint) {
 
-    if (afl->colorize_success &&
+    if (afl->colorize_success && afl->cmplog_lvl < 3 &&
         (len / positions == 1 && positions > CMPLOG_POSITIONS_MAX &&
          afl->active_paths / afl->colorize_success > CMPLOG_CORPUS_PERCENT)) {
 
@@ -1749,6 +1749,12 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
 #endif
 
+#ifdef _DEBUG
+      if (o->v0 != orig_o->v0 || o->v1 != orig_o->v1)
+        fprintf(stderr, "key=%u idx=%u o0=%llu v0=%llu o1=%llu v1=%llu\n", key,
+                idx, orig_o->v0, o->v0, orig_o->v1, o->v1);
+#endif
+
       // even for u128 and _ExtInt we do cmp_extend_encoding() because
       // if we got here their own special trials failed and it might just be
       // a cast from e.g. u64 to u128 from the input data.
@@ -2365,6 +2371,24 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
       status = 0;
 
+#ifdef _DEBUG
+      int w;
+      fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx,
+              SHAPE_BYTES(h->shape));
+      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+        fprintf(stderr, "%02x", orig_o->v0[w]);
+      fprintf(stderr, " v0=");
+      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+        fprintf(stderr, "%02x", o->v0[w]);
+      fprintf(stderr, " o1=");
+      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+        fprintf(stderr, "%02x", orig_o->v1[w]);
+      fprintf(stderr, " v1=");
+      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+        fprintf(stderr, "%02x", o->v1[w]);
+      fprintf(stderr, "\n");
+#endif
+
       if (unlikely(rtn_extend_encoding(
               afl, o->v0, o->v1, orig_o->v0, orig_o->v1, SHAPE_BYTES(h->shape),
               idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 83133dad..832f17bb 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -712,6 +712,7 @@ void sync_fuzzers(afl_state_t *afl) {
   if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
 
   afl->last_sync_time = get_cur_time();
+  afl->last_sync_cycle = afl->queue_cycle;
 
 }
 
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 0ddf8cf3..28d3339a 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
   afl->stats_update_freq = 1;
   afl->stats_avg_exec = 0;
   afl->skip_deterministic = 1;
-  afl->cmplog_lvl = 1;
+  afl->cmplog_lvl = 2;
 #ifndef NO_SPLICING
   afl->use_splicing = 1;
 #endif
@@ -292,6 +292,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_autoresume =
                 get_afl_env(afl_environment_variables[i]) ? 1 : 0;
 
+          } else if (!strncmp(env, "AFL_PERSISTENT_RECORD",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_persistent_record =
+                get_afl_env(afl_environment_variables[i]);
+
           } else if (!strncmp(env, "AFL_CYCLE_SCHEDULES",
 
                               afl_environment_variable_len)) {
@@ -299,6 +306,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->cycle_schedules = afl->afl_env.afl_cycle_schedules =
                 get_afl_env(afl_environment_variables[i]) ? 1 : 0;
 
+          } else if (!strncmp(env, "AFL_EXIT_ON_SEED_ISSUES",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_exit_on_seed_issues =
+                get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
           } else if (!strncmp(env, "AFL_EXPAND_HAVOC_NOW",
 
                               afl_environment_variable_len)) {
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 2c814d90..22c0cbd2 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -355,18 +355,18 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
 void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
                             double eps) {
 
-  if (unlikely(afl->stop_soon) ||
-      unlikely(afl->plot_prev_qp == afl->queued_paths &&
-               afl->plot_prev_pf == afl->pending_favored &&
-               afl->plot_prev_pnf == afl->pending_not_fuzzed &&
-               afl->plot_prev_ce == afl->current_entry &&
-               afl->plot_prev_qc == afl->queue_cycle &&
-               afl->plot_prev_uc == afl->unique_crashes &&
-               afl->plot_prev_uh == afl->unique_hangs &&
-               afl->plot_prev_md == afl->max_depth &&
-               afl->plot_prev_ed == afl->fsrv.total_execs) ||
-      unlikely(!afl->queue_cycle) ||
-      unlikely(get_cur_time() - afl->start_time <= 60)) {
+  if (unlikely(!afl->force_ui_update &&
+               (afl->stop_soon ||
+                (afl->plot_prev_qp == afl->queued_paths &&
+                 afl->plot_prev_pf == afl->pending_favored &&
+                 afl->plot_prev_pnf == afl->pending_not_fuzzed &&
+                 afl->plot_prev_ce == afl->current_entry &&
+                 afl->plot_prev_qc == afl->queue_cycle &&
+                 afl->plot_prev_uc == afl->unique_crashes &&
+                 afl->plot_prev_uh == afl->unique_hangs &&
+                 afl->plot_prev_md == afl->max_depth &&
+                 afl->plot_prev_ed == afl->fsrv.total_execs) ||
+                !afl->queue_cycle || get_cur_time() - afl->start_time <= 60))) {
 
     return;
 
@@ -531,7 +531,8 @@ void show_stats(afl_state_t *afl) {
 
   /* Roughly every minute, update fuzzer stats and save auto tokens. */
 
-  if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
+  if (unlikely(afl->force_ui_update ||
+               cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000)) {
 
     afl->stats_last_stats_ms = cur_ms;
     write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
@@ -543,7 +544,8 @@ void show_stats(afl_state_t *afl) {
 
   if (unlikely(afl->afl_env.afl_statsd)) {
 
-    if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) {
+    if (unlikely(afl->force_ui_update && cur_ms - afl->statsd_last_send_ms >
+                                             STATSD_UPDATE_SEC * 1000)) {
 
       /* reset counter, even if send failed. */
       afl->statsd_last_send_ms = cur_ms;
@@ -555,7 +557,8 @@ void show_stats(afl_state_t *afl) {
 
   /* Every now and then, write plot data. */
 
-  if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) {
+  if (unlikely(afl->force_ui_update ||
+               cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000)) {
 
     afl->stats_last_plot_ms = cur_ms;
     maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec);
@@ -564,14 +567,14 @@ void show_stats(afl_state_t *afl) {
 
   /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
 
-  if (!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
-      !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) {
+  if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
+               !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)) {
 
     afl->stop_soon = 2;
 
   }
 
-  if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) {
+  if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) {
 
     afl->stop_soon = 2;
 
@@ -583,7 +586,7 @@ void show_stats(afl_state_t *afl) {
 
   /* If we haven't started doing things, bail out. */
 
-  if (!afl->queue_cur) { return; }
+  if (unlikely(!afl->queue_cur)) { return; }
 
   /* Compute some mildly useful bitmap stats. */
 
@@ -602,7 +605,7 @@ void show_stats(afl_state_t *afl) {
 
   SAYF(TERM_HOME);
 
-  if (afl->term_too_small) {
+  if (unlikely(afl->term_too_small)) {
 
     SAYF(cBRI
          "Your terminal is too small to display the UI.\n"
@@ -861,9 +864,13 @@ void show_stats(afl_state_t *afl) {
        " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
        " path geometry " bSTG bH5 bH2 bVL "\n");
 
-  if (afl->skip_deterministic) {
+  if (unlikely(afl->custom_only)) {
 
-    strcpy(tmp, "n/a, n/a, n/a");
+    strcpy(tmp, "disabled (custom-mutator-only mode)");
+
+  } else if (likely(afl->skip_deterministic)) {
+
+    strcpy(tmp, "disabled (default, enable with -D)");
 
   } else {
 
@@ -881,7 +888,7 @@ void show_stats(afl_state_t *afl) {
                 "    levels : " cRST "%-10s" bSTG       bV "\n",
        tmp, u_stringify_int(IB(0), afl->max_depth));
 
-  if (!afl->skip_deterministic) {
+  if (unlikely(!afl->skip_deterministic)) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
             u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
@@ -897,7 +904,7 @@ void show_stats(afl_state_t *afl) {
                 "   pending : " cRST "%-10s" bSTG       bV "\n",
        tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
 
-  if (!afl->skip_deterministic) {
+  if (unlikely(!afl->skip_deterministic)) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
             u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
@@ -913,7 +920,7 @@ void show_stats(afl_state_t *afl) {
                 "  pend fav : " cRST "%-10s" bSTG       bV "\n",
        tmp, u_stringify_int(IB(0), afl->pending_favored));
 
-  if (!afl->skip_deterministic) {
+  if (unlikely(!afl->skip_deterministic)) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
             u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
@@ -929,7 +936,7 @@ void show_stats(afl_state_t *afl) {
                 " own finds : " cRST "%-10s" bSTG       bV "\n",
        tmp, u_stringify_int(IB(0), afl->queued_discovered));
 
-  if (!afl->skip_deterministic) {
+  if (unlikely(!afl->skip_deterministic)) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
             u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
@@ -939,6 +946,14 @@ void show_stats(afl_state_t *afl) {
             u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
             u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
 
+  } else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
+
+    strcpy(tmp, "n/a");
+
+  } else {
+
+    strcpy(tmp, "havoc mode");
+
   }
 
   SAYF(bV bSTOP "  dictionary : " cRST "%-36s " bSTG bV bSTOP
@@ -974,35 +989,57 @@ void show_stats(afl_state_t *afl) {
                   : cRST),
        tmp);
 
-  if (afl->shm.cmplog_mode) {
+  if (unlikely(afl->afl_env.afl_python_module)) {
 
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
+    sprintf(tmp, "%s/%s,",
             u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
-            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
-            u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
-            u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
-            u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
-            u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
-            u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]));
+
+  } else {
+
+    strcpy(tmp, "unused,");
+
+  }
+
+  if (unlikely(afl->afl_env.afl_custom_mutator_library)) {
 
-    SAYF(bV bSTOP "   custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
-         tmp);
+    strcat(tmp, " ");
+    strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_PYTHON]));
+    strcat(tmp, "/");
+    strcat(tmp, u_stringify_int(IB(3), afl->stage_cycles[STAGE_PYTHON]));
+    strcat(tmp, ",");
 
   } else {
 
-    sprintf(tmp, "%s/%s, %s/%s",
-            u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
-            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
-            u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+    strcat(tmp, " unused,");
+
+  }
+
+  if (unlikely(afl->shm.cmplog_mode)) {
+
+    strcat(tmp, " ");
+    strcat(tmp, u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]));
+    strcat(tmp, "/");
+    strcat(tmp, u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]));
+    strcat(tmp, ", ");
+    strcat(tmp, u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]));
+    strcat(tmp, "/");
+    strcat(tmp, u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
+
+  } else {
 
-    SAYF(bV bSTOP "   py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
-         tmp);
+    strcat(tmp, " unused, unused");
 
   }
 
-  if (!afl->bytes_trim_out) {
+  SAYF(bV bSTOP "py/custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
+       tmp);
+
+  if (likely(afl->disable_trim)) {
+
+    sprintf(tmp, "disabled, ");
+
+  } else if (unlikely(!afl->bytes_trim_out)) {
 
     sprintf(tmp, "n/a, ");
 
@@ -1015,12 +1052,13 @@ void show_stats(afl_state_t *afl) {
 
   }
 
-  if (!afl->blocks_eff_total) {
+  if (likely(afl->skip_deterministic)) {
 
-    u8 tmp2[128];
+    strcat(tmp, "disabled");
 
-    sprintf(tmp2, "n/a");
-    strcat(tmp, tmp2);
+  } else if (unlikely(!afl->blocks_eff_total)) {
+
+    strcat(tmp, "n/a");
 
   } else {
 
@@ -1044,7 +1082,7 @@ void show_stats(afl_state_t *afl) {
   //
   //} else {
 
-  SAYF(bV bSTOP "        trim : " cRST "%-36s " bSTG bV RESET_G1, tmp);
+  SAYF(bV bSTOP "    trim/eff : " cRST "%-36s " bSTG bV RESET_G1, tmp);
 
   //}
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index d70ffd31..3606533d 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -109,6 +109,7 @@ static void usage(u8 *argv0, int more_help) {
       "maximum.\n"
       "  -m megs       - memory limit for child process (%u MB, 0 = no limit "
       "[default])\n"
+      "  -O            - use binary-only instrumentation (FRIDA mode)\n"
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
@@ -126,7 +127,7 @@ static void usage(u8 *argv0, int more_help) {
       "it.\n"
       "                  if using QEMU, just use -c 0.\n"
       "  -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
-      "                  1=small files (default), 2=larger files, 3=all "
+      "                  1=small files, 2=larger files (default), 3=all "
       "files,\n"
       "                  A=arithmetic solving, T=transformational solving.\n\n"
       "Fuzzing behavior settings:\n"
@@ -175,6 +176,14 @@ static void usage(u8 *argv0, int more_help) {
   #define DYN_COLOR
 #endif
 
+#ifdef AFL_PERSISTENT_RECORD
+  #define PERSISTENT_MSG                                                 \
+    "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \
+    "out/crashes\n"
+#else
+  #define PERSISTENT_MSG
+#endif
+
     SAYF(
       "Environment variables used:\n"
       "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
@@ -222,6 +231,9 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_PATH: path to AFL support binaries\n"
       "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
       "AFL_QUIET: suppress forkserver status messages\n"
+
+      PERSISTENT_MSG
+
       "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_TARGET_ENV: pass extra environment variables to target\n"
       "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
@@ -253,7 +265,13 @@ static void usage(u8 *argv0, int more_help) {
   SAYF("Compiled with %s module support, see docs/custom_mutator.md\n",
        (char *)PYTHON_VERSION);
 #else
-  SAYF("Compiled without python module support\n");
+  SAYF("Compiled without python module support.\n");
+#endif
+
+#ifdef AFL_PERSISTENT_RECORD
+  SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n");
+#else
+  SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n");
 #endif
 
 #ifdef USEMMAP
@@ -263,27 +281,27 @@ static void usage(u8 *argv0, int more_help) {
 #endif
 
 #ifdef ASAN_BUILD
-  SAYF("Compiled with ASAN_BUILD\n\n");
+  SAYF("Compiled with ASAN_BUILD.\n");
 #endif
 
 #ifdef NO_SPLICING
-  SAYF("Compiled with NO_SPLICING\n\n");
+  SAYF("Compiled with NO_SPLICING.\n");
 #endif
 
 #ifdef PROFILING
-  SAYF("Compiled with PROFILING\n\n");
+  SAYF("Compiled with PROFILING.\n");
 #endif
 
 #ifdef INTROSPECTION
-  SAYF("Compiled with INTROSPECTION\n\n");
+  SAYF("Compiled with INTROSPECTION.\n");
 #endif
 
 #ifdef _DEBUG
-  SAYF("Compiled with _DEBUG\n\n");
+  SAYF("Compiled with _DEBUG.\n");
 #endif
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
-  SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS\n\n");
+  SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
 #endif
 
   SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
@@ -320,6 +338,8 @@ int main(int argc, char **argv_orig, char **envp) {
   u8 *extras_dir[4];
   u8  mem_limit_given = 0, exit_1 = 0, debug = 0,
      extras_dir_cnt = 0 /*, have_p = 0*/;
+  char * afl_preload;
+  char * frida_afl_preload = NULL;
   char **use_argv;
 
   struct timeval  tv;
@@ -363,7 +383,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   while ((opt = getopt(
               argc, argv,
-              "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
+              "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
 
     switch (opt) {
 
@@ -755,6 +775,18 @@ int main(int argc, char **argv_orig, char **envp) {
         afl->use_banner = optarg;
         break;
 
+      case 'O':                                               /* FRIDA mode */
+
+        if (afl->fsrv.frida_mode) {
+
+          FATAL("Multiple -O options not supported");
+
+        }
+
+        afl->fsrv.frida_mode = 1;
+
+        break;
+
       case 'Q':                                                /* QEMU mode */
 
         if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -831,6 +863,14 @@ int main(int argc, char **argv_orig, char **envp) {
               break;
             case '3':
               afl->cmplog_lvl = 3;
+
+              if (!afl->disable_trim) {
+
+                ACTF("Deactivating trimming due CMPLOG level 3");
+                afl->disable_trim = 1;
+
+              }
+
               break;
             case 'a':
             case 'A':
@@ -1023,6 +1063,30 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+  if (unlikely(afl->afl_env.afl_persistent_record)) {
+
+  #ifdef AFL_PERSISTENT_RECORD
+
+    afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record);
+
+    if (afl->fsrv.persistent_record < 2) {
+
+      FATAL(
+          "AFL_PERSISTENT_RECORD value must be be at least 2, recommended is "
+          "100 or 1000.");
+
+    }
+
+  #else
+
+    FATAL(
+        "afl-fuzz was not compiled with AFL_PERSISTENT_RECORD enabled in "
+        "config.h!");
+
+  #endif
+
+  }
+
   if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
 
   OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
@@ -1085,6 +1149,7 @@ int main(int argc, char **argv_orig, char **envp) {
   if (afl->non_instrumented_mode) {
 
     if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
+    if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
     if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
     if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
 
@@ -1289,6 +1354,25 @@ int main(int argc, char **argv_orig, char **envp) {
 
       /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
 
+    } else if (afl->fsrv.frida_mode) {
+
+      afl_preload = getenv("AFL_PRELOAD");
+      u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+      if (afl_preload) {
+
+        frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+      } else {
+
+        frida_afl_preload = alloc_printf("%s", frida_binary);
+
+      }
+
+      ck_free(frida_binary);
+
+      setenv("LD_PRELOAD", frida_afl_preload, 1);
+      setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
     } else {
 
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -1296,6 +1380,13 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+  } else if (afl->fsrv.frida_mode) {
+
+    u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+    setenv("LD_PRELOAD", frida_binary, 1);
+    setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+    ck_free(frida_binary);
+
   }
 
   if (getenv("AFL_LD_PRELOAD")) {
@@ -1479,7 +1570,8 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
+    if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode &&
+        !afl->non_instrumented_mode) {
 
       check_binary(afl, afl->cmplog_binary);
 
@@ -1489,6 +1581,23 @@ int main(int argc, char **argv_orig, char **envp) {
 
   check_binary(afl, argv[optind]);
 
+  #ifdef AFL_PERSISTENT_RECORD
+  if (unlikely(afl->fsrv.persistent_record)) {
+
+    if (!getenv(PERSIST_ENV_VAR)) {
+
+      FATAL(
+          "Target binary is not compiled in persistent mode, "
+          "AFL_PERSISTENT_RECORD makes no sense.");
+
+    }
+
+    afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
+
+  }
+
+  #endif
+
   if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
 
   afl->start_time = get_cur_time();
@@ -1513,7 +1622,8 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || afl->unicorn_mode) {
+  if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
+      afl->fsrv.frida_mode || afl->unicorn_mode) {
 
     map_size = afl->fsrv.map_size = MAP_SIZE;
     afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
@@ -1773,6 +1883,14 @@ int main(int argc, char **argv_orig, char **envp) {
                   runs_in_current_cycle > afl->queued_paths) ||
                  (afl->old_seed_selection && !afl->queue_cur))) {
 
+      if (unlikely((afl->last_sync_cycle < afl->queue_cycle ||
+                    (!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
+                   afl->sync_id)) {
+
+        sync_fuzzers(afl);
+
+      }
+
       ++afl->queue_cycle;
       runs_in_current_cycle = (u32)-1;
       afl->cur_skipped_paths = 0;
@@ -1886,6 +2004,13 @@ int main(int argc, char **argv_orig, char **envp) {
 
       }
 
+  #ifdef INTROSPECTION
+      fprintf(afl->introspection_file,
+              "CYCLE cycle=%llu cycle_wo_finds=%llu expand_havoc=%u queue=%u\n",
+              afl->queue_cycle, afl->cycles_wo_finds, afl->expand_havoc,
+              afl->queued_paths);
+  #endif
+
       if (afl->cycle_schedules) {
 
         /* we cannot mix non-AFLfast schedules with others */
@@ -1937,13 +2062,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
       prev_queued = afl->queued_paths;
 
-      if (afl->sync_id && afl->queue_cycle == 1 &&
-          afl->afl_env.afl_import_first) {
-
-        sync_fuzzers(afl);
-
-      }
-
     }
 
     ++runs_in_current_cycle;
@@ -2023,12 +2141,10 @@ int main(int argc, char **argv_orig, char **envp) {
   }
 
   write_bitmap(afl);
-  maybe_update_plot_file(afl, 0, 0, 0);
   save_auto(afl);
 
 stop_fuzzing:
 
-  write_stats_file(afl, 0, 0, 0, 0);
   afl->force_ui_update = 1;  // ensure the screen is reprinted
   show_stats(afl);           // print the screen one last time
 
@@ -2074,6 +2190,8 @@ stop_fuzzing:
 
   }
 
+  if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
   fclose(afl->fsrv.plot_file);
   destroy_queue(afl);
   destroy_extras(afl);
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 0a978653..d0113af9 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -73,8 +73,8 @@ static u32 ld_param_cnt = 1;        /* Number of params to 'ld'             */
    so we exploit this property to keep the code "simple". */
 static void edit_params(int argc, char **argv) {
 
-  u32 i, instrim = 0, gold_pos = 0, gold_present = 0, rt_present = 0,
-         rt_lto_present = 0, inst_present = 0;
+  u32 i, gold_pos = 0, gold_present = 0, rt_present = 0, rt_lto_present = 0,
+         inst_present = 0;
   char *ptr;
 
   ld_params = ck_alloc(4096 * sizeof(u8 *));
@@ -186,17 +186,18 @@ static void edit_params(int argc, char **argv) {
 
   }
 
-  if (getenv("AFL_LLVM_INSTRIM"))
-    instrim = 1;
-  else if ((ptr = getenv("AFL_LLVM_INSTRUMENT")) &&
-           (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0))
-    instrim = 1;
+  if (getenv("AFL_LLVM_INSTRIM") ||
+      ((ptr = getenv("AFL_LLVM_INSTRUMENT")) &&
+       (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0)))
+    FATAL(
+        "InsTrim was removed because it is not effective. Use a modern LLVM "
+        "and PCGUARD (which is the default in afl-cc).\n");
 
   if (debug)
     DEBUGF(
-        "passthrough=%s instrim=%u, gold_pos=%u, gold_present=%s "
+        "passthrough=%s, gold_pos=%u, gold_present=%s "
         "inst_present=%s rt_present=%s rt_lto_present=%s\n",
-        passthrough ? "true" : "false", instrim, gold_pos,
+        passthrough ? "true" : "false", gold_pos,
         gold_present ? "true" : "false", inst_present ? "true" : "false",
         rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
 
@@ -230,12 +231,8 @@ static void edit_params(int argc, char **argv) {
 
       if (!inst_present) {
 
-        if (instrim)
-          ld_params[ld_param_cnt++] =
-              alloc_printf("-mllvm=-load=%s/afl-llvm-lto-instrim.so", afl_path);
-        else
-          ld_params[ld_param_cnt++] = alloc_printf(
-              "-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", afl_path);
+        ld_params[ld_param_cnt++] = alloc_printf(
+            "-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", afl_path);
 
       }
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 077c9248..946b19cd 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -72,8 +72,7 @@ static u8 *in_data,                    /* Input data                        */
 static u64 total;                      /* tuple content information         */
 static u32 tcnt, highest;              /* tuple content information         */
 
-static u32 in_len,                     /* Input data length                 */
-    arg_offset;                        /* Total number of execs             */
+static u32 in_len;                     /* Input data length                 */
 
 static u32 map_size = MAP_SIZE;
 
@@ -556,8 +555,10 @@ static void handle_stop_sig(int sig) {
 
 /* Do basic preparations - persistent fds, filenames, etc. */
 
-static void set_up_environment(afl_forkserver_t *fsrv) {
+static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
 
+  char *afl_preload;
+  char *frida_afl_preload = NULL;
   setenv("ASAN_OPTIONS",
          "abort_on_error=1:"
          "detect_leaks=0:"
@@ -571,6 +572,13 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
          "handle_sigill=0",
          0);
 
+  setenv("LSAN_OPTIONS",
+         "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+         "fast_unwind_on_malloc=0:"
+         "symbolize=0:"
+         "print_suppressions=0",
+          0);
+
   setenv("UBSAN_OPTIONS",
          "halt_on_error=1:"
          "abort_on_error=1:"
@@ -601,6 +609,25 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
 
       /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
 
+    } else if (fsrv->frida_mode) {
+
+      afl_preload = getenv("AFL_PRELOAD");
+      u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+      if (afl_preload) {
+
+        frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+      } else {
+
+        frida_afl_preload = alloc_printf("%s", frida_binary);
+
+      }
+
+      ck_free(frida_binary);
+
+      setenv("LD_PRELOAD", frida_afl_preload, 1);
+      setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
     } else {
 
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -608,8 +635,17 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
 
     }
 
+  } else if (fsrv->frida_mode) {
+
+    u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+    setenv("LD_PRELOAD", frida_binary, 1);
+    setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+    ck_free(frida_binary);
+
   }
 
+  if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
 }
 
 /* Setup signal handlers, duh. */
@@ -656,6 +692,7 @@ static void usage(u8 *argv0) {
       "Execution control settings:\n"
       "  -t msec       - timeout for each run (none)\n"
       "  -m megs       - memory limit for child process (%u MB)\n"
+      "  -O            - use binary-only instrumentation (FRIDA mode)\n"
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use Unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine mode)\n"
@@ -724,7 +761,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; }
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrsh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) {
 
     switch (opt) {
 
@@ -858,6 +895,14 @@ int main(int argc, char **argv_orig, char **envp) {
         at_file = optarg;
         break;
 
+      case 'O':                                               /* FRIDA mode */
+
+        if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
+
+        fsrv->frida_mode = 1;
+
+        break;
+
       case 'Q':
 
         if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -944,7 +989,7 @@ int main(int argc, char **argv_orig, char **envp) {
   shm.cmplog_mode = 0;
   setup_signal_handlers();
 
-  set_up_environment(fsrv);
+  set_up_environment(fsrv, argv);
 
   fsrv->target_path = find_binary(argv[optind]);
   fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
@@ -958,10 +1003,27 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (in_dir) {
 
-    detect_file_args(argv + optind, "", &fsrv->use_stdin);
+    /* If we don't have a file name chosen yet, use a safe default. */
+    u8 *use_dir = ".";
+
+    if (access(use_dir, R_OK | W_OK | X_OK)) {
+
+      use_dir = get_afl_env("TMPDIR");
+      if (!use_dir) { use_dir = "/tmp"; }
+
+    }
+
+    stdin_file = at_file ? strdup(at_file)
+                         : (char *)alloc_printf("%s/.afl-showmap-temp-%u",
+                                                use_dir, (u32)getpid());
+    unlink(stdin_file);
+
+    // If @@ are in the target args, replace them and also set use_stdin=false.
+    detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
 
   } else {
 
+    // If @@ are in the target args, replace them and also set use_stdin=false.
     detect_file_args(argv + optind, at_file, &fsrv->use_stdin);
 
   }
@@ -986,14 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  i = 0;
-  while (use_argv[i] != NULL && !arg_offset) {
-
-    if (strcmp(use_argv[i], "@@") == 0) { arg_offset = i; }
-    i++;
-
-  }
-
   shm_fuzz = ck_alloc(sizeof(sharedmem_t));
 
   /* initialize cmplog_mode */
@@ -1104,31 +1158,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    u8 *use_dir = ".";
-
-    if (access(use_dir, R_OK | W_OK | X_OK)) {
-
-      use_dir = get_afl_env("TMPDIR");
-      if (!use_dir) { use_dir = "/tmp"; }
-
-    }
-
-    stdin_file = at_file ? strdup(at_file)
-                         : (char *)alloc_printf("%s/.afl-showmap-temp-%u",
-                                                use_dir, (u32)getpid());
-    unlink(stdin_file);
     atexit(at_exit_handler);
     fsrv->out_file = stdin_file;
     fsrv->out_fd =
         open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
     if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
 
-    if (arg_offset && use_argv[arg_offset] != stdin_file) {
-
-      use_argv[arg_offset] = strdup(stdin_file);
-
-    }
-
     if (get_afl_env("AFL_DEBUG")) {
 
       int j = optind;
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index fc974262..6656712a 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -640,9 +640,11 @@ static void handle_stop_sig(int sig) {
 
 /* Do basic preparations - persistent fds, filenames, etc. */
 
-static void set_up_environment(afl_forkserver_t *fsrv) {
+static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
 
-  u8 *x;
+  u8 *  x;
+  char *afl_preload;
+  char *frida_afl_preload = NULL;
 
   fsrv->dev_null_fd = open("/dev/null", O_RDWR);
   if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@@ -712,6 +714,18 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
 
   }
 
+  x = get_afl_env("LSAN_OPTIONS");
+
+  if (x) {
+
+    if (!strstr(x, "symbolize=0")) {
+
+      FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
+
+    }
+
+  }
+
   setenv("ASAN_OPTIONS",
          "abort_on_error=1:"
          "detect_leaks=0:"
@@ -749,12 +763,38 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
                          "handle_sigfpe=0:"
                          "handle_sigill=0", 0);
 
+  setenv("LSAN_OPTIONS",
+         "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+         "fast_unwind_on_malloc=0:"
+         "symbolize=0:"
+         "print_suppressions=0",
+         0);
+
   if (get_afl_env("AFL_PRELOAD")) {
 
     if (fsrv->qemu_mode) {
 
       /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
 
+    } else if (fsrv->frida_mode) {
+
+      afl_preload = getenv("AFL_PRELOAD");
+      u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+      if (afl_preload) {
+
+        frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
+
+      } else {
+
+        frida_afl_preload = alloc_printf("%s", frida_binary);
+
+      }
+
+      ck_free(frida_binary);
+
+      setenv("LD_PRELOAD", frida_afl_preload, 1);
+      setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
+
     } else {
 
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@@ -762,8 +802,17 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
 
     }
 
+  } else if (fsrv->frida_mode) {
+
+    u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+    setenv("LD_PRELOAD", frida_binary, 1);
+    setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
+    ck_free(frida_binary);
+
   }
 
+  if (frida_afl_preload) { ck_free(frida_afl_preload); }
+
 }
 
 /* Setup signal handlers, duh. */
@@ -804,6 +853,7 @@ static void usage(u8 *argv0) {
       "  -f file       - input file read by the tested program (stdin)\n"
       "  -t msec       - timeout for each run (%u ms)\n"
       "  -m megs       - memory limit for child process (%u MB)\n"
+      "  -O            - use binary-only instrumentation (FRIDA mode)\n"
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
@@ -859,7 +909,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeOQUWHh")) > 0) {
 
     switch (opt) {
 
@@ -971,6 +1021,14 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
+      case 'O':                                               /* FRIDA mode */
+
+        if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
+
+        fsrv->frida_mode = 1;
+
+        break;
+
       case 'Q':
 
         if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -1054,7 +1112,7 @@ int main(int argc, char **argv_orig, char **envp) {
   atexit(at_exit_handler);
   setup_signal_handlers();
 
-  set_up_environment(fsrv);
+  set_up_environment(fsrv, argv);
 
   fsrv->target_path = find_binary(argv[optind]);
   fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
diff --git a/test/test-llvm.sh b/test/test-llvm.sh
index 3ef36b37..06d0a0f8 100755
--- a/test/test-llvm.sh
+++ b/test/test-llvm.sh
@@ -46,7 +46,8 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
   ../afl-clang-fast -DTEST_SHARED_OBJECT=1 -z defs -fPIC -shared -o test-instr.so ../test-instr.c > /dev/null 2>&1
   test -e test-instr.so && {
     $ECHO "$GREEN[+] llvm_mode shared object with -z defs compilation succeeded"
-    ../afl-clang-fast -o test-dlopen.plain test-dlopen.c -ldl > /dev/null 2>&1
+    test `uname -s` = 'Linux' && LIBS=-ldl :
+    ../afl-clang-fast -o test-dlopen.plain test-dlopen.c ${LIBS} > /dev/null 2>&1
     test -e test-dlopen.plain && {
       $ECHO "$GREEN[+] llvm_mode test-dlopen compilation succeeded"
       echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ./test-dlopen.plain > /dev/null 2>&1
@@ -81,6 +82,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
       CODE=1
     }
     rm -f test-dlopen.plain test-dlopen.plain.0 test-dlopen.plain.1 test-instr.so
+    unset LIBS
   } || {
     $ECHO "$RED[!] llvm_mode shared object with -z defs compilation failed"
     CODE=1
@@ -166,27 +168,6 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
   }
   rm -f test-instr.plain
 
-  # now for the special llvm_mode things
-  test -e ../libLLVMInsTrim.so && {
-    AFL_LLVM_INSTRUMENT=CFG AFL_LLVM_INSTRIM_LOOPHEAD=1 ../afl-clang-fast -o test-instr.instrim ../test-instr.c > /dev/null 2>test.out
-    test -e test-instr.instrim && {
-      TUPLES=`echo 0|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.instrim 2>&1 | grep Captur | awk '{print$3}'`
-      test "$TUPLES" -gt 1 -a "$TUPLES" -lt 5 && {
-        $ECHO "$GREEN[+] llvm_mode InsTrim reported $TUPLES instrumented locations which is fine"
-      } || {
-        $ECHO "$RED[!] llvm_mode InsTrim instrumentation produces weird numbers: $TUPLES"
-        CODE=1
-      }
-      rm -f test-instr.instrim test.out
-    } || {
-      cat test.out
-      $ECHO "$RED[!] llvm_mode InsTrim compilation failed"
-      CODE=1
-    }
-  } || {
-    $ECHO "$YELLOW[-] llvm_mode InsTrim not compiled, cannot test"
-    INCOMPLETE=1
-  }
   AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > test.out 2>&1
   test -e test-compcov.compcov && test_compcov_binary_functionality ./test-compcov.compcov && {
     grep --binary-files=text -Eq " [ 123][0-9][0-9] location| [3-9][0-9] location" test.out && {
diff --git a/test/test-pre.sh b/test/test-pre.sh
index 85ac320b..174f2f7f 100755
--- a/test/test-pre.sh
+++ b/test/test-pre.sh
@@ -71,6 +71,7 @@ unset AFL_HARDEN
 unset AFL_USE_ASAN
 unset AFL_USE_MSAN
 unset AFL_USE_UBSAN
+unset AFL_USE_LSAN
 unset AFL_TMPDIR
 unset AFL_CC
 unset AFL_PRELOAD
diff --git a/unicorn_mode/helper_scripts/ida_context_loader.py b/unicorn_mode/helper_scripts/ida_context_loader.py
index 31d47a90..d7984c77 100644
--- a/unicorn_mode/helper_scripts/ida_context_loader.py
+++ b/unicorn_mode/helper_scripts/ida_context_loader.py
@@ -34,13 +34,11 @@ import ida_segment
 
 
 class ContextLoaderError(Exception):
-    """Base "catch all" exception for this script
-    """
+    """Base "catch all" exception for this script"""
 
 
 class ArchNotSupportedError(ContextLoaderError):
-    """Exception raised if the input file CPU architecture isn't supported fully
-    """
+    """Exception raised if the input file CPU architecture isn't supported fully"""
 
 
 def parse_mapping_index(filepath: str):
@@ -51,13 +49,16 @@ def parse_mapping_index(filepath: str):
     """
 
     if filepath is None:
-        raise ContextLoaderError('_index.json file was not selected')
+        raise ContextLoaderError("_index.json file was not selected")
 
     try:
-        with open(filepath, 'rb') as _file:
+        with open(filepath, "rb") as _file:
             return json.load(_file)
     except Exception as ex:
-        raise ContextLoaderError('Failed to parse json file {}'.format(filepath)) from ex
+        raise ContextLoaderError(
+            "Failed to parse json file {}".format(filepath)
+        ) from ex
+
 
 def get_input_name():
     """Get the name of the input file
@@ -68,19 +69,21 @@ def get_input_name():
     input_filepath = ida_nalt.get_input_file_path()
     return Path(input_filepath).name
 
+
 def write_segment_bytes(start: int, filepath: str):
-    """"Read data from context file and write it to the IDA segment
+    """ "Read data from context file and write it to the IDA segment
 
     :param start: Start address
     :param filepath: Path to context file
     """
 
-    with open(filepath, 'rb') as _file:
+    with open(filepath, "rb") as _file:
         data = _file.read()
 
     decompressed_data = zlib.decompress(data)
     ida_bytes.put_bytes(start, decompressed_data)
 
+
 def create_segment(context_dir: str, segment: dict, is_be: bool):
     """Create segment in IDA and map in the data from the file
 
@@ -90,23 +93,30 @@ def create_segment(context_dir: str, segment: dict, is_be: bool):
     """
 
     input_name = get_input_name()
-    if Path(segment['name']).name != input_name:
+    if Path(segment["name"]).name != input_name:
         ida_seg = idaapi.segment_t()
-        ida_seg.start_ea = segment['start']
-        ida_seg.end_ea = segment['end']
+        ida_seg.start_ea = segment["start"]
+        ida_seg.end_ea = segment["end"]
         ida_seg.bitness = 1 if is_be else 0
-        if segment['permissions']['r']:
+        if segment["permissions"]["r"]:
             ida_seg.perm |= ida_segment.SEGPERM_READ
-        if segment['permissions']['w']:
+        if segment["permissions"]["w"]:
             ida_seg.perm |= ida_segment.SEGPERM_WRITE
-        if segment['permissions']['x']:
+        if segment["permissions"]["x"]:
             ida_seg.perm |= ida_segment.SEGPERM_EXEC
-            idaapi.add_segm_ex(ida_seg, Path(segment['name']).name, 'CODE', idaapi.ADDSEG_OR_DIE)
+            idaapi.add_segm_ex(
+                ida_seg, Path(segment["name"]).name, "CODE", idaapi.ADDSEG_OR_DIE
+            )
         else:
-            idaapi.add_segm_ex(ida_seg, Path(segment['name']).name, 'DATA', idaapi.ADDSEG_OR_DIE)
+            idaapi.add_segm_ex(
+                ida_seg, Path(segment["name"]).name, "DATA", idaapi.ADDSEG_OR_DIE
+            )
+
+    if segment["content_file"]:
+        write_segment_bytes(
+            segment["start"], PurePath(context_dir, segment["content_file"])
+        )
 
-    if segment['content_file']:
-        write_segment_bytes(segment['start'], PurePath(context_dir, segment['content_file']))
 
 def create_segments(index: dict, context_dir: str):
     """Iterate segments in index JSON, create the segment in IDA, and map in the data from the file
@@ -117,9 +127,10 @@ def create_segments(index: dict, context_dir: str):
 
     info = idaapi.get_inf_structure()
     is_be = info.is_be()
-    for segment in index['segments']:
+    for segment in index["segments"]:
         create_segment(context_dir, segment, is_be)
 
+
 def rebase_program(index: dict):
     """Rebase the program to the offset specified in the context _index.json
 
@@ -128,20 +139,21 @@ def rebase_program(index: dict):
 
     input_name = get_input_name()
     new_base = None
-    for segment in index['segments']:
-        if not segment['name']:
+    for segment in index["segments"]:
+        if not segment["name"]:
             continue
 
-        segment_name = Path(segment['name']).name
+        segment_name = Path(segment["name"]).name
         if input_name == segment_name:
-            new_base = segment['start']
+            new_base = segment["start"]
             break
 
     if not new_base:
-        raise ContextLoaderError('Input file is not in _index.json')
+        raise ContextLoaderError("Input file is not in _index.json")
 
     current_base = idaapi.get_imagebase()
-    ida_segment.rebase_program(new_base-current_base, 8)
+    ida_segment.rebase_program(new_base - current_base, 8)
+
 
 def get_pc_by_arch(index: dict) -> int:
     """Queries the input file CPU architecture and attempts to lookup the address of the program
@@ -153,13 +165,14 @@ def get_pc_by_arch(index: dict) -> int:
 
     progctr = None
     info = idaapi.get_inf_structure()
-    if info.procname == 'metapc':
+    if info.procname == "metapc":
         if info.is_64bit():
-            progctr = index['regs']['rax']
+            progctr = index["regs"]["rax"]
         elif info.is_32bit():
-            progctr = index['regs']['eax']
+            progctr = index["regs"]["eax"]
     return progctr
 
+
 def write_reg_info(index: dict):
     """Write register info as line comment at instruction pointed to by the program counter and
     change focus to that location
@@ -167,17 +180,19 @@ def write_reg_info(index: dict):
     :param index: _index.json JSON data
     """
 
-    cmt = ''
-    for reg, val in index['regs'].items():
+    cmt = ""
+    for reg, val in index["regs"].items():
         cmt += f"{reg.ljust(6)} : {hex(val)}\n"
 
     progctr = get_pc_by_arch(index)
     if progctr is None:
         raise ArchNotSupportedError(
-            'Architecture not fully supported, skipping register status comment')
+            "Architecture not fully supported, skipping register status comment"
+        )
     ida_bytes.set_cmt(progctr, cmt, 0)
     ida_kernwin.jumpto(progctr)
 
+
 def main(filepath):
     """Main - parse _index.json input and map context files into the database
 
@@ -193,5 +208,6 @@ def main(filepath):
     except ContextLoaderError as ex:
         print(ex)
 
-if __name__ == '__main__':
-    main(ida_kernwin.ask_file(1, '*.json', 'Import file name'))
+
+if __name__ == "__main__":
+    main(ida_kernwin.ask_file(1, "*.json", "Import file name"))
diff --git a/utils/afl_frida/afl-frida.c b/utils/afl_frida/afl-frida.c
index 711d8f33..e49d6f42 100644
--- a/utils/afl_frida/afl-frida.c
+++ b/utils/afl_frida/afl-frida.c
@@ -111,7 +111,7 @@ inline static void afl_maybe_log(guint64 current_pc) {
 
 }
 
-#if GUM_NATIVE_CPU == GUM_CPU_AMD64
+#ifdef __x86_64__
 
 static const guint8 afl_maybe_log_code[] = {
 
@@ -177,7 +177,7 @@ void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output,
       if (instr->address >= range->code_start &&
           instr->address <= range->code_end) {
 
-#if GUM_NATIVE_CPU == GUM_CPU_AMD64
+#ifdef __x86_64__
         GumX86Writer *cw = output->writer.x86;
         if (range->current_log_impl == 0 ||
             !gum_x86_writer_can_branch_directly_between(
diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c
index 0dfae658..60f174ee 100644
--- a/utils/afl_network_proxy/afl-network-server.c
+++ b/utils/afl_network_proxy/afl-network-server.c
@@ -45,7 +45,6 @@
 
 #include <sys/wait.h>
 #include <sys/time.h>
-#include <sys/shm.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/resource.h>
@@ -53,7 +52,9 @@
 #include <netinet/ip6.h>
 #include <arpa/inet.h>
 #include <sys/mman.h>
-#include <sys/shm.h>
+#ifndef USEMMAP
+  #include <sys/shm.h>
+#endif
 #include <sys/socket.h>
 #include <netdb.h>
 
diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile
index c1a087d7..8ac054a6 100644
--- a/utils/aflpp_driver/GNUmakefile
+++ b/utils/aflpp_driver/GNUmakefile
@@ -26,17 +26,17 @@ debug:
 	ar ru libAFLDriver.a afl-performance.o aflpp_driver.o
 
 aflpp_qemu_driver.o:	aflpp_qemu_driver.c
-	$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c
+	-$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c
 
 libAFLQemuDriver.a:	aflpp_qemu_driver.o
-	ar ru libAFLQemuDriver.a aflpp_qemu_driver.o
-	cp -vf libAFLQemuDriver.a ../../
+	-ar ru libAFLQemuDriver.a aflpp_qemu_driver.o
+	-cp -vf libAFLQemuDriver.a ../../
 
 aflpp_qemu_driver_hook.so:	aflpp_qemu_driver_hook.o
-	$(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so
+	-$(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so
 
 aflpp_qemu_driver_hook.o:	aflpp_qemu_driver_hook.c
-	$(LLVM_BINDIR)clang -fPIC $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c
+	-$(LLVM_BINDIR)clang -fPIC $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c
 
 test:	debug
 	#clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c
diff --git a/utils/aflpp_driver/README.md b/utils/aflpp_driver/README.md
new file mode 100644
index 00000000..01bd10c0
--- /dev/null
+++ b/utils/aflpp_driver/README.md
@@ -0,0 +1,30 @@
+# afl++ drivers
+
+## aflpp_driver
+
+aflpp_driver is used to compile directly libfuzzer `LLVMFuzzerTestOneInput()`
+targets.
+
+Just do `afl-clang-fast++ -o fuzz fuzzer_harness.cc libAFLDriver.a [plus required linking]`.
+
+You can also sneakily do this little trick: 
+If this is the clang compile command to build for libfuzzer:
+  `clang++ -o fuzz -fsanitize=fuzzer fuzzer_harness.cc -lfoo`
+then just switch `clang++` with `afl-clang-fast++` and our compiler will
+magically insert libAFLDriver.a :)
+
+
+## aflpp_qemu_driver
+
+aflpp_qemu_driver is used for libfuzzer `LLVMFuzzerTestOneInput()` targets that
+are to be fuzzed in qemu_mode. So we compile them with clang/clang++, without
+-fsantize=fuzzer or afl-clang-fast, and link in libAFLQemuDriver.a:
+
+`clang++ -o fuzz fuzzer_harness.cc libAFLQemuDriver.a [plus required linking]`.
+
+
+Then just do (where the name of the binary is `fuzz`):
+```
+AFL_QEMU_PERSISTENT_ADDR=0x$(nm fuzz | grep "T LLVMFuzzerTestOneInput" | awk '{print $1}')
+AFL_QEMU_PERSISTENT_HOOK=/path/to/aflpp_qemu_driver_hook.so afl-fuzz -Q ... -- ./fuzz`
+```
diff --git a/utils/aflpp_driver/aflpp_qemu_driver_hook.c b/utils/aflpp_driver/aflpp_qemu_driver_hook.c
index 823cc42d..d3dd98b0 100644
--- a/utils/aflpp_driver/aflpp_qemu_driver_hook.c
+++ b/utils/aflpp_driver/aflpp_qemu_driver_hook.c
@@ -1,21 +1,30 @@
+#include "../../qemu_mode/qemuafl/qemuafl/api.h"
+
 #include <stdint.h>
 #include <string.h>
 
+void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
+                         uint8_t *input_buf, uint32_t input_buf_len) {
+
 #define g2h(x) ((void *)((unsigned long)(x) + guest_base))
+#define h2g(x) ((uint64_t)(x)-guest_base)
 
-#define REGS_RDI 7
-#define REGS_RSI 6
+  // In this example the register RDI is pointing to the memory location
+  // of the target buffer, and the length of the input is in RSI.
+  // This can be seen with a debugger, e.g. gdb (and "disass main")
 
-void afl_persistent_hook(uint64_t *regs, uint64_t guest_base,
-                         uint8_t *input_buf, uint32_t input_len) {
+  memcpy(g2h(regs->rdi), input_buf, input_buf_len);
+  regs->rsi = input_buf_len;
 
-  memcpy(g2h(regs[REGS_RDI]), input_buf, input_len);
-  regs[REGS_RSI] = input_len;
+#undef g2h
+#undef h2g
 
 }
 
 int afl_persistent_hook_init(void) {
 
+  // 1 for shared memory input (faster), 0 for normal input (you have to use
+  // read(), input_buf will be NULL)
   return 1;
 
 }
diff --git a/utils/autodict_ql/autodict-ql.py b/utils/autodict_ql/autodict-ql.py
new file mode 100644
index 00000000..f64e3fae
--- /dev/null
+++ b/utils/autodict_ql/autodict-ql.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+# AutoDict-QL - Optimal Token Generation for Fuzzing
+# Part of AFL++ Project
+# Developed and Maintained by Arash Ale Ebrahim (@Microsvuln)
+# Usage : python3 autodict-ql.py [CURRECT_DIR] [CODEQL_DATABASE_PATH] [TOKEN_PATH]
+# CURRENT_DIR = full of your current Dir
+# CODEQL_DATABASE_PATH = Full path to your CodeQL database
+# TOKEN_PATH = Folder name of the newly generated tokens
+# Example : python3 autodict-ql.py /home/user/libxml/automate /home/user/libxml/libxml-db tokens
+# Just pass the tokens folder to the -x flag of your fuzzer
+
+import os
+import string
+import binascii
+import codecs
+import errno
+import struct
+import argparse
+import shutil
+import subprocess
+
+from binascii import unhexlify
+
+
+def ensure_dir(dir):
+    try:
+        os.makedirs(dir)
+    except OSError as e:
+        if e.errno != errno.EEXIST:
+            raise
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description=(
+            "Helper - Specify input file analysis and output folder to save corpus for strings in the overall project ---------------------------------------------------------------------------  Example usage : python2 thisfile.py outdir str.txt"
+        )
+    )
+
+    # parser.add_argument("tokenpath",
+    # help="Destination directory for tokens")
+    parser.add_argument("cur", help="Current Path")
+    parser.add_argument("db", help="CodeQL database Path")
+    parser.add_argument("tokenpath", help="Destination directory for tokens")
+
+    return parser.parse_args()
+
+
+def static_analysis(file, file2, cur, db):
+    with open(cur + "/" + file, "w") as f:
+        print(cur + "/" + file)
+        stream = os.popen("codeql query run " + cur + "/" + file2 + " -d " + db)
+        output = stream.read()
+        f.write(output)
+        f.close()
+
+
+def copy_tokens(cur, tokenpath):
+    subprocess.call(
+        ["mv " + cur + "/" + "strcmp-strs/*" + " " + cur + "/" + tokenpath + "/."],
+        shell=True,
+    )
+    subprocess.call(
+        ["mv " + cur + "/" + "strncmp-strs/*" + " " + cur + "/" + tokenpath + "/."],
+        shell=True,
+    )
+    subprocess.call(
+        ["mv " + cur + "/" + "memcmp-strs/*" + " " + cur + "/" + tokenpath + "/."],
+        shell=True,
+    )
+    subprocess.call(
+        ["mv " + cur + "/" + "lits/*" + " " + cur + "/" + tokenpath + "/."], shell=True
+    )
+    subprocess.call(
+        ["mv " + cur + "/" + "strtool-strs/*" + " " + cur + "/" + tokenpath + "/."],
+        shell=True,
+    )
+    subprocess.call(
+        ["rm -rf strcmp-strs memcmp-strs strncmp-strs lits strtool-strs"], shell=True
+    )
+    subprocess.call(["rm *.out"], shell=True)
+    subprocess.call(["find " + tokenpath + " -size 0 -delete"], shell=True)
+
+
+def codeql_analysis(cur, db):
+    static_analysis("litout.out", "litool.ql", cur, db)
+    static_analysis("strcmp-strings.out", "strcmp-str.ql", cur, db)
+    static_analysis("strncmp-strings.out", "strncmp-str.ql", cur, db)
+    static_analysis("memcmp-strings.out", "memcmp-str.ql", cur, db)
+    static_analysis("strtool-strings.out", "strtool.ql", cur, db)
+    start_autodict(0, cur)
+
+
+def start_autodict(tokenpath, cur):
+    command = ["python3", cur + "/litan.py", cur + "/lits/", cur + "/litout.out"]
+    worker1 = subprocess.Popen(command)
+    print(worker1.communicate())
+
+    command1 = [
+        "python3",
+        cur + "/strcmp-strings.py",
+        cur + "/strcmp-strs/",
+        cur + "/strcmp-strings.out",
+    ]
+    worker2 = subprocess.Popen(command1)
+    print(worker2.communicate())
+
+    command2 = [
+        "python3",
+        cur + "/strncmp-strings.py",
+        cur + "/strncmp-strs/",
+        cur + "/strncmp-strings.out",
+    ]
+    worker3 = subprocess.Popen(command2)
+    print(worker3.communicate())
+
+    command5 = [
+        "python3",
+        cur + "/memcmp-strings.py",
+        cur + "/memcmp-strs/",
+        cur + "/memcmp-strings.out",
+    ]
+    worker6 = subprocess.Popen(command5)
+    print(worker6.communicate())
+
+    command8 = [
+        "python3",
+        cur + "/stan-strings.py",
+        cur + "/strtool-strs/",
+        cur + "/strtool-strings.out",
+    ]
+    worker9 = subprocess.Popen(command8)
+    print(worker9.communicate())
+
+
+def main():
+    args = parse_args()
+    ensure_dir(args.tokenpath)
+    # copy_tokens(args.cur, args.tokenpath)
+    codeql_analysis(args.cur, args.db)
+    copy_tokens(args.cur, args.tokenpath)
+    # start_autodict(args.tokenpath, args.cur)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/autodict_ql/build-codeql.sh b/utils/autodict_ql/build-codeql.sh
new file mode 100644
index 00000000..6ae4b362
--- /dev/null
+++ b/utils/autodict_ql/build-codeql.sh
@@ -0,0 +1,17 @@
+cd ~
+if [ -d "codeql-home" ]; then
+    echo "Exist !"
+    exit 1
+fi
+mkdir codeql-home
+cd codeql-home
+git clone https://github.com/github/codeql.git codeql-repo
+git clone https://github.com/github/codeql-go.git
+wget https://github.com/github/codeql-cli-binaries/releases/download/v2.4.6/codeql-linux64.zip
+unzip codeql-linux64.zip 
+mv codeql codeql-cli
+export "PATH=~/codeql-home/codeql-cli/:$PATH"
+echo "export PATH=~/codeql-home/codeql-cli/:$PATH" >> ~/.bashrc
+codeql resolve languages
+codeql resolve qlpacks
+codeql
diff --git a/utils/autodict_ql/litan.py b/utils/autodict_ql/litan.py
new file mode 100644
index 00000000..7033d363
--- /dev/null
+++ b/utils/autodict_ql/litan.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+# Autodict-QL - Optimal token generation for fuzzing
+# Part of AFL++ Project
+# Author : Microsvuln - Arash.vre@gmail.com
+import string
+import os
+import binascii
+import codecs
+import struct
+import errno
+import argparse
+import re
+import base64
+from binascii import unhexlify
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description=(
+            "Helper - Specify input file to analysis and output folder to save corpdirus for constants in the overall project -------  Example usage : python2 thisfile.py outdir o.txt"
+        )
+    )
+    parser.add_argument(
+        "corpdir", help="The path to the corpus directory to generate files."
+    )
+    parser.add_argument(
+        "infile",
+        help="Specify file output of codeql analysis - ex. ooo-hex.txt, analysis take place on this file, example : python2 thisfile.py outdir out.txt",
+    )
+    return parser.parse_args()
+
+
+def ensure_dir(dir):
+    try:
+        os.makedirs(dir)
+    except OSError as e:
+        if e.errno == errno.EEXIST:
+            # print "[-] Directory exists, specify another directory"
+            exit(1)
+
+
+def do_analysis1(corpdir, infile):
+    with open(infile, "rb") as f:
+        lines = f.readlines()[1:]
+        f.close()
+        new_lst = []
+        n = 1
+        for i, num in enumerate(lines):
+            if i != 0:
+                new_lst.append(num)
+                str1 = str(num)
+                print("num is " + str1)
+                str1 = str1.rstrip("\n\n")
+                # str1 = str1.replace("0x","");
+                str1 = str1.replace("|", "")
+                str1 = str1.rstrip("\r\n")
+                str1 = str1.rstrip("\n")
+                str1 = str1.replace(" ", "")
+                # str1 = str1.translate(None, string.punctuation)
+                translator = str.maketrans("", "", string.punctuation)
+                str1 = str1.translate(translator)
+                str1 = str1[1:]
+                str1 = str1[:-1]
+                print("After cleanup : " + str1)
+                if (
+                    (str1 != "0")
+                    and (str1 != "ffffffff")
+                    and (str1 != "fffffffe")
+                    or (len(str1) == 4)
+                    or (len(str1) == 8)
+                ):
+                    print("first : " + str1)
+                    if len(str1) > 8:
+                        str1 = str1[:-1]
+                    elif len(str1) == 5:
+                        str1 = str1 = "0"
+                    try:
+                        # str1 = str1.decode("hex")
+                        with open(corpdir + "/lit-seed{0}".format(n), "w") as file:
+                            str1 = str1.replace("0x", "")
+                            print(str1)
+                            str1 = int(str1, base=16)
+                            str1 = str1.to_bytes(4, byteorder="little")
+                            file.write(str(str1))
+                            file.close()
+                            with open(corpdir + "/lit-seed{0}".format(n), "r") as q:
+                                a = q.readline()
+                                a = a[1:]
+                                print(
+                                    "AFL++ Autodict-QL by Microsvuln : Writing Token :"
+                                    + str(a)
+                                )
+                                q.close()
+                                with open(
+                                    corpdir + "/lit-seed{0}".format(n), "w"
+                                ) as w1:
+                                    w1.write(str(a))
+                                    print("Done!")
+                                    w1.close()
+                    except:
+                        print("Error!")
+                    n = n + 1
+
+
+def main():
+    args = parse_args()
+    ensure_dir(args.corpdir)
+    do_analysis1(args.corpdir, args.infile)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/autodict_ql/litool.ql b/utils/autodict_ql/litool.ql
new file mode 100644
index 00000000..76f429c1
--- /dev/null
+++ b/utils/autodict_ql/litool.ql
@@ -0,0 +1,10 @@
+import cpp
+
+class HexOrOctLiteral extends Literal{
+    HexOrOctLiteral(){
+      (this instanceof HexLiteral) or (this instanceof OctalLiteral)
+    }
+}
+
+from HexOrOctLiteral lit
+select lit.getValueText()
diff --git a/utils/autodict_ql/memcmp-str.ql b/utils/autodict_ql/memcmp-str.ql
new file mode 100644
index 00000000..830c9cac
--- /dev/null
+++ b/utils/autodict_ql/memcmp-str.ql
@@ -0,0 +1,8 @@
+import cpp 
+
+/// function :  memcmp trace
+
+from FunctionCall fucall, Expr size
+where
+    fucall.getTarget().hasName("memcmp")
+select fucall.getArgument(_).getValueText()	
\ No newline at end of file
diff --git a/utils/autodict_ql/memcmp-strings.py b/utils/autodict_ql/memcmp-strings.py
new file mode 100644
index 00000000..270a697c
--- /dev/null
+++ b/utils/autodict_ql/memcmp-strings.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# Autodict-QL - Optimal token generation for fuzzing
+# Part of AFL++ Project
+# Author : Microsvuln - Arash.vre@gmail.com
+
+import os
+import string
+import binascii
+import codecs
+import errno
+import struct
+import argparse
+import re
+from binascii import unhexlify
+
+
+def ensure_dir(dir):
+    try:
+        os.makedirs(dir)
+    except OSError as e:
+        if e.errno != errno.EEXIST:
+            raise
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description=(
+            "Helper - Specify input file analysis and output folder to save corpus for strings in the overall project ---------------------------------------------------------------------------  Example usage : python2 thisfile.py outdir str.txt"
+        )
+    )
+    parser.add_argument(
+        "corpdir", help="The path to the corpus directory to generate strings."
+    )
+    parser.add_argument(
+        "infile",
+        help="Specify file output of codeql analysis - ex. ooo-atr.txt, analysis take place on this file, example : python2 thisfile.py outdir strings.txt",
+    )
+
+    return parser.parse_args()
+
+
+def do_string_analysis(corpdir, infile1):
+    with open(infile1, "r") as f1:
+        lines = f1.readlines()[1:]
+        f1.close()
+        new_lst1 = []
+        n = 1
+        for i, num1 in enumerate(lines):
+            if i != 0:
+                new_lst1.append(num1)
+                # print("num : %s" % num1)
+                str11 = str(num1)
+                str11 = str11.replace("|", "")
+                str11 = str11.replace("\n", "")
+                str11 = str11.lstrip()
+                str11 = str11.rstrip()
+                str11 = str(str11)
+                if (
+                    (" " in str11)
+                    or (")" in str11)
+                    or ("(" in str11)
+                    or ("<" in str11)
+                    or (">" in str11)
+                ):
+                    print("Space / Paranthesis String : %s" % str11)
+                else:
+                    with open(corpdir + "/memcmp-str{0}".format(n), "w") as file:
+                        file.write(str11)
+                        print(
+                            "AFL++ Autodict-QL by Microsvuln : Writing Token : %s"
+                            % str11
+                        )
+                        n = n + 1
+
+
+def main():
+    args = parse_args()
+    ensure_dir(args.corpdir)
+    do_string_analysis(args.corpdir, args.infile)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/autodict_ql/qlpack.yml b/utils/autodict_ql/qlpack.yml
new file mode 100644
index 00000000..28892f24
--- /dev/null
+++ b/utils/autodict_ql/qlpack.yml
@@ -0,0 +1,3 @@
+name: autodict
+version: 0.0.0
+libraryPathDependencies: codeql-cpp
diff --git a/utils/autodict_ql/readme.md b/utils/autodict_ql/readme.md
new file mode 100644
index 00000000..9170f552
--- /dev/null
+++ b/utils/autodict_ql/readme.md
@@ -0,0 +1,100 @@
+# Autodict-QL - Optimal Token Generation for Fuzzing
+
+## What is this?
+
+`Autodict-QL` is a plugin system that enables fast generation of Tokens/Dictionaries in a handy way that can be manipulated by the user (unlike The LLVM Passes that are hard to modify). This means that autodict-ql is a scriptable feature which basically uses CodeQL (a powerful semantic code analysis engine) to fetch information from a code base.
+
+Tokens are useful when you perform fuzzing on different parsers. The AFL++ `-x` switch enables the usage of dictionaries through your fuzzing campaign. If you are not familiar with Dictionaries in fuzzing, take a look [here](https://github.com/AFLplusplus/AFLplusplus/tree/stable/dictionaries) .
+
+
+## Why CodeQL ?
+We basically developed this plugin on top of the CodeQL engine because it gives the user scripting features, it's easier and it's independent of the LLVM system. This means that a user can write his CodeQL scripts or modify the current scripts to improve or change the token generation algorithms based on different program analysis concepts.
+
+
+## CodeQL scripts
+Currently, we pushed some scripts as defaults for Token generation. In addition, we provide every CodeQL script as an standalone script because it's easier to modify or test.
+
+Currently we provided the following CodeQL scripts :
+
+`strcmp-str.ql` is used to extract strings that are related to the `strcmp` function.
+
+`strncmp-str.ql` is used to extract the strings from the `strncmp` function.
+
+`memcmp-str.ql` is used to extract the strings from the `memcmp` function.
+
+`litool.ql` extracts Magic numbers as Hexadecimal format.
+
+`strtool.ql` extracts strings with uses of a regex and dataflow concept to capture the string comparison functions. If `strcmp` is rewritten in a project as Mystrcmp or something like strmycmp, then this script can catch the arguments and these are valuable tokens.
+
+You can write other CodeQL scripts to extract possible effective tokens if you think they can be useful.
+
+
+## Usage
+
+Before you proceed to installation make sure that you have the following packages by installing them :
+```shell
+sudo apt install build-essential libtool-bin python3-dev python3 automake git vim wget -y
+```
+The usage of Autodict-QL is pretty easy. But let's describe it as:
+
+1. First of all, you need to have CodeQL installed on the system. we make this possible with `build-codeql.sh` bash script. This script will install CodeQL completety and will set the required environment variables for your system.
+Do the following :
+```shell
+# chmod +x codeql-build.sh
+# ./codeql-build.sh
+# source ~/.bashrc
+# codeql 
+```
+Then you should get:
+
+```shell
+Usage: codeql <command> <argument>...
+Create and query CodeQL databases, or work with the QL language.
+
+GitHub makes this program freely available for the analysis of open-source software and certain other uses, but it is
+not itself free software. Type codeql --license to see the license terms.
+
+      --license              Show the license terms for the CodeQL toolchain.
+Common options:
+  -h, --help                 Show this help text.
+  -v, --verbose              Incrementally increase the number of progress messages printed.
+  -q, --quiet                Incrementally decrease the number of progress messages printed.
+Some advanced options have been hidden; try --help -v for a fuller view.
+Commands:
+  query     Compile and execute QL code.
+  bqrs      Get information from .bqrs files.
+  database  Create, analyze and process CodeQL databases.
+  dataset   [Plumbing] Work with raw QL datasets.
+  test      Execute QL unit tests.
+  resolve   [Deep plumbing] Helper commands to resolve disk locations etc.
+  execute   [Deep plumbing] Low-level commands that need special JVM options.
+  version   Show the version of the CodeQL toolchain.
+  generate  Generate formatted QL documentation.
+  github    Commands useful for interacting with the GitHub API through CodeQL.
+```
+
+2. Compile your project with CodeQL: For using the Autodict-QL plugin, you need to compile the source of the target you want to fuzz with CodeQL. This is not something hard.
+	- First you need to create a CodeQL database of the project codebase, suppose we want to compile `libxml` with codeql. Go to libxml and issue the following commands:
+		- `./configure --disable-shared`
+		- `codeql create database libxml-db --language=cpp --command=make`
+			- Now you have the CodeQL database of the project :-)
+3. The final step is to update the CodeQL database you created in step 2 (Suppose we are in `aflplusplus/utils/autodict_ql/` directory):
+	- `codeql database upgrade /home/user/libxml/libxml-db`
+4. Everything is set! Now you should issue the following to get the tokens:
+	- `python3 autodict-ql.py [CURRECT_DIR] [CODEQL_DATABASE_PATH] [TOKEN_PATH]`
+		- example : `python3 /home/user/AFLplusplus/utils/autodict_ql/autodict-ql.py $PWD /home/user/libxml/libxml-db tokens`
+			- This will create the final `tokens` dir for you and you are done, then pass the tokens path to AFL++'s `-x` flag.
+5. Done! 
+
+
+## More on dictionaries and tokens
+Core developer of the AFL++ project Marc Heuse also developed a similar tool named `dict2file` which is a LLVM pass which can automatically extract useful tokens, in addition with LTO instrumentation mode, this dict2file is automatically generates token extraction. `Autodict-QL` plugin gives you scripting capability and you can do whatever you want to extract from the Codebase and it's up to you. In addition it's independent from LLVM system.
+On the other hand, you can also use Google dictionaries which have been made public in May 2020, but the problem of using Google dictionaries is that they are limited to specific file formats and specifications. For example, for testing binutils and ELF file format or AVI in FFMPEG, there are no prebuilt dictionaries, so it is highly recommended to use `Autodict-QL` or `Dict2File` features to automatically generate dictionaries based on the target.
+
+I've personally prefered to use `Autodict-QL` or `dict2file` rather than Google dictionaries or any other manually generated dictionaries as `Autodict-QL` and `dict2file` are working based on the target.
+In overall, fuzzing with dictionaries and well-generated tokens will give better results.
+
+There are 2 important points to remember :
+
+- If you combine `Autodict-QL` with AFL++ cmplog, you will get much better code coverage and hence better chances to discover new bugs.
+- Do not forget to set `AFL_MAX_DET_EXTRAS` at least to the number of generated dictionaries. If you forget to set this environment variable, then AFL++ uses just 200 tokens and use the rest of them only probabilistically. So this will guarantee that your tokens will be used by AFL++.
diff --git a/utils/autodict_ql/stan-strings.py b/utils/autodict_ql/stan-strings.py
new file mode 100644
index 00000000..81cb0b97
--- /dev/null
+++ b/utils/autodict_ql/stan-strings.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# Autodict-QL - Optimal token generation for fuzzing
+# Part of AFL++ Project
+# Author : Microsvuln - Arash.vre@gmail.com
+
+import os
+import string
+import binascii
+import codecs
+import errno
+import struct
+import argparse
+import re
+from binascii import unhexlify
+
+
+def ensure_dir(dir):
+    try:
+        os.makedirs(dir)
+    except OSError as e:
+        if e.errno != errno.EEXIST:
+            raise
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description=(
+            "Helper - Specify input file analysis and output folder to save corpus for strings in the overall project ---------------------------------------------------------------------------  Example usage : python2 thisfile.py outdir str.txt"
+        )
+    )
+    parser.add_argument(
+        "corpdir", help="The path to the corpus directory to generate strings."
+    )
+    parser.add_argument(
+        "infile",
+        help="Specify file output of codeql analysis - ex. ooo-atr.txt, analysis take place on this file, example : python2 thisfile.py outdir strings.txt",
+    )
+
+    return parser.parse_args()
+
+
+def do_string_analysis(corpdir, infile1):
+    with open(infile1, "r") as f1:
+        lines = f1.readlines()[1:]
+        f1.close()
+        new_lst1 = []
+        n = 1
+        for i, num1 in enumerate(lines):
+            if i != 0:
+                new_lst1.append(num1)
+                # print("num : %s" % num1)
+                str11 = str(num1)
+                str11 = str11.replace("|", "")
+                str11 = str11.replace("\n", "")
+                str11 = str11.lstrip()
+                str11 = str11.rstrip()
+                str11 = str(str11)
+                if (
+                    (" " in str11)
+                    or (")" in str11)
+                    or ("(" in str11)
+                    or ("<" in str11)
+                    or (">" in str11)
+                ):
+                    print("Space / Paranthesis String : %s" % str11)
+                else:
+                    with open(corpdir + "/seed-str{0}".format(n), "w") as file:
+                        file.write(str11)
+                        print(
+                            "AFL++ Autodict-QL by Microsvuln : Writing Token : %s"
+                            % str11
+                        )
+                        n = n + 1
+
+
+def main():
+    args = parse_args()
+    ensure_dir(args.corpdir)
+    do_string_analysis(args.corpdir, args.infile)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/autodict_ql/strcmp-str.ql b/utils/autodict_ql/strcmp-str.ql
new file mode 100644
index 00000000..83ffadaf
--- /dev/null
+++ b/utils/autodict_ql/strcmp-str.ql
@@ -0,0 +1,8 @@
+import cpp 
+
+/// function : strcmp
+
+from FunctionCall fucall, Expr size
+where
+    fucall.getTarget().hasName("strcmp")
+select fucall.getArgument(_).getValueText()
\ No newline at end of file
diff --git a/utils/autodict_ql/strcmp-strings.py b/utils/autodict_ql/strcmp-strings.py
new file mode 100644
index 00000000..9c2520c9
--- /dev/null
+++ b/utils/autodict_ql/strcmp-strings.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# Autodict-QL - Optimal token generation for fuzzing
+# Part of AFL++ Project
+# Author : Microsvuln - Arash.vre@gmail.com
+
+import os
+import string
+import binascii
+import codecs
+import errno
+import struct
+import argparse
+import re
+from binascii import unhexlify
+
+
+def ensure_dir(dir):
+    try:
+        os.makedirs(dir)
+    except OSError as e:
+        if e.errno != errno.EEXIST:
+            raise
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description=(
+            "Helper - Specify input file analysis and output folder to save corpus for strings in the overall project ---------------------------------------------------------------------------  Example usage : python2 thisfile.py outdir str.txt"
+        )
+    )
+    parser.add_argument(
+        "corpdir", help="The path to the corpus directory to generate strings."
+    )
+    parser.add_argument(
+        "infile",
+        help="Specify file output of codeql analysis - ex. ooo-atr.txt, analysis take place on this file, example : python2 thisfile.py outdir strings.txt",
+    )
+
+    return parser.parse_args()
+
+
+def do_string_analysis(corpdir, infile1):
+    with open(infile1, "r") as f1:
+        lines = f1.readlines()[1:]
+        f1.close()
+        new_lst1 = []
+        n = 1
+        for i, num1 in enumerate(lines):
+            if i != 0:
+                new_lst1.append(num1)
+                # print("num : %s" % num1)
+                str11 = str(num1)
+                str11 = str11.replace("|", "")
+                str11 = str11.replace("\n", "")
+                str11 = str11.lstrip()
+                str11 = str11.rstrip()
+                str11 = str(str11)
+                if (
+                    (" " in str11)
+                    or (")" in str11)
+                    or ("(" in str11)
+                    or ("<" in str11)
+                    or (">" in str11)
+                ):
+                    print("Space / Paranthesis String : %s" % str11)
+                else:
+                    with open(corpdir + "/strcmp-str{0}".format(n), "w") as file:
+                        file.write(str11)
+                        print(
+                            "AFL++ Autodict-QL by Microsvuln : Writing Token : %s"
+                            % str11
+                        )
+                        n = n + 1
+
+
+def main():
+    args = parse_args()
+    ensure_dir(args.corpdir)
+    do_string_analysis(args.corpdir, args.infile)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/autodict_ql/strncmp-str.ql b/utils/autodict_ql/strncmp-str.ql
new file mode 100644
index 00000000..dbb952e5
--- /dev/null
+++ b/utils/autodict_ql/strncmp-str.ql
@@ -0,0 +1,8 @@
+import cpp 
+
+/// function : strncmp
+
+from FunctionCall fucall, Expr size
+where
+    fucall.getTarget().hasName("strncmp")
+select fucall.getArgument(_).getValueText()
\ No newline at end of file
diff --git a/utils/autodict_ql/strncmp-strings.py b/utils/autodict_ql/strncmp-strings.py
new file mode 100644
index 00000000..6206b4c4
--- /dev/null
+++ b/utils/autodict_ql/strncmp-strings.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# Autodict-QL - Optimal token generation for fuzzing
+# Part of AFL++ Project
+# Author : Microsvuln - Arash.vre@gmail.com
+
+import os
+import string
+import binascii
+import codecs
+import errno
+import struct
+import argparse
+import re
+from binascii import unhexlify
+
+
+def ensure_dir(dir):
+    try:
+        os.makedirs(dir)
+    except OSError as e:
+        if e.errno != errno.EEXIST:
+            raise
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description=(
+            "Helper - Specify input file analysis and output folder to save corpus for strings in the overall project ---------------------------------------------------------------------------  Example usage : python2 thisfile.py outdir str.txt"
+        )
+    )
+    parser.add_argument(
+        "corpdir", help="The path to the corpus directory to generate strings."
+    )
+    parser.add_argument(
+        "infile",
+        help="Specify file output of codeql analysis - ex. ooo-atr.txt, analysis take place on this file, example : python2 thisfile.py outdir strings.txt",
+    )
+
+    return parser.parse_args()
+
+
+def do_string_analysis(corpdir, infile1):
+    with open(infile1, "r") as f1:
+        lines = f1.readlines()[1:]
+        f1.close()
+        new_lst1 = []
+        n = 1
+        for i, num1 in enumerate(lines):
+            if i != 0:
+                new_lst1.append(num1)
+                # print("num : %s" % num1)
+                str11 = str(num1)
+                str11 = str11.replace("|", "")
+                str11 = str11.replace("\n", "")
+                str11 = str11.lstrip()
+                str11 = str11.rstrip()
+                str11 = str(str11)
+                if (
+                    (" " in str11)
+                    or (")" in str11)
+                    or ("(" in str11)
+                    or ("<" in str11)
+                    or (">" in str11)
+                ):
+                    print("Space / Paranthesis String : %s" % str11)
+                else:
+                    with open(corpdir + "/strncmp-str{0}".format(n), "w") as file:
+                        file.write(str11)
+                        print(
+                            "AFL++ Autodict-QL by Microsvuln : Writing Token : %s"
+                            % str11
+                        )
+                        n = n + 1
+
+
+def main():
+    args = parse_args()
+    ensure_dir(args.corpdir)
+    do_string_analysis(args.corpdir, args.infile)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/autodict_ql/strtool.ql b/utils/autodict_ql/strtool.ql
new file mode 100644
index 00000000..253d1555
--- /dev/null
+++ b/utils/autodict_ql/strtool.ql
@@ -0,0 +1,24 @@
+import cpp
+import semmle.code.cpp.dataflow.DataFlow
+class StringLiteralNode extends DataFlow::Node {
+  StringLiteralNode() { this.asExpr() instanceof StringLiteral }
+}
+class CmpArgNode extends DataFlow::Node {
+   CmpArgNode() {
+    exists(FunctionCall fc |
+      fc.getTarget().getName().regexpMatch(".*(str|mem|strn|b)*(cmp|str)*") and
+      fc.getArgument(0) = this.asExpr() 
+    )
+ or
+    exists(FunctionCall fc |
+      fc.getTarget().getName().regexpMatch(".*(str|mem|strn|b)*(cmp|str)*") and
+      fc.getArgument(1) = this.asExpr()
+    )
+  }
+}
+
+from StringLiteralNode src, CmpArgNode arg
+where
+  DataFlow::localFlow(src, arg)
+
+select src.asExpr().(StringLiteral).toString()
\ No newline at end of file
diff --git a/utils/crash_triage/triage_crashes.sh b/utils/crash_triage/triage_crashes.sh
index a752458d..4d75430e 100755
--- a/utils/crash_triage/triage_crashes.sh
+++ b/utils/crash_triage/triage_crashes.sh
@@ -90,12 +90,15 @@ for crash in $DIR/crashes/id:*; do
 
   for a in $@; do
 
-    if [ "$a" = "@@" ] ; then
-      use_args="$use_args $crash"
+    case "$a" in
+      *@@*)
       unset use_stdio
-    else
+      use_args="$use_args `printf %s "$a" | sed -e 's<@@<'$crash'<g'`"
+      ;;
+      *)
       use_args="$use_args $a"
-    fi
+      ;;
+    esac
 
   done
 
diff --git a/utils/qemu_persistent_hook/read_into_rdi.c b/utils/qemu_persistent_hook/read_into_rdi.c
index f4a8ae59..c1c6642f 100644
--- a/utils/qemu_persistent_hook/read_into_rdi.c
+++ b/utils/qemu_persistent_hook/read_into_rdi.c
@@ -5,7 +5,7 @@
 
 void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
                          uint8_t *input_buf, uint32_t input_buf_len) {
-\
+
 #define g2h(x) ((void *)((unsigned long)(x) + guest_base))
 #define h2g(x) ((uint64_t)(x)-guest_base)