about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile30
-rw-r--r--GNUmakefile.gcc_plugin4
-rw-r--r--GNUmakefile.llvm14
-rw-r--r--README.md2
-rw-r--r--TODO.md2
-rw-r--r--docs/Changelog.md6
-rw-r--r--docs/INSTALL.md4
-rw-r--r--docs/env_variables.md7
-rw-r--r--docs/fuzzing_binary-only_targets.md9
-rw-r--r--docs/fuzzing_in_depth.md22
-rw-r--r--frida_mode/README.md32
-rw-r--r--frida_mode/frida.map3
-rw-r--r--frida_mode/include/instrument.h11
-rw-r--r--frida_mode/include/module.h11
-rw-r--r--frida_mode/include/util.h8
-rw-r--r--frida_mode/src/instrument/instrument.c14
-rw-r--r--frida_mode/src/instrument/instrument_arm32.c34
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c32
-rw-r--r--frida_mode/src/instrument/instrument_x64.c542
-rw-r--r--frida_mode/src/instrument/instrument_x64_cache.c435
-rw-r--r--frida_mode/src/instrument/instrument_x86.c33
-rw-r--r--frida_mode/src/js/api.js22
-rw-r--r--frida_mode/src/js/js_api.c20
-rw-r--r--frida_mode/src/main.c3
-rw-r--r--frida_mode/src/module.c106
-rw-r--r--frida_mode/src/ranges.c2
-rw-r--r--frida_mode/test/cache/GNUmakefile97
-rw-r--r--frida_mode/test/cache/Makefile22
-rw-r--r--frida_mode/test/cache/cache.c115
-rw-r--r--frida_mode/test/cmov/GNUmakefile87
-rw-r--r--frida_mode/test/cmov/Makefile19
-rw-r--r--frida_mode/test/cmov/cmov.c122
-rw-r--r--frida_mode/test/python/GNUmakefile37
-rw-r--r--frida_mode/test/python/Makefile17
-rw-r--r--frida_mode/test/vorbis/GNUmakefile8
-rw-r--r--frida_mode/ts/lib/afl.ts37
-rw-r--r--include/envs.h3
-rw-r--r--include/forkserver.h3
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc168
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc205
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc79
-rw-r--r--instrumentation/afl-llvm-lto-instrumentlist.so.cc50
-rw-r--r--instrumentation/afl-llvm-pass.so.cc95
-rw-r--r--instrumentation/cmplog-instructions-pass.cc95
-rw-r--r--instrumentation/cmplog-routines-pass.cc73
-rw-r--r--instrumentation/cmplog-switches-pass.cc102
-rw-r--r--instrumentation/compare-transform-pass.so.cc120
-rw-r--r--instrumentation/split-compares-pass.so.cc132
-rw-r--r--instrumentation/split-switches-pass.so.cc107
-rw-r--r--nyx_mode/LIBNYX_VERSION2
-rw-r--r--nyx_mode/PACKER_VERSION2
m---------nyx_mode/QEMU-Nyx0
-rw-r--r--nyx_mode/QEMU_NYX_VERSION2
-rw-r--r--nyx_mode/custom_harness/example.c7
m---------nyx_mode/libnyx0
m---------nyx_mode/packer0
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
m---------qemu_mode/qemuafl0
-rw-r--r--qemu_mode/unsigaction/Makefile14
-rw-r--r--src/afl-cc.c215
-rw-r--r--src/afl-common.c3
-rw-r--r--src/afl-forkserver.c11
-rw-r--r--src/afl-fuzz-bitmap.c27
-rw-r--r--src/afl-fuzz-cmplog.c10
-rw-r--r--src/afl-fuzz-redqueen.c6
-rw-r--r--src/afl-fuzz-run.c3
-rw-r--r--src/afl-fuzz.c16
-rw-r--r--src/afl-ld-lto.c5
-rwxr-xr-xtest/test-llvm-lto.sh3
-rwxr-xr-xtest/test-qemu-mode.sh14
-rwxr-xr-xtest/test-unicorn-mode.sh2
-rw-r--r--unicorn_mode/UNICORNAFL_VERSION2
-rwxr-xr-xunicorn_mode/build_unicorn_support.sh3
-rw-r--r--unicorn_mode/samples/compcov_x64/compcov_test_harness.py4
-rw-r--r--unicorn_mode/samples/speedtest/python/harness.py4
m---------unicorn_mode/unicornafl0
76 files changed, 2733 insertions, 825 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 6392fceb..d31c52da 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -76,9 +76,9 @@ else
 endif
 endif
 
-ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
-endif
+#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+#	SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
+#endif
 
 #ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
 #  ifndef SOURCE_DATE_EPOCH
@@ -92,12 +92,10 @@ ifneq "$(SYS)" "Darwin"
   #  SPECIAL_PERFORMANCE += -march=native
   #endif
  # OS X does not like _FORTIFY_SOURCE=2
-  ifndef DEBUG
-    CFLAGS_OPT += -D_FORTIFY_SOURCE=2
-  endif
-endif
-
-ifeq "$(SYS)" "Darwin"
+ ifndef DEBUG
+   CFLAGS_OPT += -D_FORTIFY_SOURCE=2
+ endif
+else
   # On some odd MacOS system configurations, the Xcode sdk path is not set correctly
   SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
   LDFLAGS += $(SDK_LD)
@@ -144,12 +142,13 @@ ifdef DEBUG
   $(info Compiling DEBUG version of binaries)
   override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
 else
-  CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
+  CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers
 endif
 
 override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
 			-fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-			  -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
+			-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
+# -fstack-protector
 
 ifeq "$(SYS)" "FreeBSD"
   override CFLAGS  += -I /usr/local/include/
@@ -175,7 +174,7 @@ ifeq "$(SYS)" "Haiku"
   SHMAT_OK=0
   override CFLAGS  += -DUSEMMAP=1 -Wno-error=format
   override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
-  SPECIAL_PERFORMANCE += -DUSEMMAP=1
+  #SPECIAL_PERFORMANCE += -DUSEMMAP=1
 endif
 
 AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
@@ -247,9 +246,6 @@ else
 endif
 
 ifneq "$(filter Linux GNU%,$(SYS))" ""
- ifndef DEBUG
-  override CFLAGS += -D_FORTIFY_SOURCE=2
- endif
   override LDFLAGS += -ldl -lrt -lm
 endif
 
@@ -426,7 +422,7 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
 	@ln -sf afl-as as
 
 src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
-	$(CC) $(CFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
+	$(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
 
 src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
 	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
@@ -570,7 +566,7 @@ all_done: test_build
 
 .PHONY: clean
 clean:
-	rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM
+	rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
 	-$(MAKE) -f GNUmakefile.llvm clean
 	-$(MAKE) -f GNUmakefile.gcc_plugin clean
 	-$(MAKE) -C utils/libdislocator clean
diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin
index 63b22017..e21203ae 100644
--- a/GNUmakefile.gcc_plugin
+++ b/GNUmakefile.gcc_plugin
@@ -135,11 +135,11 @@ afl-common.o: ./src/afl-common.c
 
 ./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
 	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
-	@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-32.o afl-llvm-rt-32.o; else echo "failed (that's fine)"; fi
+	@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 ./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
 	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
-	@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-64.o afl-llvm-rt-64.o; else echo "failed (that's fine)"; fi
+	@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 ./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps
 	$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index f1de28a4..685964b7 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -394,7 +394,7 @@ endif
 
 ./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
 ifeq "$(LLVM_10_OK)" "1"
-	-$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
+	-$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o
 endif
 
 ./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
@@ -447,11 +447,11 @@ document:
 
 ./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
 	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
-	@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-32.o afl-llvm-rt-32.o; else echo "failed (that's fine)"; fi
+	@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 ./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
 	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
-	@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-64.o afl-llvm-rt-64.o; else echo "failed (that's fine)"; fi
+	@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
 
 .PHONY: test_build
 test_build: $(PROGS)
@@ -474,11 +474,11 @@ install: all
 	@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
 	@if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi
 	@rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt*.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt*.o
-	@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt.o ;fi
+	@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi
 	@if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
 	@if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
-	@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o ;fi
-	@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o ; fi
+	@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
+	@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
 	@if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi
 	@if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi
 	@if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi
@@ -520,4 +520,4 @@ endif
 .PHONY: clean
 clean:
 	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
-	rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-llvm-rt*.o instrumentation/*.o
+	rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-compiler-rt*.o ./afl-llvm-rt*.o instrumentation/*.o
diff --git a/README.md b/README.md
index 66b884e2..a29ce792 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ Step-by-step quick start:
 
 5. You will find found crashes and hangs in the subdirectories `crashes/` and
    `hangs/` in the `-o output_dir` directory. You can replay the crashes by
-   feeding them to the target, e.g.:
+   feeding them to the target, e.g. if your target is using stdin:
 
    ```
    cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]
diff --git a/TODO.md b/TODO.md
index e6b095fc..f3192e10 100644
--- a/TODO.md
+++ b/TODO.md
@@ -29,4 +29,4 @@ QEMU mode/FRIDA mode:
    using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow 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?
\ No newline at end of file
+ - use cmplog colorization taint result for havoc locations?
diff --git a/docs/Changelog.md b/docs/Changelog.md
index f4ae0e43..74631a88 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -12,6 +12,9 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
   - fix */build_...sh scripts to work outside of git
   - new custom_mutator: libafl with token fuzzing :)
   - afl-fuzz:
+    - when you just want to compile once and set CMPLOG, then just
+      set -c 0 to tell afl-fuzz that the fuzzing binary is also for
+      CMPLOG.
     - new commandline options -g/G to set min/max length of generated
       fuzz inputs
     - reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow
@@ -20,6 +23,9 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
     - add AFL_EARY_FORKSERVER to install the forkserver as earliest as
       possible in the target (for afl-gcc-fast/afl-clang-fast/
       afl-clang-lto)
+  - afl-cc:
+    - converted all passed to use the new llvm pass manager for llvm 11+
+    - AFL++ PCGUARD mode is not available for 10.0.1 anymore (11+ only)
   - frida_mode:
     - update to new frida release, handles now c++ throw/catch
 
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index b0090e77..3fa7fd13 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -23,7 +23,7 @@ sudo apt-get update
 sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
 # 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
+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
 sudo apt-get install -y ninja-build # for QEMU mode
 git clone https://github.com/AFLplusplus/AFLplusplus
 cd AFLplusplus
@@ -178,4 +178,4 @@ sysctl kern.sysv.shmall=98304
 
 See
 [http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
-for documentation for these settings and how to make them permanent.
+for documentation for these settings and how to make them permanent.
\ No newline at end of file
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 4626a9b6..edd57fb6 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -518,7 +518,12 @@ checks or alter some of the more exotic semantics of the tool:
     the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
     ... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
     theoretically allow fuzzing of AFL++ itself (with 'target' AFL++ using some
-    AFL_ vars that would disrupt work of 'fuzzer' AFL++).
+    AFL_ vars that would disrupt work of 'fuzzer' AFL++). Note that when using
+    QEMU mode, the `AFL_TARGET_ENV` environment variables will apply to QEMU, as
+    well as the target binary. Therefore, in this case, you might want to use
+    QEMU's `QEMU_SET_ENV` environment variable (see QEMU's documentation because
+    the format is different from `AFL_TARGET_ENV`) to apply the environment
+    variables to the target and not QEMU.
 
   - `AFL_TESTCACHE_SIZE` allows you to override the size of `#define
     TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if
diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md
index 1a2b27c7..c97af1b9 100644
--- a/docs/fuzzing_binary-only_targets.md
+++ b/docs/fuzzing_binary-only_targets.md
@@ -48,11 +48,12 @@ The following setup to use QEMU mode is recommended:
 
 Then run as many instances as you have cores left with either -Q mode or - even
 better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
+The binary rewriters all have their own advantages and caveats.
+ZAFL is the best but cannot be used in a business/commercial context.
 
-If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for your
-binary, then you can use afl-fuzz normally and it will have twice the speed
-compared to QEMU mode (but slower than QEMU persistent mode). Note that several
-other binary rewriters exist, all with their advantages and caveats.
+If a binary rewriter works for your target then you can use afl-fuzz normally
+and it will have twice the speed compared to QEMU mode (but slower than QEMU
+persistent mode).
 
 The speed decrease of QEMU mode is at about 50%. However, various options exist
 to increase the speed:
diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md
index ac72c757..cff00f77 100644
--- a/docs/fuzzing_in_depth.md
+++ b/docs/fuzzing_in_depth.md
@@ -333,6 +333,24 @@ is a non-standard way to set this, otherwise set up the build normally and edit
 the generated build environment afterwards manually to point it to the right
 compiler (and/or `RANLIB` and `AR`).
 
+#### Linker scripts
+
+If the project uses linker scripts to hide the symbols exported by the
+binary, then you may see errors such as:
+
+```
+undefined symbol: __afl_area_ptr
+```
+
+The solution is to modify the linker script to add:
+
+```
+{
+  global:
+    __afl_*;
+}
+```
+
 ### f) Better instrumentation
 
 If you just fuzz a target program as-is, you are wasting a great opportunity for
@@ -817,9 +835,9 @@ Here are some of the most important caveats for AFL++:
 
 - There is no direct support for fuzzing network services, background daemons,
   or interactive apps that require UI interaction to work. You may need to make
-  simple code changes to make them behave in a more traditional way. Preeny may
+  simple code changes to make them behave in a more traditional way. Preeny or libdesock may
   offer a relatively simple option, too - see:
-  [https://github.com/zardus/preeny](https://github.com/zardus/preeny)
+  [https://github.com/zardus/preeny](https://github.com/zardus/preeny) or [https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock)
 
   Some useful tips for modifying network-based services can be also found at:
   [https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)
diff --git a/frida_mode/README.md b/frida_mode/README.md
index e5b46baf..4025dba5 100644
--- a/frida_mode/README.md
+++ b/frida_mode/README.md
@@ -151,31 +151,35 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
 * `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
   and their instrumented counterparts during block compilation.
 
-  ```
-  ***
+Creating block for 0x7ffff7953313:
+        0x7ffff7953313  mov qword ptr [rax], 0
+        0x7ffff795331a  add rsp, 8
+        0x7ffff795331e  ret
 
-  Creating block for 0x7ffff7953313:
-          0x7ffff7953313  mov qword ptr [rax], 0
-          0x7ffff795331a  add rsp, 8
-          0x7ffff795331e  ret
+Generated block 0x7ffff75e98e2
+        0x7ffff75e98e2  mov qword ptr [rax], 0
+        0x7ffff75e98e9  add rsp, 8
+        0x7ffff75e98ed  lea rsp, [rsp - 0x80]
+        0x7ffff75e98f5  push rcx
+        0x7ffff75e98f6  movabs rcx, 0x7ffff795331e
+        0x7ffff75e9900  jmp 0x7ffff75e9384
 
-  Generated block 0x7ffff75e98e2
-          0x7ffff75e98e2  mov qword ptr [rax], 0
-          0x7ffff75e98e9  add rsp, 8
-          0x7ffff75e98ed  lea rsp, [rsp - 0x80]
-          0x7ffff75e98f5  push rcx
-          0x7ffff75e98f6  movabs rcx, 0x7ffff795331e
-          0x7ffff75e9900  jmp 0x7ffff75e9384
 
   ***
   ```
-
+* `AFL_FRIDA_INST_CACHE_SIZE` - Set the size of the instrumentation cache used
+as a look-up table to cache real to instrumented address block translations.
+Default is 256Mb.
+* `AFL_FRIDA_INST_INSN` - Generate instrumentation for conditional
+  instructions (e.g. `CMOV` instructions on x64).
 * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled
   code. Code is considered to be JIT if the executable segment is not backed by
   a file.
 * `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_CACHE` - Don't use a look-up table to cache real to
+instrumented address block translations.
 * `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, implies
diff --git a/frida_mode/frida.map b/frida_mode/frida.map
index d059bdb6..6726dbbd 100644
--- a/frida_mode/frida.map
+++ b/frida_mode/frida.map
@@ -9,12 +9,15 @@
     js_api_done;
     js_api_error;
     js_api_set_backpatch_disable;
+    js_api_set_cache_disable;
     js_api_set_debug_maps;
     js_api_set_entrypoint;
+    js_api_set_instrument_cache_size;
     js_api_set_instrument_coverage_file;
     js_api_set_instrument_debug_file;
     js_api_set_instrument_jit;
     js_api_set_instrument_libraries;
+    js_api_set_instrument_instructions;
     js_api_set_instrument_no_optimize;
     js_api_set_instrument_seed;
     js_api_set_instrument_trace;
diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h
index abb89c9f..4a54ee22 100644
--- a/frida_mode/include/instrument.h
+++ b/frida_mode/include/instrument.h
@@ -12,6 +12,7 @@ extern gboolean instrument_optimize;
 extern gboolean instrument_unique;
 extern guint64  instrument_hash_zero;
 extern char *   instrument_coverage_unstable_filename;
+extern gboolean instrument_coverage_insn;
 
 extern gboolean instrument_use_fixed_seed;
 extern guint64  instrument_fixed_seed;
@@ -21,6 +22,9 @@ extern uint32_t __afl_map_size;
 
 extern __thread guint64 *instrument_previous_pc_addr;
 
+extern gboolean instrument_cache_enabled;
+extern gsize    instrument_cache_size;
+
 void instrument_config(void);
 
 void instrument_init(void);
@@ -33,6 +37,8 @@ gboolean instrument_is_coverage_optimize_supported(void);
 void instrument_coverage_optimize_init(void);
 void instrument_coverage_optimize(const cs_insn *   instr,
                                   GumStalkerOutput *output);
+void instrument_coverage_optimize_insn(const cs_insn *   instr,
+                                       GumStalkerOutput *output);
 
 void     instrument_debug_config(void);
 void     instrument_debug_init(void);
@@ -56,5 +62,10 @@ void instrument_on_fork(void);
 
 guint64 instrument_get_offset_hash(GumAddress current_rip);
 
+void instrument_cache_config(void);
+void instrument_cache_init(void);
+void instrument_cache_insert(gpointer real_address, gpointer code_address);
+void instrument_cache(const cs_insn *instr, GumStalkerOutput *output);
+
 #endif
 
diff --git a/frida_mode/include/module.h b/frida_mode/include/module.h
new file mode 100644
index 00000000..b66f7feb
--- /dev/null
+++ b/frida_mode/include/module.h
@@ -0,0 +1,11 @@
+#ifndef _MODULE_H
+#define _MODULE_H
+
+#include "frida-gumjs.h"
+
+void module_config(void);
+
+void module_init(void);
+
+#endif
+
diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h
index bd37687c..b04e0a26 100644
--- a/frida_mode/include/util.h
+++ b/frida_mode/include/util.h
@@ -5,6 +5,14 @@
 
 #include "debug.h"
 
+#ifndef MAP_FIXED_NOREPLACE
+  #ifdef MAP_EXCL
+    #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
+  #else
+    #define MAP_FIXED_NOREPLACE MAP_FIXED
+  #endif
+#endif
+
 #define UNUSED_PARAMETER(x) (void)(x)
 #define IGNORED_RETURN(x) (void)!(x)
 
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index 418b35e8..003c3d00 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -29,6 +29,7 @@ guint64  instrument_hash_seed = 0;
 gboolean instrument_use_fixed_seed = FALSE;
 guint64  instrument_fixed_seed = 0;
 char *   instrument_coverage_unstable_filename = NULL;
+gboolean instrument_coverage_insn = FALSE;
 
 static GumStalkerTransformer *transformer = NULL;
 
@@ -233,6 +234,12 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
 
     }
 
+    if (instrument_coverage_insn) {
+
+      instrument_coverage_optimize_insn(instr, output);
+
+    }
+
     instrument_debug_instruction(instr->address, instr->size, output);
 
     if (likely(!excluded)) {
@@ -242,6 +249,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
 
     }
 
+    instrument_cache(instr, output);
+
     if (js_stalker_callback(instr, begin, excluded, output)) {
 
       gum_stalker_iterator_keep(iterator);
@@ -269,11 +278,13 @@ void instrument_config(void) {
   instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0);
   instrument_coverage_unstable_filename =
       (getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE"));
+  instrument_coverage_insn = (getenv("AFL_FRIDA_INST_INSN") != NULL);
 
   instrument_debug_config();
   instrument_coverage_config();
   asan_config();
   cmplog_config();
+  instrument_cache_config();
 
 }
 
@@ -294,6 +305,8 @@ void instrument_init(void) {
        instrument_coverage_unstable_filename == NULL
            ? " "
            : instrument_coverage_unstable_filename);
+  FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]",
+       instrument_coverage_insn ? 'X' : ' ');
 
   if (instrument_tracing && instrument_optimize) {
 
@@ -382,6 +395,7 @@ void instrument_init(void) {
   instrument_coverage_init();
   instrument_coverage_optimize_init();
   instrument_debug_init();
+  instrument_cache_init();
 
 }
 
diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c
index 16e8eaab..80f3c26d 100644
--- a/frida_mode/src/instrument/instrument_arm32.c
+++ b/frida_mode/src/instrument/instrument_arm32.c
@@ -5,6 +5,9 @@
 
 #if defined(__arm__)
 
+gboolean instrument_cache_enabled = FALSE;
+gsize    instrument_cache_size = 0;
+
 gboolean instrument_is_coverage_optimize_supported(void) {
 
   return false;
@@ -20,6 +23,15 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
 }
 
+void instrument_coverage_optimize_insn(const cs_insn *   instr,
+                                       GumStalkerOutput *output) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(output);
+  FFATAL("Optimized coverage not supported on this architecture");
+
+}
+
 void instrument_coverage_optimize_init(void) {
 
   FWARNF("Optimized coverage not supported on this architecture");
@@ -46,5 +58,27 @@ gpointer instrument_cur(GumStalkerOutput *output) {
 
 }
 
+void instrument_cache_config(void) {
+
+}
+
+void instrument_cache_init(void) {
+
+}
+
+void instrument_cache_insert(gpointer real_address, gpointer code_address) {
+
+  UNUSED_PARAMETER(real_address);
+  UNUSED_PARAMETER(code_address);
+
+}
+
+void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(output);
+
+}
+
 #endif
 
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index 1a704585..e6251cb4 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -18,6 +18,8 @@
 
 #if defined(__aarch64__)
 
+gboolean instrument_cache_enabled = FALSE;
+gsize    instrument_cache_size = 0;
 static GHashTable *coverage_blocks = NULL;
 
 __attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
@@ -341,6 +343,14 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
 }
 
+void instrument_coverage_optimize_insn(const cs_insn *   instr,
+                                       GumStalkerOutput *output) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(output);
+
+}
+
 void instrument_coverage_optimize_init(void) {
 
   char *shm_env = getenv(SHM_ENV_VAR);
@@ -371,5 +381,27 @@ gpointer instrument_cur(GumStalkerOutput *output) {
 
 }
 
+void instrument_cache_config(void) {
+
+}
+
+void instrument_cache_init(void) {
+
+}
+
+void instrument_cache_insert(gpointer real_address, gpointer code_address) {
+
+  UNUSED_PARAMETER(real_address);
+  UNUSED_PARAMETER(code_address);
+
+}
+
+void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(output);
+
+}
+
 #endif
 
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index fb84d6d2..d54c8353 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -23,13 +23,39 @@
 
 #if defined(__x86_64__)
 
-  #ifndef MAP_FIXED_NOREPLACE
-    #ifdef MAP_EXCL
-      #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
-    #else
-      #define MAP_FIXED_NOREPLACE MAP_FIXED
-    #endif
-  #endif
+enum jcc_opcodes {
+
+  OPC_JO = 0x70,
+  OPC_JNO = 0x71,
+  OPC_JB = 0x72,
+  OPC_JAE = 0x73,
+  OPC_JE = 0x74,
+  OPC_JNE = 0x75,
+  OPC_JBE = 0x76,
+  OPC_JA = 0x77,
+  OPC_JS = 0x78,
+  OPC_JNS = 0x79,
+  OPC_JP = 0x7a,
+  OPC_JNP = 0x7b,
+  OPC_JL = 0x7c,
+  OPC_JGE = 0x7d,
+  OPC_JLE = 0x7e,
+  OPC_JG = 0x7f,
+
+};
+
+typedef union {
+
+  struct {
+
+    uint8_t opcode;
+    uint8_t distance;
+
+  };
+
+  uint8_t bytes[0];
+
+} jcc_insn;
 
 static GHashTable *coverage_blocks = NULL;
 
@@ -45,8 +71,7 @@ static gboolean instrument_coverage_in_range(gssize offset) {
 
 }
 
-  #ifdef __APPLE__
-    #pragma pack(push, 1)
+  #pragma pack(push, 1)
 
 typedef struct {
 
@@ -54,95 +79,28 @@ typedef struct {
   // shared_mem[cur_location ^ prev_location]++;
   // prev_location = cur_location >> 1;
 
-  //  mov    QWORD PTR [rsp-0x80],rax
-  //  lahf
-  //  mov    QWORD PTR [rsp-0x88],rax
-  //  mov    QWORD PTR [rsp-0x90],rbx
-  //  mov    eax,DWORD PTR [rip+0x333d5a]        # 0x7ffff6ff2740
-  //  mov    DWORD PTR [rip+0x333d3c],0x9fbb        # 0x7ffff6ff2740
-  //  lea    rax,[rip + 0x103f77]
-  //  mov    bl,BYTE PTR [rax]
-  //  add    bl,0x1
-  //  adc    bl,0x0
-  //  mov    BYTE PTR [rax],bl
-  //  mov    rbx,QWORD PTR [rsp-0x90]
-  //  mov    rax,QWORD PTR [rsp-0x88]
-  //  sahf
-  //  mov    rax,QWORD PTR [rsp-0x80]
-
-  uint8_t mov_rax_rsp_88[8];
-  uint8_t lahf;
-  uint8_t mov_rax_rsp_90[8];
-  uint8_t mov_rbx_rsp_98[8];
-
-  uint8_t mov_eax_prev_loc[6];
-  uint8_t mov_prev_loc_curr_loc_shr1[10];
-
-  uint8_t leax_eax_curr_loc[7];
+  // mov    QWORD PTR [rsp-0x88],rax
+  // lahf
+  // mov    QWORD PTR [rsp-0x90],rax
+  // mov    QWORD PTR [rsp-0x98],rbx
 
-  uint8_t mov_rbx_ptr_rax[2];
-  uint8_t add_bl_1[3];
-  uint8_t adc_bl_0[3];
-  uint8_t mov_ptr_rax_rbx[2];
+  // mov    eax,DWORD PTR [rip+0x1312334]
+  // xor    eax,0x3f77
 
-  uint8_t mov_rsp_98_rbx[8];
-  uint8_t mov_rsp_90_rax[8];
-  uint8_t sahf;
-  uint8_t mov_rsp_88_rax[8];
+  // lea    rbx,[rip+0x132338]
+  // add    rax,rbx
 
-} afl_log_code_asm_t;
+  // mov    bl,BYTE PTR [rax]
+  // add    bl,0x1
+  // adc    bl,0x0
+  // mov    BYTE PTR [rax],bl
 
-    #pragma pack(pop)
+  // mov    rbx,QWORD PTR [rsp-0x98]
+  // mov    rax,QWORD PTR [rsp-0x90]
+  // sahf
+  // mov    rax,QWORD PTR [rsp-0x88]
 
-static const afl_log_code_asm_t template =
-    {
-
-        .mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
-        .lahf = 0x9f,
-        .mov_rax_rsp_90 = {0x48, 0x89, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
-        .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
-
-        .mov_eax_prev_loc = {0x8b, 0x05},
-        .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
-
-        .leax_eax_curr_loc = {0x48, 0x8d, 0x05},
-        .mov_rbx_ptr_rax = {0x8a, 0x18},
-        .add_bl_1 = {0x80, 0xc3, 0x01},
-        .adc_bl_0 = {0x80, 0xd3, 0x00},
-        .mov_ptr_rax_rbx = {0x88, 0x18},
-
-        .mov_rsp_98_rbx = {0x48, 0x8B, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
-        .mov_rsp_90_rax = {0x48, 0x8B, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
-        .sahf = 0x9e,
-        .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
-
-}
-
-;
-
-  #else
-    #pragma pack(push, 1)
-typedef struct {
-
-  // cur_location = (block_address >> 4) ^ (block_address << 8);
-  // shared_mem[cur_location ^ prev_location]++;
-  // prev_location = cur_location >> 1;
-
-  //  mov    QWORD PTR [rsp-0x80],rax
-  //  lahf
-  //  mov    QWORD PTR [rsp-0x88],rax
-  //  mov    QWORD PTR [rsp-0x90],rbx
-  //  mov    eax,DWORD PTR [rip+0x333d5a]        # 0x7ffff6ff2740
-  //  mov    DWORD PTR [rip+0x333d3c],0x9fbb        # 0x7ffff6ff2740
-  //  xor    eax,0x103f77
-  //  mov    bl,BYTE PTR [rax]
-  //  add    bl,0x1
-  //  adc    bl,0x0
-  //  mov    BYTE PTR [rax],bl
-  //  mov    rbx,QWORD PTR [rsp-0x90]
-  //  mov    rax,QWORD PTR [rsp-0x88]
-  //  sahf
-  //  mov    rax,QWORD PTR [rsp-0x80]
+  // mov    DWORD PTR [rip+0x13122f8],0x9fbb
 
   uint8_t mov_rax_rsp_88[8];
   uint8_t lahf;
@@ -150,10 +108,11 @@ typedef struct {
   uint8_t mov_rbx_rsp_98[8];
 
   uint8_t mov_eax_prev_loc[6];
-  uint8_t mov_prev_loc_curr_loc_shr1[10];
-
   uint8_t xor_eax_curr_loc[5];
 
+  uint8_t lea_rbx_area_ptr[7];
+  uint8_t add_rax_rbx[3];
+
   uint8_t mov_rbx_ptr_rax[2];
   uint8_t add_bl_1[3];
   uint8_t adc_bl_0[3];
@@ -164,9 +123,11 @@ typedef struct {
   uint8_t sahf;
   uint8_t mov_rsp_88_rax[8];
 
+  uint8_t mov_prev_loc_curr_loc_shr1[10];
+
 } afl_log_code_asm_t;
 
-    #pragma pack(pop)
+  #pragma pack(pop)
 
 static const afl_log_code_asm_t template =
     {
@@ -177,9 +138,10 @@ static const afl_log_code_asm_t template =
         .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
 
         .mov_eax_prev_loc = {0x8b, 0x05},
-        .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
-
         .xor_eax_curr_loc = {0x35},
+        .lea_rbx_area_ptr = {0x48, 0x8d, 0x1d},
+        .add_rax_rbx = {0x48, 0x01, 0xd8},
+
         .mov_rbx_ptr_rax = {0x8a, 0x18},
         .add_bl_1 = {0x80, 0xc3, 0x01},
         .adc_bl_0 = {0x80, 0xd3, 0x00},
@@ -190,10 +152,11 @@ static const afl_log_code_asm_t template =
         .sahf = 0x9e,
         .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
 
+        .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
+
 }
 
 ;
-  #endif
 
 typedef union {
 
@@ -202,171 +165,12 @@ typedef union {
 
 } afl_log_code;
 
-  #ifdef __APPLE__
-
 void instrument_coverage_optimize_init(void) {
 
-}
-
-  #else
-
-static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
-                                             gpointer               user_data) {
-
-  static GumAddress last_limit = (64ULL << 10);
-  gpointer *        address = (gpointer *)user_data;
-
-  last_limit = GUM_ALIGN_SIZE(last_limit, __afl_map_size);
-
-  if ((details->range->base_address - last_limit) > __afl_map_size) {
-
-    *address = GSIZE_TO_POINTER(last_limit);
-    return FALSE;
-
-  }
-
-  if (details->range->base_address > ((2ULL << 30) - __afl_map_size)) {
-
-    return FALSE;
-
-  }
-
-  /*
-   * Align our buffer on a 64k boundary so that the low 16-bits of the address
-   * are zero, then we can just XOR the base address in, when we XOR with the
-   * current block ID.
-   */
-  last_limit = GUM_ALIGN_SIZE(
-      details->range->base_address + details->range->size, __afl_map_size);
-  return TRUE;
-
-}
-
-static void instrument_coverage_optimize_map_mmap_anon(gpointer address) {
-
-  __afl_area_ptr =
-      mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
-           MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-  if (__afl_area_ptr != address) {
-
-    FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
-
-  }
-
-}
-
-static void instrument_coverage_optimize_map_mmap(char *   shm_file_path,
-                                                  gpointer address) {
-
-  int shm_fd = -1;
-
-  if (munmap(__afl_area_ptr, __afl_map_size) != 0) {
-
-    FATAL("Failed to unmap previous __afl_area_ptr");
-
-  }
-
-  __afl_area_ptr = NULL;
-
-    #if !defined(__ANDROID__)
-  shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
-  if (shm_fd == -1) { FATAL("shm_open() failed\n"); }
-    #else
-  shm_fd = open("/dev/ashmem", O_RDWR);
-  if (shm_fd == -1) { FATAL("open() failed\n"); }
-  if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) {
-
-    FATAL("ioctl(ASHMEM_SET_NAME) failed");
-
-  }
-
-  if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) {
-
-    FATAL("ioctl(ASHMEM_SET_SIZE) failed");
-
-  }
-
-    #endif
-
-  __afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
-                        MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0);
-  if (__afl_area_ptr != address) {
-
-    FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
-
-  }
-
-  if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); }
-
-}
-
-static void instrument_coverage_optimize_map_shm(guint64  shm_env_val,
-                                                 gpointer address) {
-
-  if (shmdt(__afl_area_ptr) != 0) {
-
-    FATAL("Failed to detach previous __afl_area_ptr");
-
-  }
-
-  __afl_area_ptr = shmat(shm_env_val, address, 0);
-  if (__afl_area_ptr != address) {
-
-    FATAL("Failed to map shm __afl_area_ptr: %d", errno);
-
-  }
-
-}
-
-void instrument_coverage_optimize_init(void) {
-
-  gpointer low_address = NULL;
-
-  gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low,
-                               &low_address);
-
-  FVERBOSE("Low address: %p", low_address);
-
-  if (low_address == 0 ||
-      GPOINTER_TO_SIZE(low_address) > ((2UL << 30) - __afl_map_size)) {
-
-    FATAL("Invalid low_address: %p", low_address);
-
-  }
-
-  ranges_print_debug_maps();
-
-  char *shm_env = getenv(SHM_ENV_VAR);
-  FVERBOSE("SHM_ENV_VAR: %s", shm_env);
-
-  if (shm_env == NULL) {
-
-    FWARNF("SHM_ENV_VAR not set, using anonymous map for debugging purposes");
-
-    instrument_coverage_optimize_map_mmap_anon(low_address);
-
-  } else {
-
-    guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10);
-
-    if (shm_env_val == 0) {
-
-      instrument_coverage_optimize_map_mmap(shm_env, low_address);
-
-    } else {
-
-      instrument_coverage_optimize_map_shm(shm_env_val, low_address);
-
-    }
-
-  }
-
   FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
 
 }
 
-  #endif
-
 static void instrument_coverage_switch(GumStalkerObserver *self,
                                        gpointer            start_address,
                                        const cs_insn *     from_insn,
@@ -398,10 +202,17 @@ static void instrument_coverage_switch(GumStalkerObserver *self,
 
       }
 
-      if (op[0].type != X86_OP_IMM) { return; }
+      if (op[0].type != X86_OP_IMM) {
+
+        instrument_cache_insert(start_address, *target);
+        return;
+
+      }
 
       break;
     case X86_INS_RET:
+      instrument_cache_insert(start_address,
+                              (guint8 *)*target + sizeof(afl_log_code));
       break;
     default:
       return;
@@ -431,48 +242,19 @@ static void instrument_coverage_suppress_init(void) {
 
 }
 
-void instrument_coverage_optimize(const cs_insn *   instr,
-                                  GumStalkerOutput *output) {
+static void instrument_coverage_write(GumAddress        address,
+                                      GumStalkerOutput *output) {
 
   afl_log_code  code = {0};
   GumX86Writer *cw = output->writer.x86;
-  guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
-  gsize   map_size_pow2;
-  gsize   area_offset_ror;
-  GumAddress code_addr = 0;
-  if (instrument_previous_pc_addr == NULL) {
-
-    GumAddressSpec spec = {.near_address = cw->code,
-                           .max_distance = 1ULL << 30};
-
-    instrument_previous_pc_addr = gum_memory_allocate_near(
-        &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
-    *instrument_previous_pc_addr = instrument_hash_zero;
-    FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
-    FVERBOSE("code_addr: %p", cw->code);
-
-  }
-
-  instrument_coverage_suppress_init();
-
-  // gum_x86_writer_put_breakpoint(cw);
-  code_addr = cw->pc;
-  if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) {
-
-    FATAL("Failed - g_hash_table_add");
-
-  }
+  guint64       area_offset = instrument_get_offset_hash(address);
+  gsize         map_size_pow2;
+  gsize         area_offset_ror;
+  GumAddress    code_addr = cw->pc;
 
   code.code = template;
 
-  gssize curr_loc_shr_1_offset =
-      offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
-      sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32);
-
-  map_size_pow2 = util_log2(__afl_map_size);
-  area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
-
-  *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror);
+  /* mov_prev_loc_curr_loc_shr1 */
 
   gssize prev_loc_value =
       GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
@@ -490,6 +272,8 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
   *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
 
+  /* mov_eax_prev_loc */
+
   gssize prev_loc_value2 =
       GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
       (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
@@ -505,40 +289,172 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
   *((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2;
 
-  #ifdef __APPLE__
+  /* xor_eax_curr_loc */
 
-  gssize xor_curr_loc_offset = offsetof(afl_log_code, code.leax_eax_curr_loc) +
-                               sizeof(code.code.leax_eax_curr_loc) -
+  gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) +
+                               sizeof(code.code.xor_eax_curr_loc) -
                                sizeof(guint32);
 
-  gssize xor_curr_loc_value =
-      ((GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset) -
-       (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
-        sizeof(code.code.mov_eax_prev_loc)));
+  *((guint32 *)&code.bytes[xor_curr_loc_offset]) = area_offset;
+
+  /* lea_rbx_area_ptr */
+
+  gssize lea_rbx_area_ptr_offset =
+      offsetof(afl_log_code, code.lea_rbx_area_ptr) +
+      sizeof(code.code.lea_rbx_area_ptr) - sizeof(guint32);
 
-  if (!instrument_coverage_in_range(xor_curr_loc_value)) {
+  gssize lea_rbx_area_ptr_value =
+      (GPOINTER_TO_SIZE(__afl_area_ptr) -
+       (code_addr + offsetof(afl_log_code, code.lea_rbx_area_ptr) +
+        sizeof(code.code.lea_rbx_area_ptr)));
 
-    FATAL("Patch out of range (xor_curr_loc_value): 0x%016lX",
-          xor_curr_loc_value);
+  if (!instrument_coverage_in_range(lea_rbx_area_ptr_value)) {
+
+    FATAL("Patch out of range (lea_rbx_area_ptr_value): 0x%016lX",
+          lea_rbx_area_ptr_value);
 
   }
 
-  *((guint32 *)&code.bytes[xor_curr_loc_offset]) = xor_curr_loc_value;
+  *((guint32 *)&code.bytes[lea_rbx_area_ptr_offset]) = lea_rbx_area_ptr_value;
 
-  #else
+  /* mov_prev_loc_curr_loc_shr1 */
 
-  gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) +
-                               sizeof(code.code.xor_eax_curr_loc) -
-                               sizeof(guint32);
+  gssize curr_loc_shr_1_offset =
+      offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
+      sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32);
 
-  *((guint32 *)&code.bytes[xor_curr_loc_offset]) =
-      (guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset);
-  #endif
+  map_size_pow2 = util_log2(__afl_map_size);
+  area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
+
+  *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror);
 
   gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
 
 }
 
+void instrument_coverage_optimize(const cs_insn *   instr,
+                                  GumStalkerOutput *output) {
+
+  GumX86Writer *cw = output->writer.x86;
+  /* guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); */
+  if (instrument_previous_pc_addr == NULL) {
+
+    GumAddressSpec spec = {.near_address = cw->code,
+                           .max_distance = 1ULL << 30};
+
+    instrument_previous_pc_addr = gum_memory_allocate_near(
+        &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
+    *instrument_previous_pc_addr = instrument_hash_zero;
+    FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
+    FVERBOSE("code_addr: %p", cw->code);
+
+  }
+
+  instrument_coverage_suppress_init();
+
+  if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) {
+
+    FATAL("Failed - g_hash_table_add");
+
+  }
+
+  instrument_coverage_write(GUM_ADDRESS(instr->address), output);
+
+}
+
+void instrument_coverage_optimize_insn(const cs_insn *   instr,
+                                       GumStalkerOutput *output) {
+
+  GumX86Writer *cw = output->writer.x86;
+  jcc_insn      taken, not_taken;
+
+  switch (instr->id) {
+
+    case X86_INS_CMOVA:
+      taken.opcode = OPC_JA;
+      not_taken.opcode = OPC_JBE;
+      break;
+    case X86_INS_CMOVAE:
+      taken.opcode = OPC_JAE;
+      not_taken.opcode = OPC_JB;
+      break;
+    case X86_INS_CMOVB:
+      taken.opcode = OPC_JB;
+      not_taken.opcode = OPC_JAE;
+      break;
+    case X86_INS_CMOVBE:
+      taken.opcode = OPC_JBE;
+      not_taken.opcode = OPC_JA;
+      break;
+    case X86_INS_CMOVE:
+      taken.opcode = OPC_JE;
+      not_taken.opcode = OPC_JNE;
+      break;
+    case X86_INS_CMOVG:
+      taken.opcode = OPC_JG;
+      not_taken.opcode = OPC_JLE;
+      break;
+    case X86_INS_CMOVGE:
+      taken.opcode = OPC_JGE;
+      not_taken.opcode = OPC_JL;
+      break;
+    case X86_INS_CMOVL:
+      taken.opcode = OPC_JL;
+      not_taken.opcode = OPC_JGE;
+      break;
+    case X86_INS_CMOVLE:
+      taken.opcode = OPC_JLE;
+      not_taken.opcode = OPC_JG;
+      break;
+    case X86_INS_CMOVNE:
+      taken.opcode = OPC_JNE;
+      not_taken.opcode = OPC_JE;
+      break;
+    case X86_INS_CMOVNO:
+      taken.opcode = OPC_JNO;
+      not_taken.opcode = OPC_JO;
+      break;
+    case X86_INS_CMOVNP:
+      taken.opcode = OPC_JNP;
+      not_taken.opcode = OPC_JP;
+      break;
+    case X86_INS_CMOVNS:
+      taken.opcode = OPC_JNS;
+      not_taken.opcode = OPC_JS;
+      break;
+    case X86_INS_CMOVO:
+      taken.opcode = OPC_JO;
+      not_taken.opcode = OPC_JNO;
+      break;
+    case X86_INS_CMOVP:
+      taken.opcode = OPC_JP;
+      not_taken.opcode = OPC_JNP;
+      break;
+    case X86_INS_CMOVS:
+      taken.opcode = OPC_JS;
+      not_taken.opcode = OPC_JNS;
+      break;
+    default:
+      return;
+
+  }
+
+  taken.distance = sizeof(afl_log_code);
+  not_taken.distance = sizeof(afl_log_code);
+
+  // gum_x86_writer_put_breakpoint(cw);
+
+  gum_x86_writer_put_bytes(cw, taken.bytes, sizeof(jcc_insn));
+  instrument_coverage_write(GUM_ADDRESS(instr->address), output);
+
+  gum_x86_writer_put_bytes(cw, not_taken.bytes, sizeof(jcc_insn));
+  instrument_coverage_write(GUM_ADDRESS(instr->address + instr->size), output);
+
+  FVERBOSE("Instrument - 0x%016lx: %s %s", instr->address, instr->mnemonic,
+           instr->op_str);
+
+}
+
 void instrument_flush(GumStalkerOutput *output) {
 
   gum_x86_writer_flush(output->writer.x86);
diff --git a/frida_mode/src/instrument/instrument_x64_cache.c b/frida_mode/src/instrument/instrument_x64_cache.c
new file mode 100644
index 00000000..3ea4421a
--- /dev/null
+++ b/frida_mode/src/instrument/instrument_x64_cache.c
@@ -0,0 +1,435 @@
+#include <sys/mman.h>
+#include <sys/resource.h>
+
+#include "instrument.h"
+#include "util.h"
+
+#if defined(__x86_64__)
+
+  #define INVALID 1
+  #define DEFAULT_CACHE_SIZE (256ULL << 20)
+
+gboolean         instrument_cache_enabled = TRUE;
+gsize            instrument_cache_size = DEFAULT_CACHE_SIZE;
+static gpointer *map_base = MAP_FAILED;
+
+void instrument_cache_config(void) {
+
+  instrument_cache_enabled = (getenv("AFL_FRIDA_INST_NO_CACHE") == NULL);
+
+  if (getenv("AFL_FRIDA_INST_CACHE_SIZE") != NULL) {
+
+    if (!instrument_cache_enabled) {
+
+      FFATAL(
+          "AFL_FRIDA_INST_CACHE_SIZE incomatible with "
+          "AFL_FRIDA_INST_NO_CACHE");
+
+    }
+
+    instrument_cache_size =
+        util_read_address("AFL_FRIDA_INST_CACHE_SIZE", DEFAULT_CACHE_SIZE);
+    util_log2(instrument_cache_size);
+
+  }
+
+}
+
+void instrument_cache_init(void) {
+
+  FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache:" cYEL " [%c]",
+       instrument_cache_enabled ? 'X' : ' ');
+  if (!instrument_cache_enabled) { return; }
+
+  FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache size:" cYEL " [0x%016lX]",
+       instrument_cache_size);
+
+  const struct rlimit data_limit = {.rlim_cur = RLIM_INFINITY,
+                                    .rlim_max = RLIM_INFINITY};
+
+  if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
+
+    FFATAL("Failed to setrlimit: %d", errno);
+
+  }
+
+  map_base =
+      gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
+                          GUM_PAGE_READ | GUM_PAGE_WRITE);
+  if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
+
+  FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
+       GUM_ADDRESS(map_base));
+
+}
+
+static gpointer *instrument_cache_get_addr(gpointer addr) {
+
+  gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1;
+  return &map_base[GPOINTER_TO_SIZE(addr) & mask];
+
+}
+
+void instrument_cache_insert(gpointer real_address, gpointer code_address) {
+
+  if (!instrument_cache_enabled) { return; }
+
+  gpointer *target = instrument_cache_get_addr(real_address);
+  if (*target == code_address) {
+
+    return;
+
+  } else if (*target == NULL) {
+
+    *target = code_address;
+
+  } else {
+
+    *target = GSIZE_TO_POINTER(INVALID);
+
+  }
+
+}
+
+static gboolean instrument_cache_relocate(GumAddress old_pc, GumAddress new_pc,
+                                          gint32  old_offset,
+                                          gint32 *new_offset) {
+
+  guint64 old_target = old_pc + old_offset;
+  gint64  relocated = old_target - new_pc;
+
+  if (relocated > G_MAXINT32 || relocated < G_MININT32) { return FALSE; }
+
+  *new_offset = relocated;
+  return TRUE;
+
+}
+
+static void instrument_cache_rewrite_branch_insn(const cs_insn *   instr,
+                                                 GumStalkerOutput *output) {
+
+  GumX86Writer *cw = output->writer.x86;
+  cs_x86 *      x86 = &instr->detail->x86;
+  guint8        modified[sizeof(instr->bytes)] = {0};
+  guint8        offset = 0;
+  guint8        skip = 0;
+
+  g_assert(sizeof(x86->prefix) == 4);
+  g_assert(sizeof(x86->opcode) == 4);
+
+  /*
+   * If the target is simply RAX, we can skip writing the code to load the
+   * RIP
+   */
+  if (x86->operands[0].type == X86_OP_REG ||
+      x86->operands[0].reg == X86_REG_RAX) {
+
+    return;
+
+  }
+
+  /* Write the prefix */
+  for (gsize i = 0; i < sizeof(x86->prefix); i++) {
+
+    if (x86->prefix[i] != 0) {
+
+      if (x86->prefix[i] == 0xf2) {
+
+        skip++;
+
+      } else {
+
+        modified[offset++] = x86->prefix[i];
+        skip++;
+
+      }
+
+    }
+
+  }
+
+  /* Write the REX */
+  if (x86->rex == 0) {
+
+    /*
+     * CALL (near) and JMP (near) default to 64-bit operands, MOV does not,
+     * write REX.W
+     */
+    modified[offset++] = 0x48;
+
+  } else {
+
+    if ((x86->rex & 0xF8) != 0x40) {
+
+      FATAL("Unexpected REX byte: 0x%02x", x86->rex);
+
+    }
+
+    modified[offset++] = x86->rex | 0x08;
+    skip++;
+
+  }
+
+  /*
+   * CALL is FF /2, JMP is FF /4. The remaining op-code fields should thus be
+   * unused
+   */
+
+  if (x86->opcode[0] != 0xFF || x86->opcode[1] != 0x00 ||
+      x86->opcode[2] != 0x00 || x86->opcode[3] != 0x00) {
+
+    FFATAL("Unexpected Op-code: 0x%02x 0x%02x 0x%02x 0x%02x", x86->opcode[0],
+           x86->opcode[1], x86->opcode[2], x86->opcode[3]);
+
+  }
+
+  /* The reg field of the ModRM should be set to 2 for CALL and 4 for JMP */
+  guint8 reg = (x86->modrm >> 3) & 7;
+  if (reg != 0x4 && reg != 0x2) {
+
+    FFATAL("Unexpected Reg: 0x%02x, ModRM: 0x%02x", reg, x86->modrm);
+
+  }
+
+  /* MOV */
+  modified[offset++] = 0x8b;
+  skip++;
+
+  /* Clear the reg field (RAX) */
+  modified[offset++] = x86->modrm & 0xc7;
+  skip++;
+
+  /* Operands */
+  guint8 op_len = instr->size - skip;
+
+  /* If our branch was RIP relative, we'll need to fix-up the offset */
+  if (x86->operands[0].type == X86_OP_MEM &&
+      x86->operands[0].mem.base == X86_REG_RIP) {
+
+    /* RIP relative offsets should be 32-bits */
+    if (op_len != sizeof(gint32)) {
+
+      FFATAL("Unexpected operand length: %d\n", op_len);
+
+    }
+
+    gint32 old_offset = *(gint32 *)&instr->bytes[skip];
+    gint32 new_offset = 0;
+    if (instrument_cache_relocate(instr->address, cw->pc, old_offset,
+                                  &new_offset)) {
+
+      gint32 *output = (gint32 *)&modified[offset];
+      *output = new_offset;
+      offset += sizeof(gint32);
+
+    } else {
+
+      GumAddress target = instr->address + old_offset;
+      gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, target);
+      gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_RAX, GUM_REG_RAX);
+      return;
+
+    }
+
+  } else {
+
+    for (int i = 0; i < op_len; i++) {
+
+      guint8 val = instr->bytes[i + skip];
+      modified[offset++] = val;
+
+    }
+
+  }
+
+  gum_x86_writer_put_bytes(cw, modified, offset);
+
+}
+
+static void instrument_cache_write_push_frame(GumX86Writer *cw) {
+
+  gum_x86_writer_put_mov_reg_offset_ptr_reg(
+      cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))),
+      GUM_REG_XAX);
+  gum_x86_writer_put_lahf(cw);
+  gum_x86_writer_put_mov_reg_offset_ptr_reg(
+      cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))),
+      GUM_REG_XAX);
+  gum_x86_writer_put_mov_reg_offset_ptr_reg(
+      cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))),
+      GUM_REG_XBX);
+
+}
+
+static void instrument_cache_write_pop_frame(GumX86Writer *cw) {
+
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(
+      cw, GUM_REG_XBX, GUM_REG_XSP,
+      -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))));
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(
+      cw, GUM_REG_XAX, GUM_REG_XSP,
+      -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))));
+  gum_x86_writer_put_sahf(cw);
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(
+      cw, GUM_REG_XAX, GUM_REG_XSP,
+      -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))));
+
+}
+
+static void instrument_cache_write_lookup(GumX86Writer *cw) {
+
+  /* &map_base[GPOINTER_TO_SIZE(addr) & MAP_MASK]; */
+
+  gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1;
+  gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, mask);
+  gum_x86_writer_put_and_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX);
+  gum_x86_writer_put_shl_reg_u8(cw, GUM_REG_XAX, util_log2(sizeof(gpointer)));
+  gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, GPOINTER_TO_SIZE(map_base));
+  gum_x86_writer_put_add_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX);
+
+  /* Read the return address lookup */
+  gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XAX);
+
+}
+
+void instrument_cache_jmp_call(const cs_insn *instr, GumStalkerOutput *output) {
+
+  GumX86Writer *cw = output->writer.x86;
+  cs_x86 *      x86 = &instr->detail->x86;
+
+  if (x86->op_count != 1) { FFATAL("Unexpected operand count"); }
+
+  if (x86->operands[0].type == X86_OP_IMM) { return; }
+
+  gconstpointer null = cw->code;
+
+  instrument_cache_write_push_frame(cw);
+
+  /*
+   * We are about to re-write the CALL or JMP instruction, but replace the
+   * op-code with that for a MOV into RAX. Since we are keeping the operand from
+   * the JMP exactly the same, it is imperative that the target register state
+   * be exactly the same as how the target left it. Since `LAHF` spoils `RAX` we
+   * must restore it from the stack. We also must avoid adjusting `RSP`, so we
+   * use `MOV` instructions to store our context into the stack beyond the
+   * red-zone.
+   */
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(
+      cw, GUM_REG_XAX, GUM_REG_XSP,
+      -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))));
+
+  instrument_cache_rewrite_branch_insn(instr, output);
+
+  instrument_cache_write_lookup(cw);
+
+  /* Test if its set*/
+  gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID);
+  gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY);
+
+  /* If it's set, then stash the address beyond the red-zone */
+  gum_x86_writer_put_mov_reg_offset_ptr_reg(
+      cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))),
+      GUM_REG_XAX);
+
+  if (instr->id == X86_INS_JMP) {
+
+    instrument_cache_write_pop_frame(cw);
+    gum_x86_writer_put_jmp_reg_offset_ptr(
+        cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))));
+
+  } else {
+
+    gum_x86_writer_put_mov_reg_address(
+        cw, GUM_REG_XAX, GUM_ADDRESS(instr->address + instr->size));
+    gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_XSP,
+                                              -sizeof(gpointer), GUM_REG_XAX);
+
+    instrument_cache_write_pop_frame(cw);
+
+    gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_XSP, GUM_REG_XSP,
+                                          -sizeof(gpointer));
+    gum_x86_writer_put_jmp_reg_offset_ptr(
+        cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + ((4 - 1) * sizeof(gpointer))));
+
+  }
+
+  /* Tidy up our mess and let FRIDA handle it */
+  gum_x86_writer_put_label(cw, null);
+  instrument_cache_write_pop_frame(cw);
+
+}
+
+void instrument_cache_ret(const cs_insn *instr, GumStalkerOutput *output) {
+
+  GumX86Writer *cw = output->writer.x86;
+  cs_x86 *      x86 = &instr->detail->x86;
+  guint16       n = 0;
+
+  if (x86->op_count != 0) {
+
+    if (x86->operands[0].type != X86_OP_IMM) {
+
+      FFATAL("Unexpected operand type");
+
+    }
+
+    n = x86->operands[0].imm;
+
+  }
+
+  gconstpointer null = cw->code;
+
+  instrument_cache_write_push_frame(cw);
+
+  gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XSP);
+
+  instrument_cache_write_lookup(cw);
+
+  /* Test if its set*/
+  gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID);
+  gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY);
+
+  /* If it's set, then overwrite our return address and return */
+  gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_XSP, GUM_REG_XAX);
+  instrument_cache_write_pop_frame(cw);
+
+  if (n == 0) {
+
+    gum_x86_writer_put_ret(cw);
+
+  } else {
+
+    gum_x86_writer_put_ret_imm(cw, n);
+
+  }
+
+  /* Tidy up our mess and let FRIDA handle it */
+  gum_x86_writer_put_label(cw, null);
+  instrument_cache_write_pop_frame(cw);
+
+}
+
+void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
+
+  if (!instrument_cache_enabled) { return; }
+
+  switch (instr->id) {
+
+    case X86_INS_RET:
+      instrument_cache_ret(instr, output);
+      break;
+
+    case X86_INS_CALL:
+    case X86_INS_JMP:
+      instrument_cache_jmp_call(instr, output);
+      break;
+
+    default:
+      return;
+
+  }
+
+}
+
+#endif
+
diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c
index c4e93324..6a899248 100644
--- a/frida_mode/src/instrument/instrument_x86.c
+++ b/frida_mode/src/instrument/instrument_x86.c
@@ -6,6 +6,9 @@
 
 #if defined(__i386__)
 
+gboolean instrument_cache_enabled = FALSE;
+gsize    instrument_cache_size = 0;
+
 static GHashTable *coverage_blocks = NULL;
 
   #pragma pack(push, 1)
@@ -218,6 +221,14 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
 }
 
+void instrument_coverage_optimize_insn(const cs_insn *   instr,
+                                       GumStalkerOutput *output) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(output);
+
+}
+
 void instrument_coverage_optimize_init(void) {
 
 }
@@ -234,5 +245,27 @@ gpointer instrument_cur(GumStalkerOutput *output) {
 
 }
 
+void instrument_cache_config(void) {
+
+}
+
+void instrument_cache_init(void) {
+
+}
+
+void instrument_cache_insert(gpointer real_address, gpointer code_address) {
+
+  UNUSED_PARAMETER(real_address);
+  UNUSED_PARAMETER(code_address);
+
+}
+
+void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
+
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(output);
+
+}
+
 #endif
 
diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js
index 52e9e45c..c1c9d36f 100644
--- a/frida_mode/src/js/api.js
+++ b/frida_mode/src/js/api.js
@@ -69,6 +69,12 @@ class Afl {
         Afl.jsApiSetBackpatchDisable();
     }
     /**
+     * See `AFL_FRIDA_INST_NO_CACHE`.
+     */
+    static setCacheDisable() {
+        Afl.jsApiSetCacheDisable();
+    }
+    /**
      * See `AFL_FRIDA_DEBUG_MAPS`.
      */
     static setDebugMaps() {
@@ -92,6 +98,13 @@ class Afl {
         Afl.jsApiAflSharedMemFuzzing.writeInt(1);
     }
     /**
+     * See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number`
+     * as an argument.
+     */
+    static setInstrumentCacheSize(size) {
+        Afl.jsApiSetInstrumentCacheSize(size);
+    }
+    /**
      * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string`
      * as an argument.
      */
@@ -114,6 +127,12 @@ class Afl {
         Afl.jsApiSetInstrumentTrace();
     }
     /**
+     * See `AFL_FRIDA_INST_INSN`
+     */
+    static setInstrumentInstructions() {
+        Afl.jsApiSetInstrumentInstructions();
+    }
+    /**
      * See `AFL_FRIDA_INST_JIT`.
      */
     static setInstrumentJit() {
@@ -293,10 +312,13 @@ Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing");
 Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []);
 Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]);
 Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []);
+Afl.jsApiSetCacheDisable = Afl.jsApiGetFunction("js_api_set_cache_disable", "void", []);
 Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []);
 Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]);
+Afl.jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction("js_api_set_instrument_cache_size", "void", ["size_t"]);
 Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]);
 Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]);
+Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []);
 Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []);
 Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
 Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []);
diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c
index 94ec8842..7cc8ffc7 100644
--- a/frida_mode/src/js/js_api.c
+++ b/frida_mode/src/js/js_api.c
@@ -142,6 +142,13 @@ js_api_set_prefetch_backpatch_disable(void) {
 
 }
 
+__attribute__((visibility("default"))) void js_api_set_instrument_instructions(
+    void) {
+
+  instrument_coverage_insn = TRUE;
+
+}
+
 __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
     void) {
 
@@ -255,6 +262,19 @@ __attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks(
 
 }
 
+__attribute__((visibility("default"))) void js_api_set_cache_disable(void) {
+
+  instrument_cache_enabled = FALSE;
+
+}
+
+__attribute__((visibility("default"))) void js_api_set_instrument_cache_size(
+    gsize size) {
+
+  instrument_cache_size = size;
+
+}
+
 __attribute__((visibility("default"))) void js_api_set_js_main_hook(
     const js_main_hook_t hook) {
 
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index d8521300..bb6e4109 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -21,6 +21,7 @@
 #include "intercept.h"
 #include "js.h"
 #include "lib.h"
+#include "module.h"
 #include "output.h"
 #include "persistent.h"
 #include "prefetch.h"
@@ -197,6 +198,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
   instrument_config();
   js_config();
   lib_config();
+  module_config();
   output_config();
   persistent_config();
   prefetch_config();
@@ -214,6 +216,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
   entry_init();
   instrument_init();
   lib_init();
+  module_init();
   persistent_init();
   prefetch_init();
   seccomp_init();
diff --git a/frida_mode/src/module.c b/frida_mode/src/module.c
new file mode 100644
index 00000000..65b394cd
--- /dev/null
+++ b/frida_mode/src/module.c
@@ -0,0 +1,106 @@
+#include "intercept.h"
+#include "module.h"
+#include "util.h"
+
+#if defined(__linux__)
+  #include <dlfcn.h>
+  #include <link.h>
+#endif
+
+static guint    page_size = 0;
+static gboolean handle_dlclose = FALSE;
+
+void module_config(void) {
+
+#if defined(__linux__)
+  handle_dlclose = (getenv("AFL_FRIDA_NO_MODULE") == NULL);
+#else
+  FWARNF("AFL_FRIDA_MODULE not supported");
+#endif
+
+}
+
+typedef struct {
+
+  GumMemoryRange    range;
+  GumPageProtection protection;
+  GumFileMapping    file;
+
+} gum_range_t;
+
+gboolean found_range(const GumRangeDetails *details, gpointer user_data) {
+
+  gum_range_t range = {0};
+  GArray *    ranges = (GArray *)user_data;
+
+  range.range = *details->range;
+  range.protection = details->protection;
+  if (details->file != NULL) { range.file = *details->file; }
+
+  g_array_append_val(ranges, range);
+  return FALSE;
+
+}
+
+#if defined(__linux__)
+static int on_dlclose(void *handle) {
+
+  GArray *         ranges = NULL;
+  struct link_map *lm = NULL;
+  gum_range_t *    range = NULL;
+  GumAddress       base;
+  GumAddress       limit;
+  gpointer         mem;
+
+  if (dlinfo(handle, RTLD_DI_LINKMAP, &lm) < 0) {
+
+    FFATAL("Failed to dlinfo: %s", dlerror());
+
+  }
+
+  FVERBOSE("on_dlclose: %s", lm->l_name);
+
+  ranges = g_array_new(FALSE, TRUE, sizeof(gum_range_t));
+  gum_module_enumerate_ranges(lm->l_name, GUM_PAGE_EXECUTE, found_range,
+                              ranges);
+
+  int ret = dlclose(handle);
+  if (ret != 0) {
+
+    FWARNF("dlclose returned: %d (%s)", ret, dlerror());
+    return ret;
+
+  }
+
+  for (guint i = 0; i < ranges->len; i++) {
+
+    range = &g_array_index(ranges, gum_range_t, i);
+    base = range->range.base_address;
+    limit = base + range->range.size;
+    FVERBOSE("Reserving range: 0x%016lx, 0x%016lX", base, limit);
+    mem = gum_memory_allocate(GSIZE_TO_POINTER(base), range->range.size,
+                              page_size, GUM_PAGE_NO_ACCESS);
+    if (mem == NULL) { FATAL("Failed to allocate %p (%d)", mem, errno); }
+
+  }
+
+  g_array_free(ranges, TRUE);
+  return 0;
+
+}
+
+#endif
+
+void module_init(void) {
+
+  FOKF(cBLU "Module" cRST " - " cYEL " [%c]", handle_dlclose ? 'X' : ' ');
+
+#if defined(__linux__)
+  if (!handle_dlclose) { return; }
+
+  page_size = gum_query_page_size();
+  intercept_hook(dlclose, on_dlclose, NULL);
+#endif
+
+}
+
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
index 84803453..d47d1c14 100644
--- a/frida_mode/src/ranges.c
+++ b/frida_mode/src/ranges.c
@@ -595,8 +595,6 @@ void ranges_init(void) {
        ranges_inst_jit ? 'X' : ' ');
   FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]",
        ranges_inst_libs ? 'X' : ' ');
-  FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]",
-       ranges_inst_libs ? 'X' : ' ');
 
   print_ranges("include", include_ranges);
   print_ranges("exclude", exclude_ranges);
diff --git a/frida_mode/test/cache/GNUmakefile b/frida_mode/test/cache/GNUmakefile
new file mode 100644
index 00000000..12736a3f
--- /dev/null
+++ b/frida_mode/test/cache/GNUmakefile
@@ -0,0 +1,97 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+
+TEST_CACHE_SRC:=$(PWD)cache.c
+TEST_CACHE_OBJ:=$(BUILD_DIR)cache
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+CACHE_INPUT:=$(TEST_DATA_DIR)in
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ADDR_BIN:=$(ROOT)frida_mode/build/addr
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
+
+AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
+
+AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
+AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_CACHE_OBJ) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
+
+DUMMY_DATA_FILE:=$(BUILD_DIR)dummy.dat
+
+.PHONY: all 32 clean frida frida_noinst debug format
+
+all: $(TEST_CACHE_OBJ)
+	make -C $(ROOT)frida_mode/
+
+32:
+	CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+	mkdir -p $@
+
+$(TEST_DATA_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(CACHE_INPUT): | $(TEST_DATA_DIR)
+	echo -n "ABC" > $@
+
+$(TEST_CACHE_OBJ): $(TEST_CACHE_SRC) | $(BUILD_DIR)
+	$(CC) -g $(CFLAGS) $(LDFLAGS) $< -o $@
+
+########## DUMMY #######
+
+$(DUMMY_DATA_FILE): | $(BUILD_DIR)
+	dd if=/dev/zero bs=1048576 count=1 of=$@
+
+frida: $(TEST_CACHE_OBJ) $(CACHE_INPUT) $(DUMMY_DATA_FILE)
+	AFL_FRIDA_INST_INSN=1 \
+	AFL_FRIDA_PERSISTENT_CNT=1000000 \
+	AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
+	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-O \
+		-i $(TEST_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-Z \
+		-t 10000+ \
+		-- \
+			$(TEST_CACHE_OBJ) $(DUMMY_DATA_FILE)
+
+frida_nocache: $(TEST_CACHE_OBJ) $(CACHE_INPUT) $(DUMMY_DATA_FILE)
+	AFL_FRIDA_INST_NO_CACHE=1 \
+	AFL_FRIDA_PERSISTENT_CNT=1000000 \
+	AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
+	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-O \
+		-i $(TEST_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-Z \
+		-- \
+			$(TEST_CACHE_OBJ) $(DUMMY_DATA_FILE)
+
+debug: $(TEST_CACHE_OBJ) $(CACHE_INPUT)
+	gdb \
+		--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+		--ex 'set disassembly-flavor intel' \
+		--ex 'r $(CACHE_INPUT)' \
+		--args $(TEST_CACHE_OBJ) $(CACHE_INPUT)
+
+show: $(TEST_CACHE_OBJ) $(CACHE_INPUT)
+	gdb \
+		--ex "set disassembly-flavor intel" \
+		--ex "set confirm off" \
+		--ex "symbol-file $(TEST_CACHE_OBJ)" \
+		--ex "x/50i LLVMFuzzerTestOneInput" \
+		--ex "r" \
+		--args $(TEST_CACHE_OBJ) $(CACHE_INPUT)
+
+clean:
+	rm -rf $(BUILD_DIR)
+
+format:
+	cd $(ROOT) && echo $(TEST_CACHE_SRC) | xargs -L1 ./.custom-format.py -i
diff --git a/frida_mode/test/cache/Makefile b/frida_mode/test/cache/Makefile
new file mode 100644
index 00000000..961a284c
--- /dev/null
+++ b/frida_mode/test/cache/Makefile
@@ -0,0 +1,22 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+32:
+	@echo trying to use GNU make...
+	@gmake 32 || echo please install GNUmake
+
+frida:
+	@gmake frida
+
+frida_nocache:
+	@gmake frida_nocache
+
+debug:
+	@gmake debug
+
+clean:
+	@gmake clean
+
+format:
+	@gmake format
diff --git a/frida_mode/test/cache/cache.c b/frida_mode/test/cache/cache.c
new file mode 100644
index 00000000..b4102205
--- /dev/null
+++ b/frida_mode/test/cache/cache.c
@@ -0,0 +1,115 @@
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void LLVMFuzzerTestOneInput(char *buf, int len);
+
+__asm__ (
+  "LLVMFuzzerTestOneInput:\n"
+  ".func LLVMFuzzerTestOneInput\n"
+  ".global LLVMFuzzerTestOneInput\n"
+  "    jmpq *jmp_offset(%rip)\n"
+  "    nop\n"
+  "    nop\n"
+  "call_target:\n"
+  "    ret\n"
+  "    nop\n"
+  "    nop\n"
+  "jmp_target:\n"
+  "    callq *call_offset(%rip)\n"
+  "    nop\n"
+  "    nop\n"
+  "    leaq rax_offset(%rip), %rax\n"
+  "    jmp (%rax)\n"
+  "    nop\n"
+  "    ud2\n"
+  "    nop\n"
+  "rax_target:\n"
+  "    ret\n"
+  "\n"
+  "\n"
+  ".global jmp_offset\n"
+  ".p2align 3\n"
+  "jmp_offset:\n"
+  "    .quad jmp_target\n"
+  "call_offset:\n"
+  "    .quad call_target\n"
+  "rax_offset:\n"
+  "    .quad rax_target\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 = (char *)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);
+
+    LLVMFuzzerTestOneInput(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/cmov/GNUmakefile b/frida_mode/test/cmov/GNUmakefile
new file mode 100644
index 00000000..96f1ae5b
--- /dev/null
+++ b/frida_mode/test/cmov/GNUmakefile
@@ -0,0 +1,87 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+
+TEST_CMOV_SRC:=$(PWD)cmov.c
+TEST_CMOV_OBJ:=$(BUILD_DIR)cmov
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+CMP_LOG_INPUT:=$(TEST_DATA_DIR)in
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ADDR_BIN:=$(ROOT)frida_mode/build/addr
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
+
+AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
+
+AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
+AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_CMOV_OBJ) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
+
+DUMMY_DATA_FILE:=$(BUILD_DIR)dummy.dat
+
+.PHONY: all 32 clean frida frida_noinst debug format
+
+all: $(TEST_CMOV_OBJ)
+	make -C $(ROOT)frida_mode/
+
+32:
+	CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+	mkdir -p $@
+
+$(TEST_DATA_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(CMP_LOG_INPUT): | $(TEST_DATA_DIR)
+	echo -n "ABC" > $@
+
+$(TEST_CMOV_OBJ): $(TEST_CMOV_SRC) | $(BUILD_DIR)
+	$(CC) -g $(CFLAGS) $(LDFLAGS) $< -o $@
+
+########## DUMMY #######
+
+$(DUMMY_DATA_FILE): | $(BUILD_DIR)
+	dd if=/dev/zero bs=1048576 count=1 of=$@
+
+frida: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE)
+	AFL_FRIDA_INST_INSN=1 \
+	AFL_FRIDA_PERSISTENT_CNT=1000000 \
+	AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
+	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-O \
+		-i $(TEST_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-Z \
+		-t 10000+ \
+		-- \
+			$(TEST_CMOV_OBJ) $(DUMMY_DATA_FILE)
+
+frida_noinst: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE)
+	AFL_FRIDA_PERSISTENT_CNT=1000000 \
+	AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
+	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-O \
+		-i $(TEST_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-Z \
+		-- \
+			$(TEST_CMOV_OBJ) $(DUMMY_DATA_FILE)
+
+debug: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT)
+	gdb \
+		--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+		--ex 'set disassembly-flavor intel' \
+		--ex 'r $(CMP_LOG_INPUT)' \
+		--args $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT)
+
+clean:
+	rm -rf $(BUILD_DIR)
+
+format:
+	cd $(ROOT) && echo $(TEST_CMOV_SRC) | xargs -L1 ./.custom-format.py -i
diff --git a/frida_mode/test/cmov/Makefile b/frida_mode/test/cmov/Makefile
new file mode 100644
index 00000000..9ef6fc8f
--- /dev/null
+++ b/frida_mode/test/cmov/Makefile
@@ -0,0 +1,19 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+32:
+	@echo trying to use GNU make...
+	@gmake 32 || echo please install GNUmake
+
+clean:
+	@gmake clean
+
+frida:
+	@gmake frida
+
+format:
+	@gmake format
+
+debug:
+	@gmake debug
diff --git a/frida_mode/test/cmov/cmov.c b/frida_mode/test/cmov/cmov.c
new file mode 100644
index 00000000..08c7c132
--- /dev/null
+++ b/frida_mode/test/cmov/cmov.c
@@ -0,0 +1,122 @@
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static bool cmov_test(char *x, char *y, size_t len) {
+
+  register char * __rdi __asm__("rdi") = x;
+  register char * __rsi __asm__("rsi") = y;
+  register size_t __rcx __asm__("rcx") = len;
+
+  register long __rax __asm__("rax");
+
+  __asm__ __volatile__(
+      "mov $0x1, %%rax\n"
+      "mov $0x0, %%r8\n"
+      "1:\n"
+      "mov (%%rsi), %%bl\n"
+      "mov (%%rdi), %%dl\n"
+      "cmp %%bl, %%dl\n"
+      "cmovne %%r8, %%rax\n"
+      "inc %%rsi\n"
+      "inc %%rdi\n"
+      "dec %%rcx\n"
+      "jnz 1b\n"
+      : "=r"(__rax)
+      : "r"(__rdi), "r"(__rsi)
+      : "r8", "bl", "dl", "memory");
+
+  return __rax;
+
+}
+
+void LLVMFuzzerTestOneInput(char *buf, int len) {
+
+  char match[] = "CBAABC";
+
+  if (len > sizeof(match)) { return; }
+
+  if (cmov_test(buf, match, sizeof(buf)) != 0) {
+
+    printf("Puzzle solved, congrats!\n");
+    abort();
+
+  }
+
+}
+
+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 = (char *)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);
+
+    LLVMFuzzerTestOneInput(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/python/GNUmakefile b/frida_mode/test/python/GNUmakefile
new file mode 100644
index 00000000..e4f7857b
--- /dev/null
+++ b/frida_mode/test/python/GNUmakefile
@@ -0,0 +1,37 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+
+.PHONY: all clean run qemu frida
+
+all:
+	make -C $(ROOT)frida_mode/
+
+clean:
+	rm -rf $(BUILD_DIR)
+
+$(BUILD_DIR):
+	mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+run:
+	date
+	/usr/bin/python -c 'print("hi");'
+	date
+
+qemu:
+	date
+	$(ROOT)afl-qemu-trace \
+		/usr/bin/python -c 'print("hi");'
+	date
+
+frida:
+	date
+	LD_PRELOAD=$(ROOT)afl-frida-trace.so \
+		python -c 'print("hi");'
+	date
diff --git a/frida_mode/test/python/Makefile b/frida_mode/test/python/Makefile
new file mode 100644
index 00000000..e66cfdef
--- /dev/null
+++ b/frida_mode/test/python/Makefile
@@ -0,0 +1,17 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+clean:
+	@gmake clean
+
+run:
+	@gmake run
+
+qemu:
+	@gmake qemu
+
+frida:
+	@gmake frida
+
+
diff --git a/frida_mode/test/vorbis/GNUmakefile b/frida_mode/test/vorbis/GNUmakefile
index 9cce6c9e..4cb5d417 100644
--- a/frida_mode/test/vorbis/GNUmakefile
+++ b/frida_mode/test/vorbis/GNUmakefile
@@ -125,7 +125,7 @@ vorbis: $(VORBIS_LIB)
 ########## HARNESS #######
 
 $(DECODE_SRC):
-	wget -O $@ $(DECODE_URL)
+	wget -O $@ $(DECODE_URL) || curl -L -o $@ $(DECODE_URL)
 
 $(DECODE_OBJ): $(DECODE_SRC)
 	$(CXX) -o $@ -c $< -I$(VORBIS_DIR)include/ -I$(OGG_DIR)include/
@@ -135,7 +135,7 @@ decode: $(DECODE_OBJ)
 ########## HARNESS #######
 
 $(HARNESS_SRC):
-	wget -O $@ $(HARNESS_URL)
+	wget -O $@ $(HARNESS_URL) || curl -L -o $@ $(HARNESS_URL)
 
 $(HARNESS_OBJ): $(HARNESS_SRC)
 	$(CC) -o $@ -c $<
@@ -165,8 +165,8 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
 
 ###### TEST DATA #######
 
-$(TEST_DATA_FILE): $(TEST_DATA_DIR)
-	wget -O $@ $(TEST_DATA_SRC)
+$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
+	wget -O $@ $(TEST_DATA_SRC) || curl -L -o $@ $(TEST_DATA_SRC)
 
 clean:
 	rm -rf $(BUILD_DIR)
diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts
index 57d7b5b5..a858f074 100644
--- a/frida_mode/ts/lib/afl.ts
+++ b/frida_mode/ts/lib/afl.ts
@@ -85,6 +85,13 @@ class Afl {
   }
 
   /**
+   * See `AFL_FRIDA_INST_NO_CACHE`.
+   */
+  public static setCacheDisable(): void {
+    Afl.jsApiSetCacheDisable();
+  }
+
+  /**
    * See `AFL_FRIDA_DEBUG_MAPS`.
    */
   public static setDebugMaps(): void {
@@ -111,6 +118,14 @@ class Afl {
   }
 
   /**
+   * See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number`
+   * as an argument.
+   */
+  public static setInstrumentCacheSize(size: number): void {
+    Afl.jsApiSetInstrumentCacheSize(size);
+  }
+
+  /**
    * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string`
    * as an argument.
    */
@@ -136,6 +151,13 @@ class Afl {
   }
 
   /**
+   * See `AFL_FRIDA_INST_INSN`
+   */
+  public static setInstrumentInstructions(): void {
+    Afl.jsApiSetInstrumentInstructions();
+  }
+
+  /**
    * See `AFL_FRIDA_INST_JIT`.
    */
   public static setInstrumentJit(): void {
@@ -347,6 +369,11 @@ class Afl {
     "void",
     []);
 
+  private static readonly jsApiSetCacheDisable = Afl.jsApiGetFunction(
+    "js_api_set_cache_disable",
+    "void",
+    []);
+
   private static readonly jsApiSetDebugMaps = Afl.jsApiGetFunction(
     "js_api_set_debug_maps",
     "void",
@@ -357,6 +384,11 @@ class Afl {
     "void",
     ["pointer"]);
 
+  private static readonly jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction(
+    "js_api_set_instrument_cache_size",
+    "void",
+    ["size_t"]);
+
   private static readonly jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction(
     "js_api_set_instrument_coverage_file",
     "void",
@@ -367,6 +399,11 @@ class Afl {
     "void",
     ["pointer"]);
 
+  private static readonly jsApiSetInstrumentInstructions = Afl.jsApiGetFunction(
+    "js_api_set_instrument_instructions",
+    "void",
+    []);
+
   private static readonly jsApiSetInstrumentJit = Afl.jsApiGetFunction(
     "js_api_set_instrument_jit",
     "void",
diff --git a/include/envs.h b/include/envs.h
index 2c9305f6..1746f946 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -57,9 +57,12 @@ static char *afl_environment_variables[] = {
     "AFL_FRIDA_DEBUG_MAPS",
     "AFL_FRIDA_DRIVER_NO_HOOK",
     "AFL_FRIDA_EXCLUDE_RANGES",
+    "AFL_FRIDA_INST_CACHE_SIZE",
     "AFL_FRIDA_INST_COVERAGE_FILE",
     "AFL_FRIDA_INST_DEBUG_FILE",
+    "AFL_FRIDA_INST_INSN",
     "AFL_FRIDA_INST_JIT",
+    "AFL_FRIDA_INST_NO_CACHE",
     "AFL_FRIDA_INST_NO_OPTIMIZE",
     "AFL_FRIDA_INST_NO_PREFETCH",
     "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",
diff --git a/include/forkserver.h b/include/forkserver.h
index fd4d283c..5b66e7ec 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -70,6 +70,8 @@ typedef struct {
   enum NyxReturnValue (*nyx_exec)(void *qemu_process);
   uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process);
   size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process);
+  uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer,
+                                 uint32_t size);
 
 } nyx_plugin_handler_t;
 
@@ -173,6 +175,7 @@ typedef struct afl_forkserver {
   void *                nyx_runner;      /* nyx runner object                */
   u32                   nyx_id;          /* nyx runner id (0 -> master)      */
   u32                   nyx_bind_cpu_id; /* nyx runner cpu id                */
+  char *                nyx_aux_string;
 #endif
 
 } afl_forkserver_t;
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 6a4a071f..9a48ae6d 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -17,6 +17,7 @@
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -33,7 +34,6 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Mangler.h"
@@ -51,6 +51,9 @@
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/IR/PassManager.h"
 
 #include "config.h"
 #include "debug.h"
@@ -161,27 +164,21 @@ using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
 using PostDomTreeCallback =
     function_ref<const PostDominatorTree *(Function &F)>;
 
-class ModuleSanitizerCoverage {
+class ModuleSanitizerCoverageLTO
+    : public PassInfoMixin<ModuleSanitizerCoverageLTO> {
 
  public:
-  ModuleSanitizerCoverage(
+  ModuleSanitizerCoverageLTO(
       const SanitizerCoverageOptions &Options = SanitizerCoverageOptions())
       : Options(OverrideFromCL(Options)) {
 
-    /* ,
-    const SpecialCaseList *         Allowlist = nullptr,
-    const SpecialCaseList *         Blocklist = nullptr)
-      ,
-      Allowlist(Allowlist),
-      Blocklist(Blocklist) {
-
-    */
-
   }
 
   bool instrumentModule(Module &M, DomTreeCallback DTCallback,
                         PostDomTreeCallback PDTCallback);
 
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+
  private:
   void            instrumentFunction(Function &F, DomTreeCallback DTCallback,
                                      PostDomTreeCallback PDTCallback);
@@ -279,18 +276,6 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
       const SanitizerCoverageOptions &Options = SanitizerCoverageOptions())
       : ModulePass(ID), Options(Options) {
 
-    /* ,
-          const std::vector<std::string> &AllowlistFiles =
-              std::vector<std::string>(),
-          const std::vector<std::string> &BlocklistFiles =
-              std::vector<std::string>())
-        if (AllowlistFiles.size() > 0)
-          Allowlist = SpecialCaseList::createOrDie(AllowlistFiles,
-                                                   *vfs::getRealFileSystem());
-        if (BlocklistFiles.size() > 0)
-          Blocklist = SpecialCaseList::createOrDie(BlocklistFiles,
-                                                   *vfs::getRealFileSystem());
-    */
     initializeModuleSanitizerCoverageLegacyPassPass(
         *PassRegistry::getPassRegistry());
 
@@ -298,8 +283,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
 
   bool runOnModule(Module &M) override {
 
-    ModuleSanitizerCoverage ModuleSancov(Options);
-    // , Allowlist.get(), Blocklist.get());
+    ModuleSanitizerCoverageLTO ModuleSancov(Options);
     auto DTCallback = [this](Function &F) -> const DominatorTree * {
 
       return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
@@ -320,18 +304,36 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
  private:
   SanitizerCoverageOptions Options;
 
-  // std::unique_ptr<SpecialCaseList> Allowlist;
-  // std::unique_ptr<SpecialCaseList> Blocklist;
-
 };
 
 }  // namespace
 
-PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &               M,
-                                                   ModuleAnalysisManager &MAM) {
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "SanitizerCoverageLTO", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+#if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+#endif
+            //            PB.registerFullLinkTimeOptimizationLastEPCallback(
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(ModuleSanitizerCoverageLTO());
+
+                });
+
+          }};
+
+}
+
+PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &               M,
+                                                  ModuleAnalysisManager &MAM) {
 
-  ModuleSanitizerCoverage ModuleSancov(Options);
-  // Allowlist.get(), Blocklist.get());
+  ModuleSanitizerCoverageLTO ModuleSancov(Options);
   auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
   auto  DTCallback = [&FAM](Function &F) -> const DominatorTree * {
 
@@ -352,35 +354,7 @@ PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &               M,
 
 }
 
-/*
-std::pair<Value *, Value *> ModuleSanitizerCoverage::CreateSecStartEnd(
-    Module &M, const char *Section, Type *Ty) {
-
-  GlobalVariable *SecStart =
-      new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr,
-                         getSectionStart(Section));
-  SecStart->setVisibility(GlobalValue::HiddenVisibility);
-  GlobalVariable *SecEnd =
-      new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr,
-                         getSectionEnd(Section));
-  SecEnd->setVisibility(GlobalValue::HiddenVisibility);
-  IRBuilder<> IRB(M.getContext());
-  Value *     SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty);
-  if (!TargetTriple.isOSBinFormatCOFF())
-    return std::make_pair(IRB.CreatePointerCast(SecStart, Ty), SecEndPtr);
-
-  // Account for the fact that on windows-msvc __start_* symbols actually
-  // point to a uint64_t before the start of the array.
-  auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
-  auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
-                           ConstantInt::get(IntptrTy, sizeof(uint64_t)));
-  return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr);
-
-}
-
-*/
-
-bool ModuleSanitizerCoverage::instrumentModule(
+bool ModuleSanitizerCoverageLTO::instrumentModule(
     Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false;
@@ -757,7 +731,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
             if (!HasStr2) {
 
               auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
-              if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+              if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
 
                 if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
 
@@ -838,7 +812,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
 
               auto Ptr = dyn_cast<ConstantExpr>(Str1P);
 
-              if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+              if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
 
                 if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
 
@@ -1044,7 +1018,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
           M, Int64Tyi, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr");
       ConstantInt *MapAddr = ConstantInt::get(Int64Tyi, map_addr);
       StoreInst *  StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreMapAddr);
+      ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreMapAddr);
 
     }
 
@@ -1059,7 +1033,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
                              "__afl_final_loc");
       ConstantInt *const_loc = ConstantInt::get(Int32Tyi, write_loc);
       StoreInst *  StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreFinalLoc);
+      ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreFinalLoc);
 
     }
 
@@ -1107,7 +1081,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
                                0, "__afl_dictionary_len");
         ConstantInt *const_len = ConstantInt::get(Int32Tyi, offset);
         StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen);
-        ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDictLen);
+        ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreDictLen);
 
         ArrayType *ArrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
         GlobalVariable *AFLInternalDictionary = new GlobalVariable(
@@ -1127,7 +1101,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
         Value *AFLDictPtr =
             IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Tyi, 0));
         StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary);
-        ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDict);
+        ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreDict);
 
       }
 
@@ -1234,7 +1208,7 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
 
 }
 
-void ModuleSanitizerCoverage::instrumentFunction(
+void ModuleSanitizerCoverageLTO::instrumentFunction(
     Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   if (F.empty()) return;
@@ -1389,7 +1363,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
         /* Load SHM pointer */
         LoadInst *MapPtr =
             IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
-        ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
+        ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr);
 
         while (1) {
 
@@ -1419,7 +1393,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
           } else {
 
             LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx);
-            ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
+            ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(Counter);
 
             /* Update bitmap */
 
@@ -1434,7 +1408,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
             }
 
             auto nosan = IRB.CreateStore(Incr, MapPtrIdx);
-            ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan);
+            ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(nosan);
 
           }
 
@@ -1472,7 +1446,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
 
 }
 
-GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
+GlobalVariable *ModuleSanitizerCoverageLTO::CreateFunctionLocalArrayInSection(
     size_t NumElements, Function &F, Type *Ty, const char *Section) {
 
   ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);
@@ -1502,7 +1476,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
 
 }
 
-GlobalVariable *ModuleSanitizerCoverage::CreatePCArray(
+GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray(
     Function &F, ArrayRef<BasicBlock *> AllBlocks) {
 
   size_t N = AllBlocks.size();
@@ -1538,7 +1512,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreatePCArray(
 
 }
 
-void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
+void ModuleSanitizerCoverageLTO::CreateFunctionLocalArrays(
     Function &F, ArrayRef<BasicBlock *> AllBlocks) {
 
   if (Options.TracePCGuard)
@@ -1554,9 +1528,8 @@ void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
 
 }
 
-bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
-                                             ArrayRef<BasicBlock *> AllBlocks,
-                                             bool IsLeafFunc) {
+bool ModuleSanitizerCoverageLTO::InjectCoverage(
+    Function &F, ArrayRef<BasicBlock *> AllBlocks, bool IsLeafFunc) {
 
   if (AllBlocks.empty()) return false;
   CreateFunctionLocalArrays(F, AllBlocks);
@@ -1602,7 +1575,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
 //     The cache is used to speed up recording the caller-callee pairs.
 // The address of the caller is passed implicitly via caller PC.
 // CacheSize is encoded in the name of the run-time function.
-void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
+void ModuleSanitizerCoverageLTO::InjectCoverageForIndirectCalls(
     Function &F, ArrayRef<Instruction *> IndirCalls) {
 
   if (IndirCalls.empty()) return;
@@ -1620,9 +1593,10 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
 
 }
 
-void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
-                                                    size_t Idx,
-                                                    bool   IsLeafFunc) {
+void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &  F,
+                                                       BasicBlock &BB,
+                                                       size_t      Idx,
+                                                       bool        IsLeafFunc) {
 
   BasicBlock::iterator IP = BB.getFirstInsertionPt();
   bool                 IsEntryBB = &BB == &F.getEntryBlock();
@@ -1677,7 +1651,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     } else {
 
       LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
+      ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr);
       MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc);
 
     }
@@ -1694,7 +1668,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     } else {
 
       LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
+      ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(Counter);
 
       Value *Incr = IRB.CreateAdd(Counter, One);
 
@@ -1707,7 +1681,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
       }
 
       auto nosan = IRB.CreateStore(Incr, MapPtrIdx);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan);
+      ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(nosan);
 
     }
 
@@ -1759,7 +1733,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
 
 }
 
-std::string ModuleSanitizerCoverage::getSectionName(
+std::string ModuleSanitizerCoverageLTO::getSectionName(
     const std::string &Section) const {
 
   if (TargetTriple.isOSBinFormatCOFF()) {
@@ -1776,27 +1750,6 @@ std::string ModuleSanitizerCoverage::getSectionName(
 
 }
 
-/*
-std::string ModuleSanitizerCoverage::getSectionStart(
-    const std::string &Section) const {
-
-  if (TargetTriple.isOSBinFormatMachO())
-    return "\1section$start$__DATA$__" + Section;
-  return "__start___" + Section;
-
-}
-
-std::string ModuleSanitizerCoverage::getSectionEnd(
-    const std::string &Section) const {
-
-  if (TargetTriple.isOSBinFormatMachO())
-    return "\1section$end$__DATA$__" + Section;
-  return "__stop___" + Section;
-
-}
-
-*/
-
 char ModuleSanitizerCoverageLegacyPass::ID = 0;
 
 INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
@@ -1814,7 +1767,6 @@ ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
     const std::vector<std::string> &BlocklistFiles) {
 
   return new ModuleSanitizerCoverageLegacyPass(Options);
-  //, AllowlistFiles, BlocklistFiles);
 
 }
 
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index e4ffeb50..f80b1a1e 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -13,6 +13,7 @@
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/IR/CFG.h"
@@ -36,14 +37,14 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SpecialCaseList.h"
-#if LLVM_VERSION_MAJOR >= 11 || \
-    (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1)
-  #include "llvm/Support/VirtualFileSystem.h"
-#endif
+#include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/IR/PassManager.h"
 
 #include "config.h"
 #include "debug.h"
@@ -123,21 +124,18 @@ using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
 using PostDomTreeCallback =
     function_ref<const PostDominatorTree *(Function &F)>;
 
-class ModuleSanitizerCoverage {
+class ModuleSanitizerCoverageAFL
+    : public PassInfoMixin<ModuleSanitizerCoverageAFL> {
 
  public:
-  ModuleSanitizerCoverage(
-      const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()
-#if (LLVM_VERSION_MAJOR >= 11)
-          ,
-      const SpecialCaseList *Allowlist = nullptr,
-      const SpecialCaseList *Blocklist = nullptr
-#endif
-      )
+  ModuleSanitizerCoverageAFL(
+      const SanitizerCoverageOptions &Options = SanitizerCoverageOptions())
       : Options(OverrideFromCL(Options)) {
 
   }
 
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+
   bool instrumentModule(Module &M, DomTreeCallback DTCallback,
                         PostDomTreeCallback PDTCallback);
 
@@ -215,15 +213,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
 
  public:
   ModuleSanitizerCoverageLegacyPass(
-      const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()
-#if LLVM_VERSION_MAJOR >= 11
-          ,
-      const std::vector<std::string> &AllowlistFiles =
-          std::vector<std::string>(),
-      const std::vector<std::string> &BlocklistFiles =
-          std::vector<std::string>()
-#endif
-          )
+      const SanitizerCoverageOptions &Options = SanitizerCoverageOptions())
       : ModulePass(ID), Options(Options) {
 
     initializeModuleSanitizerCoverageLegacyPassPass(
@@ -233,12 +223,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
 
   bool runOnModule(Module &M) override {
 
-    ModuleSanitizerCoverage ModuleSancov(Options
-#if (LLVM_VERSION_MAJOR >= 11)
-                                         ,
-                                         Allowlist.get(), Blocklist.get()
-#endif
-    );
+    ModuleSanitizerCoverageAFL ModuleSancov(Options);
     auto DTCallback = [this](Function &F) -> const DominatorTree * {
 
       return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
@@ -256,8 +241,8 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
 
   }
 
-  static char ID;  // Pass identification, replacement for typeid
-  StringRef   getPassName() const override {
+  /*static*/ char ID;  // Pass identification, replacement for typeid
+  StringRef       getPassName() const override {
 
     return "ModuleSanitizerCoverage";
 
@@ -273,22 +258,39 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
  private:
   SanitizerCoverageOptions Options;
 
-  std::unique_ptr<SpecialCaseList> Allowlist;
-  std::unique_ptr<SpecialCaseList> Blocklist;
-
 };
 
 }  // namespace
 
-PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &               M,
-                                                   ModuleAnalysisManager &MAM) {
+#if 1
+
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+  #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(ModuleSanitizerCoverageAFL());
+
+                });
+
+          }};
+
+}
 
-  ModuleSanitizerCoverage ModuleSancov(Options
-#if (LLVM_VERSION_MAJOR >= 11)
-                                       ,
-                                       Allowlist.get(), Blocklist.get()
 #endif
-  );
+
+PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &               M,
+                                                  ModuleAnalysisManager &MAM) {
+
+  ModuleSanitizerCoverageAFL ModuleSancov(Options);
   auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
   auto  DTCallback = [&FAM](Function &F) -> const DominatorTree * {
 
@@ -308,7 +310,7 @@ PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &               M,
 
 }
 
-std::pair<Value *, Value *> ModuleSanitizerCoverage::CreateSecStartEnd(
+std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd(
     Module &M, const char *Section, Type *Ty) {
 
   GlobalVariable *SecStart = new GlobalVariable(
@@ -332,7 +334,7 @@ std::pair<Value *, Value *> ModuleSanitizerCoverage::CreateSecStartEnd(
 
 }
 
-Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
+Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
     Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty,
     const char *Section) {
 
@@ -373,7 +375,7 @@ Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
 
 }
 
-bool ModuleSanitizerCoverage::instrumentModule(
+bool ModuleSanitizerCoverageAFL::instrumentModule(
     Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   setvbuf(stdout, NULL, _IONBF, 0);
@@ -656,7 +658,7 @@ bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
 
 }
 
-void ModuleSanitizerCoverage::instrumentFunction(
+void ModuleSanitizerCoverageAFL::instrumentFunction(
     Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   if (F.empty()) return;
@@ -742,7 +744,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
 
 }
 
-GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
+GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
     size_t NumElements, Function &F, Type *Ty, const char *Section) {
 
   ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);
@@ -778,7 +780,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
 
 }
 
-GlobalVariable *ModuleSanitizerCoverage::CreatePCArray(
+GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
     Function &F, ArrayRef<BasicBlock *> AllBlocks) {
 
   size_t N = AllBlocks.size();
@@ -814,7 +816,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreatePCArray(
 
 }
 
-void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
+void ModuleSanitizerCoverageAFL::CreateFunctionLocalArrays(
     Function &F, ArrayRef<BasicBlock *> AllBlocks, uint32_t special) {
 
   if (Options.TracePCGuard)
@@ -833,9 +835,8 @@ void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
 
 }
 
-bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
-                                             ArrayRef<BasicBlock *> AllBlocks,
-                                             bool IsLeafFunc) {
+bool ModuleSanitizerCoverageAFL::InjectCoverage(
+    Function &F, ArrayRef<BasicBlock *> AllBlocks, bool IsLeafFunc) {
 
   uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0;
 
@@ -931,6 +932,15 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
 
         IRBuilder<> IRB(callInst);
 
+        if (!FunctionGuardArray) {
+
+          fprintf(stderr,
+                  "SANCOV: FunctionGuardArray is NULL, failed to emit "
+                  "instrumentation.");
+          continue;
+
+        }
+
         Value *GuardPtr = IRB.CreateIntToPtr(
             IRB.CreateAdd(
                 IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
@@ -938,7 +948,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
             Int32PtrTy);
 
         LoadInst *Idx = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr);
-        ModuleSanitizerCoverage::SetNoSanitizeMetadata(Idx);
+        ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Idx);
 
         callInst->setOperand(1, Idx);
 
@@ -956,6 +966,15 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
 
         if (t->getTypeID() == llvm::Type::IntegerTyID) {
 
+          if (!FunctionGuardArray) {
+
+            fprintf(stderr,
+                    "SANCOV: FunctionGuardArray is NULL, failed to emit "
+                    "instrumentation.");
+            continue;
+
+          }
+
           auto GuardPtr1 = IRB.CreateIntToPtr(
               IRB.CreateAdd(
                   IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
@@ -992,6 +1011,15 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
                   FixedVectorType::get(Int32PtrTy, elements);
               Value *x, *y;
 
+              if (!FunctionGuardArray) {
+
+                fprintf(stderr,
+                        "SANCOV: FunctionGuardArray is NULL, failed to emit "
+                        "instrumentation.");
+                continue;
+
+              }
+
               Value *val1 = IRB.CreateIntToPtr(
                   IRB.CreateAdd(
                       IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
@@ -1060,7 +1088,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
 
         LoadInst *MapPtr =
             IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
-        ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
+        ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr);
 
         /*
             std::string errMsg;
@@ -1079,7 +1107,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
           if (!vector_cnt) {
 
             CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), result);
-            ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc);
+            ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc);
             MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc);
 
           } else {
@@ -1087,7 +1115,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
             auto element = IRB.CreateExtractElement(result, vector_cur++);
             auto elementptr = IRB.CreateIntToPtr(element, Int32PtrTy);
             auto elementld = IRB.CreateLoad(IRB.getInt32Ty(), elementptr);
-            ModuleSanitizerCoverage::SetNoSanitizeMetadata(elementld);
+            ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(elementld);
             MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, elementld);
 
           }
@@ -1103,7 +1131,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
           } else {
 
             LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx);
-            ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
+            ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter);
 
             /* Update bitmap */
 
@@ -1118,7 +1146,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
             }
 
             StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx);
-            ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx);
+            ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx);
 
           }
 
@@ -1165,7 +1193,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &             F,
 //     The cache is used to speed up recording the caller-callee pairs.
 // The address of the caller is passed implicitly via caller PC.
 // CacheSize is encoded in the name of the run-time function.
-void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
+void ModuleSanitizerCoverageAFL::InjectCoverageForIndirectCalls(
     Function &F, ArrayRef<Instruction *> IndirCalls) {
 
   if (IndirCalls.empty()) return;
@@ -1185,7 +1213,7 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
 // __sanitizer_cov_trace_switch(CondValue,
 //      {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
 
-void ModuleSanitizerCoverage::InjectTraceForSwitch(
+void ModuleSanitizerCoverageAFL::InjectTraceForSwitch(
     Function &, ArrayRef<Instruction *> SwitchTraceTargets) {
 
   for (auto I : SwitchTraceTargets) {
@@ -1236,7 +1264,7 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch(
 
 }
 
-void ModuleSanitizerCoverage::InjectTraceForDiv(
+void ModuleSanitizerCoverageAFL::InjectTraceForDiv(
     Function &, ArrayRef<BinaryOperator *> DivTraceTargets) {
 
   for (auto BO : DivTraceTargets) {
@@ -1256,7 +1284,7 @@ void ModuleSanitizerCoverage::InjectTraceForDiv(
 
 }
 
-void ModuleSanitizerCoverage::InjectTraceForGep(
+void ModuleSanitizerCoverageAFL::InjectTraceForGep(
     Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) {
 
   for (auto GEP : GepTraceTargets) {
@@ -1271,7 +1299,7 @@ void ModuleSanitizerCoverage::InjectTraceForGep(
 
 }
 
-void ModuleSanitizerCoverage::InjectTraceForCmp(
+void ModuleSanitizerCoverageAFL::InjectTraceForCmp(
     Function &, ArrayRef<Instruction *> CmpTraceTargets) {
 
   for (auto I : CmpTraceTargets) {
@@ -1313,9 +1341,10 @@ void ModuleSanitizerCoverage::InjectTraceForCmp(
 
 }
 
-void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
-                                                    size_t Idx,
-                                                    bool   IsLeafFunc) {
+void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function &  F,
+                                                       BasicBlock &BB,
+                                                       size_t      Idx,
+                                                       bool        IsLeafFunc) {
 
   BasicBlock::iterator IP = BB.getFirstInsertionPt();
   bool                 IsEntryBB = &BB == &F.getEntryBlock();
@@ -1348,12 +1377,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
         Int32PtrTy);
 
     LoadInst *CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr);
-    ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc);
+    ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc);
 
     /* Load SHM pointer */
 
     LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
-    ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
+    ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr);
 
     /* Load counter for CurLoc */
 
@@ -1370,7 +1399,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     } else {
 
       LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
+      ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter);
 
       /* Update bitmap */
 
@@ -1385,7 +1414,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
       }
 
       StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx);
-      ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx);
+      ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx);
 
     }
 
@@ -1450,7 +1479,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
 
 }
 
-std::string ModuleSanitizerCoverage::getSectionName(
+std::string ModuleSanitizerCoverageAFL::getSectionName(
     const std::string &Section) const {
 
   if (TargetTriple.isOSBinFormatCOFF()) {
@@ -1467,7 +1496,7 @@ std::string ModuleSanitizerCoverage::getSectionName(
 
 }
 
-std::string ModuleSanitizerCoverage::getSectionStart(
+std::string ModuleSanitizerCoverageAFL::getSectionStart(
     const std::string &Section) const {
 
   if (TargetTriple.isOSBinFormatMachO())
@@ -1476,7 +1505,7 @@ std::string ModuleSanitizerCoverage::getSectionStart(
 
 }
 
-std::string ModuleSanitizerCoverage::getSectionEnd(
+std::string ModuleSanitizerCoverageAFL::getSectionEnd(
     const std::string &Section) const {
 
   if (TargetTriple.isOSBinFormatMachO())
@@ -1485,8 +1514,9 @@ std::string ModuleSanitizerCoverage::getSectionEnd(
 
 }
 
-char ModuleSanitizerCoverageLegacyPass::ID = 0;
+#if 0
 
+char ModuleSanitizerCoverageLegacyPass::ID = 0;
 INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
                       "Pass for instrumenting coverage on functions", false,
                       false)
@@ -1495,36 +1525,15 @@ INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
 INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
                     "Pass for instrumenting coverage on functions", false,
                     false)
-
 ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
-    const SanitizerCoverageOptions &Options
-#if (LLVM_VERSION_MAJOR >= 11)
-    ,
+    const SanitizerCoverageOptions &Options,
     const std::vector<std::string> &AllowlistFiles,
-    const std::vector<std::string> &BlocklistFiles
-#endif
-) {
-
-  return new ModuleSanitizerCoverageLegacyPass(Options
-#if (LLVM_VERSION_MAJOR >= 11)
-                                               ,
-                                               AllowlistFiles, BlocklistFiles
-#endif
-  );
+    const std::vector<std::string> &BlocklistFiles) {
 
-}
-
-void registerPCGUARDPass(const PassManagerBuilder &,
-                         legacy::PassManagerBase &PM) {
-
-  auto p = new ModuleSanitizerCoverageLegacyPass();
-  PM.add(p);
+  return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles,
+                                               BlocklistFiles);
 
 }
 
-RegisterStandardPasses RegisterCompTransPass(
-    PassManagerBuilder::EP_OptimizerLast, registerPCGUARDPass);
-
-RegisterStandardPasses RegisterCompTransPass0(
-    PassManagerBuilder::EP_EnabledOnOptLevel0, registerPCGUARDPass);
+#endif
 
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index 39124660..31aaab07 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -39,7 +39,13 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+#endif
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/DebugInfo.h"
@@ -64,6 +70,17 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+class AFLdict2filePass : public PassInfoMixin<AFLdict2filePass> {
+
+  std::ofstream of;
+  void          dict2file(u8 *, u32);
+
+ public:
+  AFLdict2filePass() {
+
+#else
+
 class AFLdict2filePass : public ModulePass {
 
   std::ofstream of;
@@ -74,16 +91,48 @@ class AFLdict2filePass : public ModulePass {
 
   AFLdict2filePass() : ModulePass(ID) {
 
+#endif
+
     if (getenv("AFL_DEBUG")) debug = 1;
 
   }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
   bool runOnModule(Module &M) override;
+#endif
 
 };
 
 }  // namespace
 
+#if LLVM_MAJOR >= 11
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "AFLdict2filePass", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+  #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(AFLdict2filePass());
+
+                });
+
+          }};
+
+}
+
+#else
+char AFLdict2filePass::ID = 0;
+#endif
+
 void AFLdict2filePass::dict2file(u8 *mem, u32 len) {
 
   u32  i, j, binary = 0;
@@ -123,8 +172,14 @@ void AFLdict2filePass::dict2file(u8 *mem, u32 len) {
 
 }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+PreservedAnalyses AFLdict2filePass::run(Module &M, ModuleAnalysisManager &MAM) {
+
+#else
 bool AFLdict2filePass::runOnModule(Module &M) {
 
+#endif
+
   DenseMap<Value *, std::string *> valueMap;
   char *                           ptr;
   int                              found = 0;
@@ -435,7 +490,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
           if (!HasStr2) {
 
             auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
-            if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+            if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
 
               if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
 
@@ -481,15 +536,17 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
                 }
 
-                if (optLength > Str2.length()) { optLength = Str2.length(); }
-
               }
 
               valueMap[Str1P] = new std::string(Str2);
 
-              if (debug)
+              if (debug) {
+
                 fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(),
                         (void *)Str1P);
+
+              }
+
               continue;
 
             }
@@ -519,7 +576,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
             auto Ptr = dyn_cast<ConstantExpr>(Str1P);
 
-            if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+            if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
 
               if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
 
@@ -658,12 +715,16 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
   }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  auto PA = PreservedAnalyses::all();
+  return PA;
+#else
   return true;
+#endif
 
 }
 
-char AFLdict2filePass::ID = 0;
-
+#if LLVM_VERSION_MAJOR < 11                         /* use old pass manager */
 static void registerAFLdict2filePass(const PassManagerBuilder &,
                                      legacy::PassManagerBase &PM) {
 
@@ -681,3 +742,5 @@ static RegisterStandardPasses RegisterAFLdict2filePass(
 static RegisterStandardPasses RegisterAFLdict2filePass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLdict2filePass);
 
+#endif
+
diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
index 35ba9c5a..70c6b10d 100644
--- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
@@ -43,9 +43,16 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+//#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/IR/PassManager.h"
 #include "llvm/IR/CFG.h"
+#if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
+  #include "llvm/Passes/OptimizationLevel.h"
+#endif
 
 #include "afl-llvm-common.h"
 
@@ -53,11 +60,10 @@ using namespace llvm;
 
 namespace {
 
-class AFLcheckIfInstrument : public ModulePass {
+class AFLcheckIfInstrument : public PassInfoMixin<AFLcheckIfInstrument> {
 
  public:
-  static char ID;
-  AFLcheckIfInstrument() : ModulePass(ID) {
+  AFLcheckIfInstrument() {
 
     if (getenv("AFL_DEBUG")) debug = 1;
 
@@ -65,12 +71,7 @@ class AFLcheckIfInstrument : public ModulePass {
 
   }
 
-  bool runOnModule(Module &M) override;
-
-  // StringRef getPassName() const override {
-
-  //  return "American Fuzzy Lop Instrumentation";
-  // }
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
 
  protected:
   std::list<std::string> myInstrumentList;
@@ -79,9 +80,29 @@ class AFLcheckIfInstrument : public ModulePass {
 
 }  // namespace
 
-char AFLcheckIfInstrument::ID = 0;
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "AFLcheckIfInstrument", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+#if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+#endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(AFLcheckIfInstrument());
+
+                });
+
+          }};
 
-bool AFLcheckIfInstrument::runOnModule(Module &M) {
+}
+
+PreservedAnalyses AFLcheckIfInstrument::run(Module &               M,
+                                            ModuleAnalysisManager &MAM) {
 
   /* Show a banner */
 
@@ -130,10 +151,12 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
 
   }
 
-  return true;
+  auto PA = PreservedAnalyses::all();
+  return PA;
 
 }
 
+#if 0
 static void registerAFLcheckIfInstrumentpass(const PassManagerBuilder &,
                                              legacy::PassManagerBase &PM) {
 
@@ -148,4 +171,5 @@ static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass(
 static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0,
     registerAFLcheckIfInstrumentpass);
+#endif
 
diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc
index 5246ba08..fde785bd 100644
--- a/instrumentation/afl-llvm-pass.so.cc
+++ b/instrumentation/afl-llvm-pass.so.cc
@@ -44,13 +44,22 @@
 typedef long double max_align_t;
 #endif
 
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Pass.h"
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
+  #include "llvm/Passes/OptimizationLevel.h"
+#endif
 
 #if LLVM_VERSION_MAJOR >= 4 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
@@ -61,6 +70,8 @@ typedef long double max_align_t;
   #include "llvm/Support/CFG.h"
 #endif
 
+#include "llvm/IR/IRBuilder.h"
+
 #include "afl-llvm-common.h"
 #include "llvm-alternative-coverage.h"
 
@@ -68,17 +79,30 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+class AFLCoverage : public PassInfoMixin<AFLCoverage> {
+
+ public:
+  AFLCoverage() {
+
+#else
 class AFLCoverage : public ModulePass {
 
  public:
   static char ID;
   AFLCoverage() : ModulePass(ID) {
 
+#endif
+
     initInstrumentList();
 
   }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
   bool runOnModule(Module &M) override;
+#endif
 
  protected:
   uint32_t    ngram_size = 0;
@@ -92,7 +116,55 @@ class AFLCoverage : public ModulePass {
 
 }  // namespace
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if 1
+    #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+    #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(AFLCoverage());
+
+                });
+
+  /* TODO LTO registration */
+  #else
+            using PipelineElement = typename PassBuilder::PipelineElement;
+            PB.registerPipelineParsingCallback([](StringRef          Name,
+                                                  ModulePassManager &MPM,
+                                                  ArrayRef<PipelineElement>) {
+
+              if (Name == "AFLCoverage") {
+
+                MPM.addPass(AFLCoverage());
+                return true;
+
+              } else {
+
+                return false;
+
+              }
+
+            });
+
+  #endif
+
+          }};
+
+}
+
+#else
+
 char AFLCoverage::ID = 0;
+#endif
 
 /* needed up to 3.9.0 */
 #if LLVM_VERSION_MAJOR == 3 && \
@@ -118,8 +190,15 @@ uint64_t PowerOf2Ceil(unsigned in) {
     (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
   #define AFL_HAVE_VECTOR_INTRINSICS 1
 #endif
+
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) {
+
+#else
 bool AFLCoverage::runOnModule(Module &M) {
 
+#endif
+
   LLVMContext &C = M.getContext();
 
   IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
@@ -133,6 +212,10 @@ bool AFLCoverage::runOnModule(Module &M) {
   u32             rand_seed;
   unsigned int    cur_loc = 0;
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  auto PA = PreservedAnalyses::all();
+#endif
+
   /* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
   gettimeofday(&tv, &tz);
   rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
@@ -997,10 +1080,15 @@ bool AFLCoverage::runOnModule(Module &M) {
 
   }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  return PA;
+#else
   return true;
+#endif
 
 }
 
+#if LLVM_VERSION_MAJOR < 11                         /* use old pass manager */
 static void registerAFLPass(const PassManagerBuilder &,
                             legacy::PassManagerBase &PM) {
 
@@ -1013,4 +1101,5 @@ static RegisterStandardPasses RegisterAFLPass(
 
 static RegisterStandardPasses RegisterAFLPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);
+#endif
 
diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc
index 310f5585..fd7930a1 100644
--- a/instrumentation/cmplog-instructions-pass.cc
+++ b/instrumentation/cmplog-instructions-pass.cc
@@ -28,14 +28,23 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#if LLVM_MAJOR >= 11
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
+#if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
+  #include "llvm/Passes/OptimizationLevel.h"
+#endif
 
 #if LLVM_VERSION_MAJOR >= 4 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
@@ -55,6 +64,17 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+class CmpLogInstructions : public PassInfoMixin<CmpLogInstructions> {
+
+ public:
+  CmpLogInstructions() {
+
+    initInstrumentList();
+
+  }
+
+#else
 class CmpLogInstructions : public ModulePass {
 
  public:
@@ -65,19 +85,26 @@ class CmpLogInstructions : public ModulePass {
 
   }
 
-  bool runOnModule(Module &M) override;
+#endif
 
-#if LLVM_VERSION_MAJOR >= 4
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
+  bool      runOnModule(Module &M) override;
+
+  #if LLVM_VERSION_MAJOR >= 4
   StringRef getPassName() const override {
 
-#else
+  #else
   const char *getPassName() const override {
 
-#endif
+  #endif
     return "cmplog instructions";
 
   }
 
+#endif
+
  private:
   bool hookInstrs(Module &M);
 
@@ -85,7 +112,31 @@ class CmpLogInstructions : public ModulePass {
 
 }  // namespace
 
+#if LLVM_MAJOR >= 11
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "cmploginstructions", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+  #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(CmpLogInstructions());
+
+                });
+
+          }};
+
+}
+
+#else
 char CmpLogInstructions::ID = 0;
+#endif
 
 template <class Iterator>
 Iterator Unique(Iterator first, Iterator last) {
@@ -464,7 +515,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
       while (1) {
 
         std::vector<Value *> args;
-        uint32_t             skip = 0;
+        bool                 skip = true;
 
         if (vector_cnt) {
 
@@ -486,16 +537,18 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
                         if (i0) {
 
                           cur_val = (uint64_t)i0->getValue().convertToDouble();
-                          if (last_val0 && last_val0 == cur_val) { skip = 1; }
-                          last_val0 = cur_val;
+                          if (last_val0 && last_val0 == cur_val) { skip = true;
+
+               } last_val0 = cur_val;
 
                         }
 
                         if (i1) {
 
                           cur_val = (uint64_t)i1->getValue().convertToDouble();
-                          if (last_val1 && last_val1 == cur_val) { skip = 1; }
-                          last_val1 = cur_val;
+                          if (last_val1 && last_val1 == cur_val) { skip = true;
+
+               } last_val1 = cur_val;
 
                         }
 
@@ -508,7 +561,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
             if (i0 && i0->uge(0xffffffffffffffff) == false) {
 
               cur_val = i0->getZExtValue();
-              if (last_val0 && last_val0 == cur_val) { skip = 1; }
+              if (last_val0 && last_val0 == cur_val) { skip = true; }
               last_val0 = cur_val;
 
             }
@@ -516,7 +569,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
             if (i1 && i1->uge(0xffffffffffffffff) == false) {
 
               cur_val = i1->getZExtValue();
-              if (last_val1 && last_val1 == cur_val) { skip = 1; }
+              if (last_val1 && last_val1 == cur_val) { skip = true; }
               last_val1 = cur_val;
 
             }
@@ -598,7 +651,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 
         ++cur;
         if (cur >= vector_cnt) { break; }
-        skip = 0;
 
       }
 
@@ -613,8 +665,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 
 }
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+PreservedAnalyses CmpLogInstructions::run(Module &               M,
+                                          ModuleAnalysisManager &MAM) {
+
+#else
 bool CmpLogInstructions::runOnModule(Module &M) {
 
+#endif
+
   if (getenv("AFL_QUIET") == NULL)
     printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
   else
@@ -622,10 +681,15 @@ bool CmpLogInstructions::runOnModule(Module &M) {
   hookInstrs(M);
   verifyModule(M);
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+  return PreservedAnalyses::all();
+#else
   return true;
+#endif
 
 }
 
+#if LLVM_MAJOR < 11                                 /* use old pass manager */
 static void registerCmpLogInstructionsPass(const PassManagerBuilder &,
                                            legacy::PassManagerBase &PM) {
 
@@ -640,9 +704,10 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPass(
 static RegisterStandardPasses RegisterCmpLogInstructionsPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass);
 
-#if LLVM_VERSION_MAJOR >= 11
+  #if LLVM_VERSION_MAJOR >= 11
 static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
     registerCmpLogInstructionsPass);
+  #endif
 #endif
 
diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc
index 2af01a7a..8205cfb0 100644
--- a/instrumentation/cmplog-routines-pass.cc
+++ b/instrumentation/cmplog-routines-pass.cc
@@ -27,7 +27,14 @@
 
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
@@ -36,6 +43,7 @@
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
 
+#include "llvm/IR/IRBuilder.h"
 #if LLVM_VERSION_MAJOR >= 4 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
   #include "llvm/IR/Verifier.h"
@@ -53,29 +61,43 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+class CmpLogRoutines : public PassInfoMixin<CmpLogRoutines> {
+
+ public:
+  CmpLogRoutines() {
+
+#else
 class CmpLogRoutines : public ModulePass {
 
  public:
   static char ID;
   CmpLogRoutines() : ModulePass(ID) {
 
+#endif
+
     initInstrumentList();
 
   }
 
-  bool runOnModule(Module &M) override;
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
+  bool      runOnModule(Module &M) override;
 
-#if LLVM_VERSION_MAJOR >= 4
+  #if LLVM_VERSION_MAJOR >= 4
   StringRef getPassName() const override {
 
-#else
+  #else
   const char *getPassName() const override {
 
-#endif
+  #endif
     return "cmplog routines";
 
   }
 
+#endif
+
  private:
   bool hookRtns(Module &M);
 
@@ -83,7 +105,31 @@ class CmpLogRoutines : public ModulePass {
 
 }  // namespace
 
+#if LLVM_MAJOR >= 11
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "cmplogroutines", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+  #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(CmpLogRoutines());
+
+                });
+
+          }};
+
+}
+
+#else
 char CmpLogRoutines::ID = 0;
+#endif
 
 bool CmpLogRoutines::hookRtns(Module &M) {
 
@@ -697,19 +743,33 @@ bool CmpLogRoutines::hookRtns(Module &M) {
 
 }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+PreservedAnalyses CmpLogRoutines::run(Module &M, ModuleAnalysisManager &MAM) {
+
+#else
 bool CmpLogRoutines::runOnModule(Module &M) {
 
+#endif
+
   if (getenv("AFL_QUIET") == NULL)
     printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
   else
     be_quiet = 1;
   hookRtns(M);
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  auto PA = PreservedAnalyses::all();
+#endif
   verifyModule(M);
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  return PA;
+#else
   return true;
+#endif
 
 }
 
+#if LLVM_VERSION_MAJOR < 11                         /* use old pass manager */
 static void registerCmpLogRoutinesPass(const PassManagerBuilder &,
                                        legacy::PassManagerBase &PM) {
 
@@ -724,9 +784,10 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPass(
 static RegisterStandardPasses RegisterCmpLogRoutinesPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass);
 
-#if LLVM_VERSION_MAJOR >= 11
+  #if LLVM_VERSION_MAJOR >= 11
 static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
     registerCmpLogRoutinesPass);
+  #endif
 #endif
 
diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc
index 068650ce..37bf3889 100644
--- a/instrumentation/cmplog-switches-pass.cc
+++ b/instrumentation/cmplog-switches-pass.cc
@@ -28,7 +28,14 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
@@ -37,6 +44,7 @@
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
 
+#include "llvm/IR/IRBuilder.h"
 #if LLVM_VERSION_MAJOR >= 4 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
   #include "llvm/IR/Verifier.h"
@@ -54,29 +62,42 @@ using namespace llvm;
 
 namespace {
 
-class CmpLogInstructions : public ModulePass {
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+class CmplogSwitches : public PassInfoMixin<CmplogSwitches> {
+
+ public:
+  CmplogSwitches() {
+
+#else
+class CmplogSwitches : public ModulePass {
 
  public:
   static char ID;
-  CmpLogInstructions() : ModulePass(ID) {
+  CmplogSwitches() : ModulePass(ID) {
 
+#endif
     initInstrumentList();
 
   }
 
-  bool runOnModule(Module &M) override;
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
+  bool        runOnModule(Module &M) override;
 
-#if LLVM_VERSION_MAJOR < 4
+  #if LLVM_VERSION_MAJOR < 4
   const char *getPassName() const override {
 
-#else
+  #else
   StringRef getPassName() const override {
 
-#endif
-    return "cmplog instructions";
+  #endif
+    return "cmplog switch split";
 
   }
 
+#endif
+
  private:
   bool hookInstrs(Module &M);
 
@@ -84,7 +105,31 @@ class CmpLogInstructions : public ModulePass {
 
 }  // namespace
 
-char CmpLogInstructions::ID = 0;
+#if LLVM_MAJOR >= 11
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "cmplogswitches", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+  #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(CmplogSwitches());
+
+                });
+
+          }};
+
+}
+
+#else
+char CmplogSwitches::ID = 0;
+#endif
 
 template <class Iterator>
 Iterator Unique(Iterator first, Iterator last) {
@@ -101,7 +146,7 @@ Iterator Unique(Iterator first, Iterator last) {
 
 }
 
-bool CmpLogInstructions::hookInstrs(Module &M) {
+bool CmplogSwitches::hookInstrs(Module &M) {
 
   std::vector<SwitchInst *> switches;
   LLVMContext &             C = M.getContext();
@@ -383,36 +428,51 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 
 }
 
-bool CmpLogInstructions::runOnModule(Module &M) {
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+PreservedAnalyses CmplogSwitches::run(Module &M, ModuleAnalysisManager &MAM) {
+
+#else
+bool CmplogSwitches::runOnModule(Module &M) {
+
+#endif
 
   if (getenv("AFL_QUIET") == NULL)
     printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
   else
     be_quiet = 1;
   hookInstrs(M);
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  auto PA = PreservedAnalyses::all();
+#endif
   verifyModule(M);
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  return PA;
+#else
   return true;
+#endif
 
 }
 
-static void registerCmpLogInstructionsPass(const PassManagerBuilder &,
-                                           legacy::PassManagerBase &PM) {
+#if LLVM_VERSION_MAJOR < 11                         /* use old pass manager */
+static void registerCmplogSwitchesPass(const PassManagerBuilder &,
+                                       legacy::PassManagerBase &PM) {
 
-  auto p = new CmpLogInstructions();
+  auto p = new CmplogSwitches();
   PM.add(p);
 
 }
 
-static RegisterStandardPasses RegisterCmpLogInstructionsPass(
-    PassManagerBuilder::EP_OptimizerLast, registerCmpLogInstructionsPass);
+static RegisterStandardPasses RegisterCmplogSwitchesPass(
+    PassManagerBuilder::EP_OptimizerLast, registerCmplogSwitchesPass);
 
-static RegisterStandardPasses RegisterCmpLogInstructionsPass0(
-    PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass);
+static RegisterStandardPasses RegisterCmplogSwitchesPass0(
+    PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmplogSwitchesPass);
 
-#if LLVM_VERSION_MAJOR >= 11
-static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO(
+  #if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCmplogSwitchesPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
-    registerCmpLogInstructionsPass);
+    registerCmplogSwitchesPass);
+  #endif
 #endif
 
diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc
index c3a4ee34..34c88735 100644
--- a/instrumentation/compare-transform-pass.so.cc
+++ b/instrumentation/compare-transform-pass.so.cc
@@ -26,14 +26,23 @@
 
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
+#if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
+  #include "llvm/Passes/OptimizationLevel.h"
+#endif
 
 #if LLVM_VERSION_MAJOR >= 4 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
@@ -52,29 +61,46 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+class CompareTransform : public PassInfoMixin<CompareTransform> {
+
+ public:
+  CompareTransform() {
+
+#else
 class CompareTransform : public ModulePass {
 
  public:
   static char ID;
   CompareTransform() : ModulePass(ID) {
 
+#endif
+
     initInstrumentList();
 
   }
 
-  bool runOnModule(Module &M) override;
-
-#if LLVM_VERSION_MAJOR >= 4
+#if LLVM_MAJOR < 11
+  #if LLVM_VERSION_MAJOR >= 4
   StringRef getPassName() const override {
 
-#else
+  #else
   const char *getPassName() const override {
 
-#endif
-    return "transforms compare functions";
+  #endif
+
+    return "cmplog transform";
 
   }
 
+#endif
+
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
+  bool runOnModule(Module &M) override;
+#endif
+
  private:
   bool transformCmps(Module &M, const bool processStrcmp,
                      const bool processMemcmp, const bool processStrncmp,
@@ -85,7 +111,54 @@ class CompareTransform : public ModulePass {
 
 }  // namespace
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if 1
+    #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+    #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(CompareTransform());
+
+                });
+
+  /* TODO LTO registration */
+  #else
+            using PipelineElement = typename PassBuilder::PipelineElement;
+            PB.registerPipelineParsingCallback([](StringRef          Name,
+                                                  ModulePassManager &MPM,
+                                                  ArrayRef<PipelineElement>) {
+
+              if (Name == "comparetransform") {
+
+                MPM.addPass(CompareTransform());
+                return true;
+
+              } else {
+
+                return false;
+
+              }
+
+            });
+
+  #endif
+
+          }};
+
+}
+
+#else
 char CompareTransform::ID = 0;
+#endif
 
 bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
                                      const bool processMemcmp,
@@ -103,7 +176,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 #if LLVM_VERSION_MAJOR >= 9
   FunctionCallee tolowerFn;
 #else
-  Function *  tolowerFn;
+  Function *tolowerFn;
 #endif
   {
 
@@ -246,7 +319,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
           if (!(HasStr1 || HasStr2)) {
 
             auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
-            if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+            if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
 
               if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
 
@@ -271,7 +344,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
             if (!HasStr2) {
 
               Ptr = dyn_cast<ConstantExpr>(Str1P);
-              if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+              if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
 
                 if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
 
@@ -385,6 +458,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
     bool        isCaseInsensitive = false;
     bool        needs_null = false;
     Function *  Callee = callInst->getCalledFunction();
+
     if (Callee) {
 
       if (!Callee->getName().compare("memcmp") ||
@@ -642,8 +716,14 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 
 }
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) {
+
+#else
 bool CompareTransform::runOnModule(Module &M) {
 
+#endif
+
   if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
     printf(
         "Running compare-transform-pass by laf.intel@gmail.com, extended by "
@@ -651,13 +731,28 @@ bool CompareTransform::runOnModule(Module &M) {
   else
     be_quiet = 1;
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+  auto PA = PreservedAnalyses::all();
+#endif
+
   transformCmps(M, true, true, true, true, true);
   verifyModule(M);
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+                     /*  if (modified) {
+                   
+                         PA.abandon<XX_Manager>();
+                   
+                       }*/
+
+  return PA;
+#else
   return true;
+#endif
 
 }
 
+#if LLVM_MAJOR < 11                                 /* use old pass manager */
 static void registerCompTransPass(const PassManagerBuilder &,
                                   legacy::PassManagerBase &PM) {
 
@@ -672,8 +767,9 @@ static RegisterStandardPasses RegisterCompTransPass(
 static RegisterStandardPasses RegisterCompTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
 
-#if LLVM_VERSION_MAJOR >= 11
+  #if LLVM_VERSION_MAJOR >= 11
 static RegisterStandardPasses RegisterCompTransPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass);
+  #endif
 #endif
 
diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc
index 0f00fa96..d7bb7aba 100644
--- a/instrumentation/split-compares-pass.so.cc
+++ b/instrumentation/split-compares-pass.so.cc
@@ -1,6 +1,7 @@
 /*
  * Copyright 2016 laf-intel
  * extended for floating point by Heiko Eißfeldt
+ * adapted to new pass manager by Heiko Eißfeldt
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,10 +29,20 @@
 
 #include "llvm/Pass.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+
+#if LLVM_MAJOR >= 11
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/IR/Module.h"
+#if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
+  #include "llvm/Passes/OptimizationLevel.h"
+#endif
 
 #include "llvm/IR/IRBuilder.h"
 #if LLVM_VERSION_MAJOR >= 4 || \
@@ -53,27 +64,31 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_MAJOR >= 11
+class SplitComparesTransform : public PassInfoMixin<SplitComparesTransform> {
+
+ public:
+  //  static char ID;
+  SplitComparesTransform() : enableFPSplit(0) {
+
+#else
 class SplitComparesTransform : public ModulePass {
 
  public:
   static char ID;
   SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) {
 
+#endif
+
     initInstrumentList();
 
   }
 
-  bool runOnModule(Module &M) override;
-#if LLVM_VERSION_MAJOR >= 4
-  StringRef getPassName() const override {
-
+#if LLVM_MAJOR >= 11
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
 #else
-  const char *getPassName() const override {
-
+  bool runOnModule(Module &M) override;
 #endif
-    return "AFL_SplitComparesTransform";
-
-  }
 
  private:
   int enableFPSplit;
@@ -162,7 +177,54 @@ class SplitComparesTransform : public ModulePass {
 
 }  // namespace
 
+#if LLVM_MAJOR >= 11
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "splitcompares", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if 1
+    #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+    #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(SplitComparesTransform());
+
+                });
+
+  /* TODO LTO registration */
+  #else
+            using PipelineElement = typename PassBuilder::PipelineElement;
+            PB.registerPipelineParsingCallback([](StringRef          Name,
+                                                  ModulePassManager &MPM,
+                                                  ArrayRef<PipelineElement>) {
+
+              if (Name == "splitcompares") {
+
+                MPM.addPass(SplitComparesTransform());
+                return true;
+
+              } else {
+
+                return false;
+
+              }
+
+            });
+
+  #endif
+
+          }};
+
+}
+
+#else
 char SplitComparesTransform::ID = 0;
+#endif
 
 /// This function splits FCMP instructions with xGE or xLE predicates into two
 /// FCMP instructions with predicate xGT or xLT and EQ
@@ -1421,8 +1483,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
 }
 
+#if LLVM_MAJOR >= 11
+PreservedAnalyses SplitComparesTransform::run(Module &               M,
+                                              ModuleAnalysisManager &MAM) {
+
+#else
 bool SplitComparesTransform::runOnModule(Module &M) {
 
+#endif
+
   char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW");
   if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW");
   if (bitw_env) { target_bitwidth = atoi(bitw_env); }
@@ -1432,7 +1501,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
   if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
       getenv("AFL_DEBUG") != NULL) {
 
-    errs() << "Split-compare-pass by laf.intel@gmail.com, extended by "
+    errs() << "Split-compare-newpass by laf.intel@gmail.com, extended by "
               "heiko@hexco.de (splitting icmp to "
            << target_bitwidth << " bit)\n";
 
@@ -1444,6 +1513,10 @@ bool SplitComparesTransform::runOnModule(Module &M) {
 
   }
 
+#if LLVM_MAJOR >= 11
+  auto PA = PreservedAnalyses::all();
+#endif
+
   if (enableFPSplit) {
 
     simplifyFPCompares(M);
@@ -1473,7 +1546,16 @@ bool SplitComparesTransform::runOnModule(Module &M) {
 
           auto op0 = CI->getOperand(0);
           auto op1 = CI->getOperand(1);
-          if (!op0 || !op1) { return false; }
+          if (!op0 || !op1) {
+
+#if LLVM_MAJOR >= 11
+            return PA;
+#else
+            return false;
+#endif
+
+          }
+
           auto iTy1 = dyn_cast<IntegerType>(op0->getType());
           if (iTy1 && isa<IntegerType>(op1->getType())) {
 
@@ -1522,10 +1604,29 @@ bool SplitComparesTransform::runOnModule(Module &M) {
 
   }
 
+  if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
+      getenv("AFL_DEBUG") != NULL) {
+
+    errs() << count << " comparisons found\n";
+
+  }
+
+#if LLVM_MAJOR >= 11
+  /*  if (modified) {
+
+      PA.abandon<XX_Manager>();
+
+    }*/
+
+  return PA;
+#else
   return true;
+#endif
 
 }
 
+#if LLVM_MAJOR < 11                                 /* use old pass manager */
+
 static void registerSplitComparesPass(const PassManagerBuilder &,
                                       legacy::PassManagerBase &PM) {
 
@@ -1539,14 +1640,15 @@ static RegisterStandardPasses RegisterSplitComparesPass(
 static RegisterStandardPasses RegisterSplitComparesTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
 
-#if LLVM_VERSION_MAJOR >= 11
+  #if LLVM_VERSION_MAJOR >= 11
 static RegisterStandardPasses RegisterSplitComparesTransPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
     registerSplitComparesPass);
-#endif
+  #endif
 
 static RegisterPass<SplitComparesTransform> X("splitcompares",
                                               "AFL++ split compares",
                                               true /* Only looks at CFG */,
                                               true /* Analysis Pass */);
+#endif
 
diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc
index 9f9e7eca..96e01a8b 100644
--- a/instrumentation/split-switches-pass.so.cc
+++ b/instrumentation/split-switches-pass.so.cc
@@ -27,14 +27,23 @@
 
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  #include "llvm/Passes/PassPlugin.h"
+  #include "llvm/Passes/PassBuilder.h"
+  #include "llvm/IR/PassManager.h"
+#else
+  #include "llvm/IR/LegacyPassManager.h"
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
+#if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
+  #include "llvm/Passes/OptimizationLevel.h"
+#endif
 
 #include "llvm/IR/IRBuilder.h"
 #if LLVM_VERSION_MAJOR >= 4 || \
@@ -54,29 +63,42 @@ using namespace llvm;
 
 namespace {
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+class SplitSwitchesTransform : public PassInfoMixin<SplitSwitchesTransform> {
+
+ public:
+  SplitSwitchesTransform() {
+
+#else
 class SplitSwitchesTransform : public ModulePass {
 
  public:
   static char ID;
   SplitSwitchesTransform() : ModulePass(ID) {
 
+#endif
     initInstrumentList();
 
   }
 
-  bool runOnModule(Module &M) override;
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+#else
+  bool      runOnModule(Module &M) override;
 
-#if LLVM_VERSION_MAJOR >= 4
+  #if LLVM_VERSION_MAJOR >= 4
   StringRef getPassName() const override {
 
-#else
+  #else
   const char *getPassName() const override {
 
-#endif
+  #endif
     return "splits switch constructs";
 
   }
 
+#endif
+
   struct CaseExpr {
 
     ConstantInt *Val;
@@ -103,7 +125,54 @@ class SplitSwitchesTransform : public ModulePass {
 
 }  // namespace
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo() {
+
+  return {LLVM_PLUGIN_API_VERSION, "splitswitches", "v0.1",
+          /* lambda to insert our pass into the pass pipeline. */
+          [](PassBuilder &PB) {
+
+  #if 1
+    #if LLVM_VERSION_MAJOR <= 13
+            using OptimizationLevel = typename PassBuilder::OptimizationLevel;
+    #endif
+            PB.registerOptimizerLastEPCallback(
+                [](ModulePassManager &MPM, OptimizationLevel OL) {
+
+                  MPM.addPass(SplitSwitchesTransform());
+
+                });
+
+  /* TODO LTO registration */
+  #else
+            using PipelineElement = typename PassBuilder::PipelineElement;
+            PB.registerPipelineParsingCallback([](StringRef          Name,
+                                                  ModulePassManager &MPM,
+                                                  ArrayRef<PipelineElement>) {
+
+              if (Name == "splitswitches") {
+
+                MPM.addPass(SplitSwitchesTransform());
+                return true;
+
+              } else {
+
+                return false;
+
+              }
+
+            });
+
+  #endif
+
+          }};
+
+}
+
+#else
 char SplitSwitchesTransform::ID = 0;
+#endif
 
 /* switchConvert - Transform simple list of Cases into list of CaseRange's */
 BasicBlock *SplitSwitchesTransform::switchConvert(
@@ -413,19 +482,42 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
 
 }
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+PreservedAnalyses SplitSwitchesTransform::run(Module &               M,
+                                              ModuleAnalysisManager &MAM) {
+
+#else
 bool SplitSwitchesTransform::runOnModule(Module &M) {
 
+#endif
+
   if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
     printf("Running split-switches-pass by laf.intel@gmail.com\n");
   else
     be_quiet = 1;
+
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+  auto PA = PreservedAnalyses::all();
+#endif
+
   splitSwitches(M);
   verifyModule(M);
 
+#if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
+                             /*  if (modified) {
+                           
+                                 PA.abandon<XX_Manager>();
+                           
+                               }*/
+
+  return PA;
+#else
   return true;
+#endif
 
 }
 
+#if LLVM_VERSION_MAJOR < 11                         /* use old pass manager */
 static void registerSplitSwitchesTransPass(const PassManagerBuilder &,
                                            legacy::PassManagerBase &PM) {
 
@@ -440,9 +532,10 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass(
 static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);
 
-#if LLVM_VERSION_MAJOR >= 11
+  #if LLVM_VERSION_MAJOR >= 11
 static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
     registerSplitSwitchesTransPass);
+  #endif
 #endif
 
diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION
index b45b4e90..65e119c9 100644
--- a/nyx_mode/LIBNYX_VERSION
+++ b/nyx_mode/LIBNYX_VERSION
@@ -1 +1 @@
-2e45754
+8a77c71
diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION
index 43488114..d67dee20 100644
--- a/nyx_mode/PACKER_VERSION
+++ b/nyx_mode/PACKER_VERSION
@@ -1 +1 @@
-76100c5
+5d143ee
diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx
-Subproject c2c69cfc528398d9db9363b92f8c50db4008c98
+Subproject c08e4ac94244a9739b4484b3010abc06b372923
diff --git a/nyx_mode/QEMU_NYX_VERSION b/nyx_mode/QEMU_NYX_VERSION
index be13a784..2d9ee5e3 100644
--- a/nyx_mode/QEMU_NYX_VERSION
+++ b/nyx_mode/QEMU_NYX_VERSION
@@ -1 +1 @@
-c2c69cfc52
+c08e4ac942
diff --git a/nyx_mode/custom_harness/example.c b/nyx_mode/custom_harness/example.c
index dd268534..a67d42c6 100644
--- a/nyx_mode/custom_harness/example.c
+++ b/nyx_mode/custom_harness/example.c
@@ -7,7 +7,7 @@
 #define TRACE_BUFFER_SIZE (64)
 
 #define PAGE_SIZE 0x1000
-#define MMAP_SIZE(x) ((x & ~(PAGE_SIZE-1)) + PAGE_SIZE)
+#define MMAP_SIZE(x) ((x & ~(PAGE_SIZE - 1)) + PAGE_SIZE)
 
 int main(int argc, char **argv) {
 
@@ -30,8 +30,9 @@ int main(int argc, char **argv) {
   /* this is our "bitmap" that is later shared with the fuzzer (you can also
    * pass the pointer of the bitmap used by compile-time instrumentations in
    * your target) */
-  uint8_t *trace_buffer = mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | 
-                               PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  uint8_t *trace_buffer =
+      mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | PROT_WRITE,
+           MAP_SHARED | MAP_ANONYMOUS, -1, 0);
   memset(trace_buffer, 0,
          TRACE_BUFFER_SIZE);  // makes sure that the bitmap buffer is already
                               // mapped into the guest's memory (alternatively
diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx
-Subproject 2e45754e271463f446c31a6f467231d8657910e
+Subproject 8a77c71dc8a8c0b73abd8fb9c22e30d565184ef
diff --git a/nyx_mode/packer b/nyx_mode/packer
-Subproject 76100c52db96429350693a6c7284c5c6cbcb6b0
+Subproject 5d143eee4e4dcd12a1fc5d6786dd8da25cbb995
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 0c5c12d3..f39cb77e 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-ce65a7349e
+a120c3feb5
diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl
-Subproject ce65a7349e7156e052b37a660422cad8346764d
+Subproject a120c3feb573d4cade292cdeb7c1f6b1ce109ef
diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile
index eabe6c77..f026a2b7 100644
--- a/qemu_mode/unsigaction/Makefile
+++ b/qemu_mode/unsigaction/Makefile
@@ -12,19 +12,19 @@
 #
 #   http://www.apache.org/licenses/LICENSE-2.0
 #
-.POSIX:
 
-_UNIQ=_QINU_
-
-TARGETCANDIDATES=unsigaction.so
-_TARGETS=$(_UNIQ)$(AFL_NO_X86)$(_UNIQ)
-__TARGETS=$(_TARGETS:$(_UNIQ)1$(_UNIQ)=)
-TARGETS=$(__TARGETS:$(_UNIQ)$(_UNIQ)=$(TARGETCANDIDATES))
+TARGETS=unsigaction.so unsigaction32.so unsigaction64.so
 
 all:  $(TARGETS)
 
 unsigaction.so: unsigaction.c
 	@if $(CC) -fPIC -shared unsigaction.c -o unsigaction.so 2>/dev/null ; then echo "unsigaction build success"; else echo "unsigaction build failure (that's fine)"; fi
 
+unsigaction32.so: unsigaction.c
+	@if $(CC) -fPIC -m32 -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
+
+unsigaction64.so: unsigaction.c
+	@if $(CC) -fPIC -m64 -shared unsigaction.c -o unsigaction64.so 2>/dev/null ; then echo "unsigaction64 build success"; else echo "unsigaction64 build failure (that's fine)"; fi
+
 clean:
 	rm -f unsigaction.so
diff --git a/src/afl-cc.c b/src/afl-cc.c
index ed57ca1e..ffdda386 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -434,81 +434,84 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     if (lto_mode && have_instr_env) {
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] = alloc_printf(
+          "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path);
+#else
       cc_params[cc_par_cnt++] = "-Xclang";
       cc_params[cc_par_cnt++] = "-load";
       cc_params[cc_par_cnt++] = "-Xclang";
       cc_params[cc_par_cnt++] =
           alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
+#endif
 
     }
 
     if (getenv("AFL_LLVM_DICT2FILE")) {
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path);
+#else
       cc_params[cc_par_cnt++] = "-Xclang";
       cc_params[cc_par_cnt++] = "-load";
       cc_params[cc_par_cnt++] = "-Xclang";
       cc_params[cc_par_cnt++] =
           alloc_printf("%s/afl-llvm-dict2file.so", obj_path);
+#endif
 
     }
 
     // laf
     if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
 
-      if (lto_mode && !have_c) {
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
-
-      } else {
-
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/split-switches-pass.so", obj_path);
-
-      }
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
+#else
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/split-switches-pass.so", obj_path);
+#endif
 
     }
 
     if (getenv("LAF_TRANSFORM_COMPARES") ||
         getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
 
-      if (lto_mode && !have_c) {
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/compare-transform-pass.so", obj_path);
-
-      } else {
-
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/compare-transform-pass.so", obj_path);
-
-      }
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path);
+#else
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/compare-transform-pass.so", obj_path);
+#endif
 
     }
 
     if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
         getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
 
-      if (lto_mode && !have_c) {
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/split-compares-pass.so", obj_path);
-
-      } else {
-
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/split-compares-pass.so", obj_path);
-
-      }
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path);
+#else
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/split-compares-pass.so", obj_path);
+#endif
 
     }
 
@@ -519,39 +522,36 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     if (cmplog_mode) {
 
-      if (lto_mode && !have_c) {
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/cmplog-switches-pass.so", obj_path);
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
-
-      } else {
-
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/cmplog-switches-pass.so", obj_path);
-
-        // reuse split switches from laf
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/split-switches-pass.so", obj_path);
+      cc_params[cc_par_cnt++] = "-fno-inline";
 
-      }
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path);
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
+#else
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/cmplog-switches-pass.so", obj_path);
 
-      cc_params[cc_par_cnt++] = "-fno-inline";
+      // reuse split switches from laf
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/split-switches-pass.so", obj_path);
+#endif
 
     }
 
-#if LLVM_MAJOR >= 13
-    // fuck you llvm 13
-    cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager";
-#endif
+    //#if LLVM_MAJOR >= 13
+    //    // Use the old pass manager in LLVM 14 which the afl++ passes still
+    //    use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
+    //#endif
 
     if (lto_mode && !have_c) {
 
@@ -566,7 +566,19 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       }
 
-      if (!ld_path || !*ld_path) { ld_path = strdup("ld.lld"); }
+      if (!ld_path || !*ld_path) {
+
+        if (ld_path) {
+
+          // Freeing empty string
+          free(ld_path);
+
+        }
+
+        ld_path = strdup("ld.lld");
+
+      }
+
       if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); }
 #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12
       cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path);
@@ -575,6 +587,12 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 #endif
       free(ld_path);
 
+#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13
+      cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager";
+#else
+      cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager";
+#endif
+
       cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
       cc_params[cc_par_cnt++] =
           alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
@@ -584,7 +602,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       if (instrument_mode == INSTRUMENT_PCGUARD) {
 
-#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR >= 1)
+#if LLVM_MAJOR >= 11
   #if defined __ANDROID__ || ANDROID
         cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
         instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -601,11 +619,17 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
         } else {
 
+    #if LLVM_MAJOR >= 11                            /* use new pass manager */
+          cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+          cc_params[cc_par_cnt++] = alloc_printf(
+              "-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path);
+    #else
           cc_params[cc_par_cnt++] = "-Xclang";
           cc_params[cc_par_cnt++] = "-load";
           cc_params[cc_par_cnt++] = "-Xclang";
           cc_params[cc_par_cnt++] =
               alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+    #endif
 
         }
 
@@ -633,10 +657,17 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       } else {
 
+#if LLVM_MAJOR >= 11                                /* use new pass manager */
+        cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+        cc_params[cc_par_cnt++] =
+            alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path);
+#else
+
         cc_params[cc_par_cnt++] = "-Xclang";
         cc_params[cc_par_cnt++] = "-load";
         cc_params[cc_par_cnt++] = "-Xclang";
         cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
+#endif
 
       }
 
@@ -644,28 +675,26 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     if (cmplog_mode) {
 
-      if (lto_mode && !have_c) {
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path);
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path);
-
-      } else {
-
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
-
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/cmplog-routines-pass.so", obj_path);
+#if LLVM_MAJOR >= 11
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] = alloc_printf(
+          "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path);
+      cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path);
+#else
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
 
-      }
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/cmplog-routines-pass.so", obj_path);
+#endif
 
     }
 
diff --git a/src/afl-common.c b/src/afl-common.c
index 7c074acc..eca7d272 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -805,10 +805,7 @@ bool extract_and_set_env(u8 *env_str) {
     *rest = '\0';  // done with variable value
 
     rest += 1;
-    if (rest < end && *rest != ' ') { goto free_and_return; }
-
     num_pairs++;
-
     setenv(key, val, 1);
 
   }
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 8997781d..628ff590 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -450,6 +450,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
     fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0);
     fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner);
 
+    fsrv->nyx_aux_string = malloc(0x1000);
+    memset(fsrv->nyx_aux_string, 0, 0x1000);
+
     /* dry run */
     fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, "INIT", 4);
     switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
@@ -1253,7 +1256,13 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
   fsrv->child_pid = -1;
 
 #ifdef __linux__
-  if (fsrv->nyx_mode) { fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); }
+  if (fsrv->nyx_mode) {
+
+    free(fsrv->nyx_aux_string);
+    fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+
+  }
+
 #endif
 
 }
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index b963caf8..99f37cbf 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -423,10 +423,10 @@ void write_crash_readme(afl_state_t *afl) {
       "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n"
 
       "Found any cool bugs in open-source tools using afl-fuzz? If yes, please "
-      "drop\n"
-      "an mail at <afl-users@googlegroups.com> once the issues are fixed\n\n"
-
-      "  https://github.com/AFLplusplus/AFLplusplus\n\n",
+      "post\n"
+      "to https://github.com/AFLplusplus/AFLplusplus/issues/286 once the "
+      "issues\n"
+      " are fixed :)\n\n",
 
       afl->orig_cmdline,
       stringify_mem_size(val_buf, sizeof(val_buf),
@@ -771,6 +771,25 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
   ck_write(fd, mem, len, fn);
   close(fd);
 
+#ifdef __linux__
+  if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {
+
+    u8 fn_log[PATH_MAX];
+
+    (void)(snprintf(fn_log, PATH_MAX, "%s.log", fn) + 1);
+    fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+    if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); }
+
+    u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string(
+        afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, 0x1000);
+
+    ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log);
+    close(fd);
+
+  }
+
+#endif
+
   return keeping;
 
 }
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 1a8052a0..7d94085d 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -49,7 +49,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   u8 fault;
 
-  len = write_to_testcase(afl, out_buf, len, 0);
+  write_to_testcase(afl, out_buf, len, 0);
 
   fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout);
 
@@ -81,14 +81,6 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   }
 
-  /* This handles FAULT_ERROR for us: */
-
-  /* afl->queued_discovered += save_if_interesting(afl, argv, out_buf, len,
-  fault);
-
-  if (!(afl->stage_cur % afl->stats_update_freq) || afl->stage_cur + 1 ==
-  afl->stage_max) show_stats(afl); */
-
   return 0;
 
 }
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 1e4b1b3c..2dbad5cf 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -1969,7 +1969,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
   if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
       ol0 > 31 || ol1 > 31) {
 
-    l0 = l1 = ol0 = ol1 = hshape;
+    l0 = ol0 = hshape;
 
   }
 
@@ -2136,7 +2136,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
       if ((i % 2)) {
 
-        if (len > idx + i && is_hex(orig_buf + idx + i)) {
+        if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) {
 
           fromhex += 2;
 
@@ -2323,7 +2323,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
         if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
         // fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex,
         // *status);
-        memcpy(buf + idx + i, save + i, i + 1 + off);
+        memcpy(buf + idx, save, i + 1 + off);
 
       }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 5da0e583..ffba3475 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -232,7 +232,8 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
 
       memcpy(afl->fsrv.shmem_fuzz, mem, skip_at);
 
-      memcpy(afl->fsrv.shmem_fuzz, mem + skip_at + skip_len, tail_len);
+      memcpy(afl->fsrv.shmem_fuzz + skip_at, mem + skip_at + skip_len,
+             tail_len);
 
     }
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8cc2a62e..cc1240e7 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -167,7 +167,9 @@ static void usage(u8 *argv0, int more_help) {
       "                  See docs/README.MOpt.md\n"
       "  -c program    - enable CmpLog by specifying a binary compiled for "
       "it.\n"
-      "                  if using QEMU, just use -c 0.\n"
+      "                  if using QEMU/FRIDA or if you the fuzzing target is "
+      "compiled"
+      "                  for CmpLog then just use -c 0.\n"
       "  -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
       "                  1=small files, 2=larger files (default), 3=all "
       "files,\n"
@@ -466,6 +468,9 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
       dlsym(handle, "nyx_get_bitmap_buffer_size");
   if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
 
+  plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
+  if (plugin->nyx_get_aux_string == NULL) { goto fail; }
+
   OKF("libnyx plugin is ready!");
   return plugin;
 
@@ -1458,6 +1463,13 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (!afl->use_banner) { afl->use_banner = argv[optind]; }
 
+  if (afl->shm.cmplog_mode &&
+      (!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) {
+
+    afl->cmplog_binary = argv[optind];
+
+  }
+
   if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
 
     WARNF(cLRD
@@ -1675,7 +1687,7 @@ int main(int argc, char **argv_orig, char **envp) {
   if (getenv("LD_PRELOAD")) {
 
     WARNF(
-        "LD_PRELOAD is set, are you sure that is what to you want to do "
+        "LD_PRELOAD is set, are you sure that is what you want to do "
         "instead of using AFL_PRELOAD?");
 
   }
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 9b58125f..5797def8 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -86,7 +86,7 @@ static void edit_params(int argc, char **argv) {
     for (i = 1; i < (u32)argc; i++) {
 
       if (strstr(argv[i], "/afl-llvm-rt-lto.o") != NULL) rt_lto_present = 1;
-      if (strstr(argv[i], "/afl-llvm-rt.o") != NULL) rt_present = 1;
+      if (strstr(argv[i], "/afl-compiler-rt.o") != NULL) rt_present = 1;
       if (strstr(argv[i], "/afl-llvm-lto-instr") != NULL) inst_present = 1;
 
     }
@@ -237,7 +237,8 @@ static void edit_params(int argc, char **argv) {
       }
 
       if (!rt_present)
-        ld_params[ld_param_cnt++] = alloc_printf("%s/afl-llvm-rt.o", afl_path);
+        ld_params[ld_param_cnt++] =
+            alloc_printf("%s/afl-compiler-rt.o", afl_path);
       if (!rt_lto_present)
         ld_params[ld_param_cnt++] =
             alloc_printf("%s/afl-llvm-rt-lto.o", afl_path);
diff --git a/test/test-llvm-lto.sh b/test/test-llvm-lto.sh
index 9ff2ec10..bb4a9f7c 100755
--- a/test/test-llvm-lto.sh
+++ b/test/test-llvm-lto.sh
@@ -49,6 +49,9 @@ test -e ../afl-clang-lto -a -e ../SanitizerCoverageLTO.so && {
     grep -q "No instrumentation targets found" test.out && {
       $ECHO "$GREEN[+] llvm_mode LTO instrumentlist feature works correctly"
     } || {
+	echo CUT------------------------------------------------------------------CUT
+        cat test.out
+        echo CUT------------------------------------------------------------------CUT
       $ECHO "$RED[!] llvm_mode LTO instrumentlist feature failed"
       CODE=1
     }
diff --git a/test/test-qemu-mode.sh b/test/test-qemu-mode.sh
index 85578d55..46b138ff 100755
--- a/test/test-qemu-mode.sh
+++ b/test/test-qemu-mode.sh
@@ -165,11 +165,8 @@ test -e ../afl-qemu-trace && {
             CODE=1
           }
         } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-	  $ECHO "$RED[!] cannot compile test program (32 bit) for unsigaction library"
-          CODE=1
+	  $ECHO "$YELLOW[-] cannot compile test program (32 bit) for unsigaction library"
+          INCOMPLETE=1
         }
       } || {
         $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (32 bit) because it is not present"
@@ -194,11 +191,8 @@ test -e ../afl-qemu-trace && {
           }
           unset LD_PRELOAD
         } || {
-          echo CUT------------------------------------------------------------------CUT
-          cat errors
-          echo CUT------------------------------------------------------------------CUT
-	  $ECHO "$RED[!] cannot compile test program (64 bit) for unsigaction library"
-          CODE=1
+	  $ECHO "$YELLOW[-] cannot compile test program (64 bit) for unsigaction library"
+          INCOMPLETE=1
         }
       } || {
         $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (64 bit) because it is not present"
diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh
index 182958d6..f8ff4190 100755
--- a/test/test-unicorn-mode.sh
+++ b/test/test-unicorn-mode.sh
@@ -3,7 +3,7 @@
 . ./test-pre.sh
 
 $ECHO "$BLUE[*] Testing: unicorn_mode"
-test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shellcode && {
+test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && {
   test -e ../unicorn_mode/samples/python_simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
     {
       # We want to see python errors etc. in logs, in case something doesn't work
diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION
index 4697a492..fe7be8e1 100644
--- a/unicorn_mode/UNICORNAFL_VERSION
+++ b/unicorn_mode/UNICORNAFL_VERSION
@@ -1 +1 @@
-46879845
+a44fa94488d01aba60401ccf81f8bebcce685bf2
diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh
index a846fd1c..f24c8ce3 100755
--- a/unicorn_mode/build_unicorn_support.sh
+++ b/unicorn_mode/build_unicorn_support.sh
@@ -217,7 +217,8 @@ cd ../samples/python_simple || echo "Cannot cd"
 
 # Run afl-showmap on the sample application. If anything comes out then it must have worked!
 unset AFL_INST_RATIO
-echo 0 | ../../../afl-showmap -U -m none -t 2000 -q -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin || echo "Showmap"
+# pwd; echo "echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin"
+echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin >/dev/null 2>&1 || echo "Showmap"
 
 if [ -s ./.test-instr0 ]
 then
diff --git a/unicorn_mode/samples/compcov_x64/compcov_test_harness.py b/unicorn_mode/samples/compcov_x64/compcov_test_harness.py
index 52f0a286..ce96b882 100644
--- a/unicorn_mode/samples/compcov_x64/compcov_test_harness.py
+++ b/unicorn_mode/samples/compcov_x64/compcov_test_harness.py
@@ -19,7 +19,7 @@ import os
 import signal
 
 from unicornafl import *
-from unicornafl.x86_const import *
+from unicorn.x86_const import *
 
 # Path to the file containing the binary to emulate
 BINARY_FILE = os.path.join(
@@ -160,7 +160,7 @@ def main():
     # Emulate the code, allowing it to process the mutated input
 
     print("Starting the AFL fuzz")
-    uc.afl_fuzz(
+    uc_afl_fuzz(uc,
         input_file=args.input_file,
         place_input_callback=place_input_callback,
         exits=[end_address],
diff --git a/unicorn_mode/samples/speedtest/python/harness.py b/unicorn_mode/samples/speedtest/python/harness.py
index 801ef4d1..604adf39 100644
--- a/unicorn_mode/samples/speedtest/python/harness.py
+++ b/unicorn_mode/samples/speedtest/python/harness.py
@@ -20,8 +20,8 @@ import os
 import struct
 
 from unicornafl import *
-from unicornafl.unicorn_const import UC_ARCH_X86, UC_HOOK_CODE, UC_MODE_64
-from unicornafl.x86_const import (
+from unicorn.unicorn_const import UC_ARCH_X86, UC_HOOK_CODE, UC_MODE_64
+from unicorn.x86_const import (
     UC_X86_REG_RAX,
     UC_X86_REG_RDI,
     UC_X86_REG_RIP,
diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl
-Subproject 468798455a9f9790d2da369a18ed49fda3a64e8
+Subproject a44fa94488d01aba60401ccf81f8bebcce685bf