about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile2
-rw-r--r--README.md26
-rwxr-xr-xafl-system-config2
-rw-r--r--custom_mutators/libfuzzer/FuzzerLoop.cpp1
-rw-r--r--custom_mutators/libfuzzer/libfuzzer.inc4
-rw-r--r--docs/Changelog.md1
-rw-r--r--docs/best_practices.md6
-rw-r--r--docs/branches.md2
-rw-r--r--docs/ci_fuzzing.md2
-rw-r--r--docs/env_variables.md4
-rw-r--r--docs/fuzzing_binary-only_targets.md5
-rw-r--r--docs/fuzzing_expert.md11
-rw-r--r--docs/interpreting_output.md4
-rw-r--r--docs/known_limitations.md4
-rw-r--r--docs/parallel_fuzzing.md2
-rw-r--r--docs/rpc_statsd.md230
-rw-r--r--docs/triaging_crashes.md2
-rw-r--r--frida_mode/src/instrument/instrument.c8
-rw-r--r--frida_mode/src/instrument/instrument_x64.c205
-rw-r--r--frida_mode/src/prefetch.c8
-rw-r--r--frida_mode/src/seccomp/seccomp_callback.c6
-rw-r--r--frida_mode/test/freetype2/GNUmakefile192
-rw-r--r--frida_mode/test/freetype2/Makefile13
-rwxr-xr-xfrida_mode/test/freetype2/get_symbol_addr.py36
-rw-r--r--frida_mode/test/libpcap/GNUmakefile2
-rw-r--r--include/config.h4
-rw-r--r--instrumentation/README.laf-intel.md5
-rw-r--r--instrumentation/README.llvm.md2
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc34
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc23
-rw-r--r--instrumentation/afl-llvm-lto-instrumentation.so.cc30
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
-rw-r--r--qemu_mode/libcompcov/libcompcov.so.c12
m---------qemu_mode/qemuafl0
-rw-r--r--src/afl-analyze.c2
-rw-r--r--src/afl-fuzz-stats.c5
-rw-r--r--src/afl-fuzz.c4
-rw-r--r--src/afl-showmap.c2
-rw-r--r--src/afl-tmin.c2
-rw-r--r--unicorn_mode/UNICORNAFL_VERSION2
-rw-r--r--unicorn_mode/samples/speedtest/rust/src/main.rs20
m---------unicorn_mode/unicornafl0
42 files changed, 676 insertions, 251 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 376f6e9a..0a6f3950 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -541,7 +541,7 @@ test_build: afl-cc afl-gcc afl-as afl-showmap
 #	echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
 #	@rm -f test-instr
 #	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
-#		gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option."; echo "See docs/INSTALL.md section 5 how to build a -B enabled gcc." ) || \
+#		gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option." ) || \
 #		( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
 #	@echo
 #	@echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
diff --git a/README.md b/README.md
index db6a70b5..1a22dd12 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ You are free to copy, modify, and distribute AFL++ with attribution under the te
 
 Here is some information to get you started:
 
-* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [major behaviour changes in AFL++](docs/behaviour_changes.md).
+* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [major changes in AFL++](docs/important_changes.md).
 * If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website.
 * To cite our work, look at the [Cite](#cite) section.
 * For comparisons, use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
@@ -66,23 +66,35 @@ A common way to do this would be:
         make clean all
 
 2. Get a small but valid input file that makes sense to the program.
-When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in [dictionaries/README.md](../dictionaries/README.md), too.
+When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described
+in [dictionaries/README.md](dictionaries/README.md), too.
 
 3. If the program reads from stdin, run `afl-fuzz` like so:
 
-        ./afl-fuzz -i testcase_dir -o findings_dir -- \
-          /path/to/tested/program [...program's cmdline...]
+```
+   ./afl-fuzz -i seeds_dir -o output_dir -- \
+     /path/to/tested/program [...program's cmdline...]
+```
+
+   To add a dictionary, add `-x /path/to/dictionary.txt` to afl-fuzz.
 
-   If the program takes input from a file, you can put `@@` in the program's command line; AFL will put an auto-generated file name in there for you.
+   If the program takes input from a file, you can put `@@` in the program's
+   command line; AFL will put an auto-generated file name in there for you.
 
 4. Investigate anything shown in red in the fuzzer UI by promptly consulting [docs/status_screen.md](docs/status_screen.md).
 
+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.:
+   `cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]`
+   You can generate cores or use gdb directly to follow up the crashes.
+
 ## Contact
 
 Questions? Concerns? Bug reports?
 
 * The contributors can be reached via [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
-* Take a look at our [FAQ](docs/faq.md). If you find an interesting or important question missing, submit it via
+* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important question missing, submit it via
 [https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
 * There is a mailing list for the AFL/AFL++ project ([browse archive](https://groups.google.com/group/afl-users)). To compare notes with other users or to get notified about major new features, send an email to <afl-users+subscribe@googlegroups.com>.
 * Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
@@ -179,4 +191,4 @@ If you use AFL++ in scientific work, consider citing [our paper](https://www.use
   }
   ```
 
-</details>
\ No newline at end of file
+</details>
diff --git a/afl-system-config b/afl-system-config
index dbdbbf1f..3c14ba55 100755
--- a/afl-system-config
+++ b/afl-system-config
@@ -52,7 +52,7 @@ if [ "$PLATFORM" = "Linux" ] ; then
     echo '  /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
     echo
   }
-  echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed
+  echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed.
   echo
   DONE=1
 fi
diff --git a/custom_mutators/libfuzzer/FuzzerLoop.cpp b/custom_mutators/libfuzzer/FuzzerLoop.cpp
index 08fda520..6716dbf5 100644
--- a/custom_mutators/libfuzzer/FuzzerLoop.cpp
+++ b/custom_mutators/libfuzzer/FuzzerLoop.cpp
@@ -1086,6 +1086,7 @@ ATTRIBUTE_INTERFACE size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size,
                                             size_t MaxSize) {
 
   assert(fuzzer::F);
+  fuzzer::F->GetMD().StartMutationSequence();
   size_t r = fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
 #ifdef  INTROSPECTION
   introspection_ptr = fuzzer::F->GetMD().WriteMutationSequence();
diff --git a/custom_mutators/libfuzzer/libfuzzer.inc b/custom_mutators/libfuzzer/libfuzzer.inc
index 01f21dbe..8c4bdbf6 100644
--- a/custom_mutators/libfuzzer/libfuzzer.inc
+++ b/custom_mutators/libfuzzer/libfuzzer.inc
@@ -2,7 +2,7 @@
 
 extern "C" ATTRIBUTE_INTERFACE void
 LLVMFuzzerMyInit(int (*Callback)(const uint8_t *Data, size_t Size), unsigned int Seed) {
-  Random Rand(Seed);
+  auto *Rand = new Random(Seed);
   FuzzingOptions Options;
   Options.Verbosity = 3;
   Options.MaxLen = 1024000;
@@ -30,7 +30,7 @@ LLVMFuzzerMyInit(int (*Callback)(const uint8_t *Data, size_t Size), unsigned int
   struct EntropicOptions Entropic;
   Entropic.Enabled = Options.Entropic;
   EF = new ExternalFunctions();
-  auto *MD = new MutationDispatcher(Rand, Options);
+  auto *MD = new MutationDispatcher(*Rand, Options);
   auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic);
   auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
 }
diff --git a/docs/Changelog.md b/docs/Changelog.md
index de217c2e..dad5fee2 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -15,6 +15,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
       information on how to deal with instrumenting libraries
     - fix a regression introduced in 3.10 that resulted in less
       coverage being detected. thanks to Collin May for reporting!
+    - fix -n dumb mode (nobody should use this)
   - afl-showmap, afl-tmin and afl-analyze now honor persistent mode
     for more speed. thanks to dloffre-snl for reporting!
   - afl-cc:
diff --git a/docs/best_practices.md b/docs/best_practices.md
index 23fa237d..0708d49d 100644
--- a/docs/best_practices.md
+++ b/docs/best_practices.md
@@ -59,10 +59,10 @@ which allows you to define network state with different type of data packets.
 1. Use [llvm_mode](../instrumentation/README.llvm.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended).
 2. Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20 speed increase).
 3. Use the [AFL++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase).
-4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input file directory on a tempfs location, see [docs/env_variables.md](docs/env_variables.md).
+4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input file directory on a tempfs location, see [env_variables.md](env_variables.md).
 5. Improve Linux kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system less secure).
 6. Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem.
-7. Use your cores! [README.md:3.b) Using multiple cores/threads](../README.md#b-using-multiple-coresthreads).
+7. Use your cores! [fuzzing_expert.md:b) Using multiple cores](fuzzing_expert.md#b-using-multiple-cores).
 
 ### Improving stability
 
@@ -117,4 +117,4 @@ Four steps are required to do this and it also requires quite some knowledge of
 
      Recompile, fuzz it, be happy :)
 
-     This link explains this process for [Fuzzbench](https://github.com/google/fuzzbench/issues/677).
\ No newline at end of file
+     This link explains this process for [Fuzzbench](https://github.com/google/fuzzbench/issues/677).
diff --git a/docs/branches.md b/docs/branches.md
index 1e4ebbb2..98fd6827 100644
--- a/docs/branches.md
+++ b/docs/branches.md
@@ -7,4 +7,4 @@ The following branches exist:
 * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state of AFL++ - bleeding edge and you might catch a checkout which does not compile or has a bug. *We only accept PRs in dev!!*
 * (any other): experimental branches to work on specific features or testing new functionality or changes.
 
-For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab. Also take a look at the list of [major behaviour changes in AFL++](behaviour_changes.md).
\ No newline at end of file
+For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab. Also take a look at the list of [major changes in AFL++](important_changes.md).
diff --git a/docs/ci_fuzzing.md b/docs/ci_fuzzing.md
index 316059f8..8d1a2f99 100644
--- a/docs/ci_fuzzing.md
+++ b/docs/ci_fuzzing.md
@@ -26,4 +26,4 @@ Some notes on CI Fuzzing - this fuzzing is different to normal fuzzing campaigns
 `-M` enables old queue handling etc. which is good for a fuzzing campaign but not good for short CI runs.
 
 How this can look like can e.g. be seen at AFL++'s setup in Google's [oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
-and [clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/python/bot/fuzzers/afl/launcher.py).
\ No newline at end of file
+and [clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 0686f1a8..5f5c2510 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -2,7 +2,7 @@
 
   This document discusses the environment variables used by American Fuzzy Lop++
   to expose various exotic functions that may be (rarely) useful for power
-  users or for some types of custom fuzzing setups. See [README.md](README.md) for the general
+  users or for some types of custom fuzzing setups. See [../README.md](../README.md) for the general
   instruction manual.
 
   Note that most tools will warn on any unknown AFL environment variables.
@@ -422,7 +422,7 @@ checks or alter some of the more exotic semantics of the tool:
   - Setting `AFL_FORCE_UI` will force painting the UI on the screen even if
     no valid terminal was detected (for virtual consoles)
 
-  - If you are using persistent mode (you should, see [instrumentation/README.persistent_mode.md](instrumentation/README.persistent_mode.md))
+  - If you are using persistent mode (you should, see [instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md))
     some targets keep inherent state due which a detected crash testcase does
     not crash the target again when the testcase is given. To be able to still
     re-trigger these crashes you can use the `AFL_PERSISTENT_RECORD` variable
diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md
index a39e40a0..8b3bbeff 100644
--- a/docs/fuzzing_binary-only_targets.md
+++ b/docs/fuzzing_binary-only_targets.md
@@ -51,7 +51,7 @@ make
 ```
 
 For additional instructions and caveats, see [frida_mode/README.md](../frida_mode/README.md).
-If possible you should use the persistent mode, see [qemu_frida/README.persistent.md](../qemu_frida/README.persistent.md).
+If possible you should use the persistent mode, see [qemu_frida/README.md](../qemu_frida/README.md).
 The mode is approximately 2-5x slower than compile-time instrumentation, and is
 less conducive to parallelization.
 
@@ -71,7 +71,8 @@ cd unicorn_mode
 
 If the goal is to fuzz a dynamic library then there are two options available.
 For both you need to write a small harness that loads and calls the library.
-Faster is the frida solution: [utils/afl_frida/README.md](../utils/afl_frida/README.md)
+Then you fuzz this with either frida_mode or qemu_mode, and either use
+`AFL_INST_LIBS=1` or `AFL_QEMU/FRIDA_INST_RANGES`
 
 Another, less precise and slower option is using ptrace with debugger interrupt
 instrumentation: [utils/afl_untracer/README.md](../utils/afl_untracer/README.md).
diff --git a/docs/fuzzing_expert.md b/docs/fuzzing_expert.md
index 23b24ad0..ef3f8a4e 100644
--- a/docs/fuzzing_expert.md
+++ b/docs/fuzzing_expert.md
@@ -472,7 +472,7 @@ If you are using AFL spinoffs or AFL conforming fuzzers, then just use the
 same -o directory and give it a unique `-S` name.
 Examples are:
  * [Fuzzolic](https://github.com/season-lab/fuzzolic)
- * [symcc](https://github.com/eurecom-s/symcc/)
+ * [symcc](https://github.com/eurecom-s3/symcc/)
  * [Eclipser](https://github.com/SoftSec-KAIST/Eclipser/)
  * [AFLsmart](https://github.com/aflsmart/aflsmart)
  * [FairFuzz](https://github.com/carolemieux/afl-rb)
@@ -540,6 +540,11 @@ To have only the summary use the `-s` switch e.g.: `afl-whatsup -s out/`
 If you have multiple servers then use the command after a sync, or you have
 to execute this script per server.
 
+Another tool to inspect the current state and history of a specific instance
+is afl-plot, which generates an index.html file and a graphs that show how
+the fuzzing instance is performing.
+The syntax is `afl-plot instance_dir web_dir`, e.g. `afl-plot out/default /srv/www/htdocs/plot`
+
 #### e) Stopping fuzzing, restarting fuzzing, adding new seeds
 
 To stop an afl-fuzz run, simply press Control-C.
@@ -608,7 +613,7 @@ switch or honggfuzz.
  * If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [env_variables.md](env_variables.md)
  * Linux: Improve kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system more insecure) - you can also just run `sudo afl-persistent-config`
  * Linux: Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem
- * Use your cores! [3.b) Using multiple cores/threads](#b-using-multiple-coresthreads)
+ * Use your cores! [b) Using multiple cores](#b-using-multiple-cores)
  * Run `sudo afl-system-config` before starting the first afl-fuzz instance after a reboot
 
 ### The End
@@ -620,4 +625,4 @@ This is basically all you need to know to professionally run fuzzing campaigns.
 If you want to know more, the tons of texts in [docs/](./) will have you covered.
 
 Note that there are also a lot of tools out there that help fuzzing with AFL++
-(some might be deprecated or unsupported), see [links_tools.md](links_tools.md).
\ No newline at end of file
+(some might be deprecated or unsupported), see [tools.md](tools.md).
diff --git a/docs/interpreting_output.md b/docs/interpreting_output.md
index 54ad76df..327a0ac0 100644
--- a/docs/interpreting_output.md
+++ b/docs/interpreting_output.md
@@ -1,6 +1,6 @@
 # Interpreting output
 
-See the [docs/status_screen.md](docs/status_screen.md) file for information on
+See the [status_screen.md](status_screen.md) file for information on
 how to interpret the displayed stats and monitor the health of the process. Be
 sure to consult this file especially if any UI elements are highlighted in red.
 
@@ -68,4 +68,4 @@ cd utils/plot_ui
 make
 cd ../../
 sudo make install
-```
\ No newline at end of file
+```
diff --git a/docs/known_limitations.md b/docs/known_limitations.md
index deb539e2..2d8f84a5 100644
--- a/docs/known_limitations.md
+++ b/docs/known_limitations.md
@@ -15,7 +15,7 @@ Here are some of the most important caveats for AFL:
     To work around this, you can comment out the relevant checks (see
     utils/libpng_no_checksum/ for inspiration); if this is not possible,
     you can also write a postprocessor, one of the hooks of custom mutators.
-    See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use
+    See [custom_mutators.md](custom_mutators.md) on how to use
     `AFL_CUSTOM_MUTATOR_LIBRARY`
 
   - There are some unfortunate trade-offs with ASAN and 64-bit binaries. This
@@ -33,4 +33,4 @@ Here are some of the most important caveats for AFL:
   - Occasionally, sentient machines rise against their creators. If this
     happens to you, please consult [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/).
 
-Beyond this, see [INSTALL.md](INSTALL.md) for platform-specific tips.
\ No newline at end of file
+Beyond this, see [INSTALL.md](INSTALL.md) for platform-specific tips.
diff --git a/docs/parallel_fuzzing.md b/docs/parallel_fuzzing.md
index 90e12e89..e37276a5 100644
--- a/docs/parallel_fuzzing.md
+++ b/docs/parallel_fuzzing.md
@@ -4,7 +4,7 @@ This document talks about synchronizing afl-fuzz jobs on a single machine
 or across a fleet of systems. See README.md for the general instruction manual.
 
 Note that this document is rather outdated. please refer to the main document
-section on multiple core usage [../README.md#Using multiple cores](../README.md#b-using-multiple-coresthreads)
+section on multiple core usage [fuzzing_expert.md#Using multiple cores](fuzzing_expert.md#b-using-multiple-cores)
 for up to date strategies!
 
 ## 1) Introduction
diff --git a/docs/rpc_statsd.md b/docs/rpc_statsd.md
index 898ad099..9b3d8d40 100644
--- a/docs/rpc_statsd.md
+++ b/docs/rpc_statsd.md
@@ -1,143 +1,155 @@
-# Remote monitoring with StatsD
+# Remote monitoring and metrics visualization
 
-StatsD allows you to receive and aggregate metrics from a wide range of applications and retransmit them to the backend of your choice.
-This enables you to create nice and readable dashboards containing all the information you need on your fuzzer instances.
-No need to write your own statistics parsing system, deploy and maintain it to all your instances, sync with your graph rendering system...
+AFL++ can send out metrics as StatsD messages. For remote monitoring and visualization of the metrics, you can set up a tool chain. For example, with Prometheus and Grafana. All tools are free and open source.
 
-The available metrics are :
+This enables you to create nice and readable dashboards containing all the information you need on your fuzzer instances. There is no need to write your own statistics parsing system, deploy and maintain it to all your instances, and sync with your graph rendering system.
+
+Compared to the default integrated UI of AFL++, this can help you to visualize trends and the fuzzing state over time. You might be able to see when the fuzzing process has reached a state of no progress and visualize what are the "best strategies" for your targets (according to your own criteria). You can do so without logging into each instance individually.
+
+![example visualization with Grafana](resources/statsd-grafana.png)
+
+This is an example visualization with Grafana. The dashboard can be imported with [this JSON template](resources/grafana-afl++.json).
+
+## AFL++ metrics and StatsD
+
+StatsD allows you to receive and aggregate metrics from a wide range of applications and retransmit them to a backend of your choice.
+
+From AFL++, StatsD can receive the following metrics:
+- cur_path
 - cycle_done
 - cycles_wo_finds
+- edges_found
 - execs_done
 - execs_per_sec
-- paths_total
+- havoc_expansion
+- max_depth
 - paths_favored
 - paths_found
 - paths_imported
-- max_depth
-- cur_path
+- paths_total
 - pending_favs
 - pending_total
-- variable_paths
+- slowest_exec_ms
+- total_crashes
 - unique_crashes
 - unique_hangs
-- total_crashes
-- slowest_exec_ms
-- edges_found
 - var_byte_count
-- havoc_expansion
+- variable_paths
 
-Compared to the default integrated UI, these metrics give you the opportunity to visualize trends and fuzzing state over time.
-By doing so, you might be able to see when the fuzzing process has reached a state of no progress, visualize what are the "best strategies"
-(according to your own criteria) for your targets, etc. And doing so without requiring to log into each instance manually.
+Depending on your StatsD server, you will be able to monitor, trigger alerts, or perform actions based on these metrics (for example: alert on slow exec/s for a new build, threshold of crashes, time since last crash > X, and so on).
 
-An example visualisation may look like the following:
-![StatsD Grafana](resources/statsd-grafana.png)
+## Setting environment variables in AFL++
 
-*Notes: The exact same dashboard can be imported with [this JSON template](resources/grafana-afl++.json).*
+1. To enable the StatsD metrics collection on your fuzzer instances, set the environment variable `AFL_STATSD=1`. By default, AFL++ will send the metrics over UDP to 127.0.0.1:8125.
 
-## How to use
+2. To enable tags for each metric based on their format (banner and afl_version), set the environment variable `AFL_STATSD_TAGS_FLAVOR`. By default, no tags will be added to the metrics.
 
-To enable the StatsD reporting on your fuzzer instances, you need to set the environment variable `AFL_STATSD=1`.
+    The available values are the following:
+    -  `dogstatsd`
+    -  `influxdb`
+    -  `librato`
+    -  `signalfx`
+    
+    For more information on environment variables, see [env_variables.md](env_variables.md).
 
-Setting `AFL_STATSD_TAGS_FLAVOR` to the provider of your choice will assign tags / labels to each metric based on their format.
-The possible values are  `dogstatsd`, `librato`, `signalfx` or `influxdb`.
-For more information on these env vars, check out `docs/env_variables.md`.
+    Note: When using multiple fuzzer instances with StatsD it is *strongly* recommended to set up `AFL_STATSD_TAGS_FLAVOR` to match your StatsD server. This will allow you to see individual fuzzer performance, detect bad ones, and see the progress of each strategy.
 
-The simplest way of using this feature is to use any metric provider and change the host/port of your StatsD daemon,
-with `AFL_STATSD_HOST` and `AFL_STATSD_PORT`, if required (defaults are `localhost` and port `8125`).
-To get started, here are some instructions with free and open source tools.
-The following setup is based on Prometheus, statsd_exporter and Grafana.
-Grafana here is not mandatory, but gives you some nice graphs and features.
+3. Optional: To set the host and port of your StatsD daemon, set `AFL_STATSD_HOST` and `AFL_STATSD_PORT`. The default values are `localhost` and `8125`.
 
-Depending on your setup and infrastructure, you may want to run these applications not on your fuzzer instances.
-Only one instance of these 3 application is required for all your fuzzers.
+## Installing and setting up StatsD, Prometheus, and Grafana
 
-To simplify everything, we will use Docker and docker-compose.
-Make sure you have them both installed. On most common Linux distributions, it's as simple as:
+The easiest way to install and set up the infrastructure is with Docker and Docker Compose.
 
-```sh
-curl -fsSL https://get.docker.com -o get-docker.sh
-sh get-docker.sh
-```
+Depending on your fuzzing setup and infrastructure, you may not want to run these applications on your fuzzer instances. This setup may be modified before use in a production environment; for example, adding passwords, creating volumes for storage, tweaking the metrics gathering to get host metrics (CPU, RAM, and so on).
 
-Once that's done, we can create the infrastructure.
-Create and move into the directory of your choice. This will store all the configurations files required.
-
-First, create a `docker-compose.yml` containing the following:
-```yml
-version: '3'
-
-networks:
-  statsd-net:
-    driver: bridge
-
-services:
-  prometheus:
-    image: prom/prometheus
-    container_name: prometheus
-    volumes:
-      - ./prometheus.yml:/prometheus.yml
-    command:
-      - '--config.file=/prometheus.yml'
-    restart: unless-stopped
-    ports:
-      - "9090:9090"
-    networks:
-      - statsd-net
-
-  statsd_exporter:
-    image: prom/statsd-exporter
-    container_name: statsd_exporter
-    volumes:
-      - ./statsd_mapping.yml:/statsd_mapping.yml
-    command:
-      - "--statsd.mapping-config=/statsd_mapping.yml"
-    ports:
-      - "9102:9102/tcp"
-      - "8125:9125/udp"
-    networks:
-      - statsd-net
-  
-  grafana:
-    image: grafana/grafana
-    container_name: grafana
-    restart: unless-stopped
-    ports:
-        - "3000:3000"
-    networks:
-      - statsd-net
-```
+For all your fuzzing instances, only one instance of Prometheus and Grafana is required. The [statsd exporter](https://registry.hub.docker.com/r/prom/statsd-exporter) converts the StatsD metrics to Prometheus. If you are using a provider that supports StatsD directly, you can skip this part of the setup."
 
-Then `prometheus.yml`
-```yml
-global:
-  scrape_interval:      15s
-  evaluation_interval:  15s
+You can create and move the infrastructure files into a directory of your choice. The directory will store all the required configuration files.
 
-scrape_configs:
-  - job_name: 'fuzzing_metrics'
-    static_configs:
-      - targets: ['statsd_exporter:9102']
-```
+To install and set up Prometheus and Grafana:
 
-And finally `statsd_mapping.yml`
-```yml 
-mappings:
-- match: "fuzzing.*"
-  name: "fuzzing"
-  labels:
-      type: "$1"
-```
+1. Install Docker and Docker Compose:
+
+    ```sh
+    curl -fsSL https://get.docker.com -o get-docker.sh
+    sh get-docker.sh
+    ```
 
-Run `docker-compose up -d`.
+2. Create a `docker-compose.yml` containing the following:
+    ```yml
+    version: '3'
 
-Everything should now be setup, you are now able to run your fuzzers with
+    networks:
+      statsd-net:
+        driver: bridge
+
+    services:
+      prometheus:
+        image: prom/prometheus
+        container_name: prometheus
+        volumes:
+          - ./prometheus.yml:/prometheus.yml
+        command:
+          - '--config.file=/prometheus.yml'
+        restart: unless-stopped
+        ports:
+          - "9090:9090"
+        networks:
+          - statsd-net
+
+      statsd_exporter:
+        image: prom/statsd-exporter
+        container_name: statsd_exporter
+        volumes:
+          - ./statsd_mapping.yml:/statsd_mapping.yml
+        command:
+          - "--statsd.mapping-config=/statsd_mapping.yml"
+        ports:
+          - "9102:9102/tcp"
+          - "8125:9125/udp"
+        networks:
+          - statsd-net
+      
+      grafana:
+        image: grafana/grafana
+        container_name: grafana
+        restart: unless-stopped
+        ports:
+            - "3000:3000"
+        networks:
+          - statsd-net
+    ```
+
+3. Create a `prometheus.yml` containing the following:
+
+    ```yml
+    global:
+      scrape_interval:      15s
+      evaluation_interval:  15s
+
+    scrape_configs:
+      - job_name: 'fuzzing_metrics'
+        static_configs:
+          - targets: ['statsd_exporter:9102']
+    ```
+
+4. Create a `statsd_mapping.yml` containing the following:
+    ```yml 
+    mappings:
+    - match: "fuzzing.*"
+      name: "fuzzing"
+      labels:
+          type: "$1"
+    ```
+
+5. Run `docker-compose up -d`.
+
+## Running AFL++ with StatsD
+
+To run your fuzzing instances:
 
 ```
-AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -M test-fuzzer-1 -i i -o o ./bin/my-application @@
-AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o o ./bin/my-application @@
+AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -M test-fuzzer-1 -i i -o o [./bin/my-application] @@
+AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o o [./bin/my-application] @@
 ...
 ```
-
-This setup may be modified before use in a production environment. Depending on your needs: adding passwords, creating volumes for storage,
-tweaking the metrics gathering to get host metrics (CPU, RAM ...).
diff --git a/docs/triaging_crashes.md b/docs/triaging_crashes.md
index 1857c4b1..b0015c90 100644
--- a/docs/triaging_crashes.md
+++ b/docs/triaging_crashes.md
@@ -43,4 +43,4 @@ file, attempts to sequentially flip bytes, and observes the behavior of the
 tested program. It then color-codes the input based on which sections appear to
 be critical, and which are not; while not bulletproof, it can often offer quick
 insights into complex file formats. More info about its operation can be found
-near the end of [docs/technical_details.md](docs/technical_details.md).
\ No newline at end of file
+near the end of [technical_details.md](technical_details.md).
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index fd0982f8..71d9bdf6 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -341,8 +341,14 @@ void instrument_init(void) {
      * parallel fuzzing. The seed itself, doesn't have to be random, it
      * just needs to be different for each instance.
      */
+    guint64 tid;
+#if defined(__APPLE__)
+    pthread_threadid_np(NULL, &tid);
+#else
+    tid = syscall(SYS_gettid);
+#endif
     instrument_hash_seed = g_get_monotonic_time() ^
-                           (((guint64)getpid()) << 32) ^ syscall(SYS_gettid);
+                           (((guint64)getpid()) << 32) ^ tid;
 
   }
 
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index fec8afbb..1c2cf113 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -1,6 +1,9 @@
+#include <stddef.h>
+
 #include "frida-gumjs.h"
 
 #include "config.h"
+#include "debug.h"
 
 #include "instrument.h"
 
@@ -8,38 +11,120 @@
 
 static GumAddress current_log_impl = GUM_ADDRESS(0);
 
-static const guint8 afl_log_code[] = {
+  #pragma pack(push, 1)
+
+typedef struct {
+
+  /*
+   * pushfq
+   * push rdx
+   * mov rdx, [&previouspc] (rip relative addr)
+   * xor rdx, rdi (current_pc)
+   * shr rdi. 1
+   * mov [&previouspc], rdi
+   * lea rsi, [&_afl_area_ptr] (rip relative)
+   * add rdx, rsi
+   * add byte ptr [rdx], 1
+   * adc byte ptr [rdx], 0
+
+   * pop rdx
+   * popfq
+   */
+  uint8_t push_fq;
+  uint8_t push_rdx;
+  uint8_t mov_rdx_rip_off[7];
+  uint8_t xor_rdx_rdi[3];
+  uint8_t shr_rdi[3];
+  uint8_t mov_rip_off_rdi[7];
+
+  uint8_t lea_rdi_rip_off[7];
+  uint8_t add_rdx_rdi[3];
+  uint8_t add_byte_ptr_rdx[3];
+  uint8_t adc_byte_ptr_rdx[3];
+
+  uint8_t pop_rdx;
+  uint8_t pop_fq;
+  uint8_t ret;
+
+} afl_log_code_asm_t;
+
+  #pragma pack(pop)
+
+  #pragma pack(push, 8)
+typedef struct {
+
+  afl_log_code_asm_t assembly;
+  uint64_t           current_pc;
+
+} afl_log_code_t;
+
+  #pragma pack(pop)
+
+typedef union {
+
+  afl_log_code_t data;
+  uint8_t        bytes[0];
+
+} afl_log_code;
+
+static const afl_log_code_asm_t template = {
+
+    .push_fq = 0x9c,
+    .push_rdx = 0x52,
+    .mov_rdx_rip_off =
+        {
+
+            0x48, 0x8b, 0x15,
+            /* TBC */
+
+        },
+
+    .xor_rdx_rdi =
+        {
+
+            0x48,
+            0x31,
+            0xfa,
+
+        },
+
+    .shr_rdi = {0x48, 0xd1, 0xef},
+    .mov_rip_off_rdi = {0x48, 0x89, 0x3d},
+
+    .lea_rdi_rip_off =
+        {
+
+            0x48,
+            0x8d,
+            0x3d,
 
-    0x9c,                                                         /* pushfq */
-    0x51,                                                       /* push rcx */
-    0x52,                                                       /* push rdx */
+        },
 
-    0x48, 0x8b, 0x0d, 0x26,
-    0x00, 0x00, 0x00,                          /* mov rcx, sym.&previous_pc */
-    0x48, 0x8b, 0x11,                               /* mov rdx, qword [rcx] */
-    0x48, 0x31, 0xfa,                                       /* xor rdx, rdi */
+    .add_rdx_rdi = {0x48, 0x01, 0xfA},
 
-    0x48, 0x03, 0x15, 0x11,
-    0x00, 0x00, 0x00,                     /* add rdx, sym._afl_area_ptr_ptr */
+    .add_byte_ptr_rdx =
+        {
 
-    0x80, 0x02, 0x01,                              /* add byte ptr [rdx], 1 */
-    0x80, 0x12, 0x00,                              /* adc byte ptr [rdx], 0 */
-    0x66, 0xd1, 0xcf,                                          /* ror di, 1 */
-    0x48, 0x89, 0x39,                               /* mov qword [rcx], rdi */
+            0x80,
+            0x02,
+            0x01,
 
-    0x5a,                                                        /* pop rdx */
-    0x59,                                                        /* pop rcx */
-    0x9d,                                                          /* popfq */
+        },
 
-    0xc3,                                                            /* ret */
+    .adc_byte_ptr_rdx =
+        {
 
-    0x90
+            0x80,
+            0x12,
+            0x00,
 
-    /* Read-only data goes here: */
-    /* uint8_t* __afl_area_ptr */
-    /* uint64_t* &previous_pc */
+        },
 
-};
+    .pop_rdx = 0x5a,
+    .pop_fq = 0x9d,
+    .ret = 0xc3};
+
+static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
 
 gboolean instrument_is_coverage_optimize_supported(void) {
 
@@ -47,12 +132,19 @@ gboolean instrument_is_coverage_optimize_supported(void) {
 
 }
 
-static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+static gboolean instrument_coverage_in_range(gssize offset) {
+
+  return (offset >= G_MININT32 && offset <= G_MAXINT32);
+
+}
 
 static void instrument_coverate_write_function(GumStalkerOutput *output) {
 
   guint64       misalign = 0;
   GumX86Writer *cw = output->writer.x86;
+  GumAddress    code_addr = 0;
+  afl_log_code  code = {0};
+  /*guint64       instrument_hash_zero = 0;*/
 
   if (current_log_impl == 0 ||
       !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
@@ -71,13 +163,66 @@ static void instrument_coverate_write_function(GumStalkerOutput *output) {
     }
 
     current_log_impl = cw->pc;
-    gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+    // gum_x86_writer_put_breakpoint(cw);
+    code_addr = cw->pc;
+
+    code.data.assembly = template;
+    code.data.current_pc = instrument_get_offset_hash(0);
+
+    gssize current_pc_value1 =
+        GPOINTER_TO_SIZE(&instrument_previous_pc) -
+        (code_addr + offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
+         sizeof(code.data.assembly.mov_rdx_rip_off));
+    gssize patch_offset1 =
+        offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
+        sizeof(code.data.assembly.mov_rdx_rip_off) - sizeof(gint);
+    if (!instrument_coverage_in_range(current_pc_value1)) {
+
+      FATAL("Patch out of range (current_pc_value1): 0x%016lX",
+            current_pc_value1);
+
+    }
+
+    gint *dst_pc_value = (gint *)&code.bytes[patch_offset1];
+    *dst_pc_value = (gint)current_pc_value1;
+
+    gssize current_pc_value2 =
+        GPOINTER_TO_SIZE(&instrument_previous_pc) -
+        (code_addr + offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
+         sizeof(code.data.assembly.mov_rip_off_rdi));
+    gssize patch_offset2 =
+        offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
+        sizeof(code.data.assembly.mov_rip_off_rdi) - sizeof(gint);
+
+    if (!instrument_coverage_in_range(current_pc_value2)) {
+
+      FATAL("Patch out of range (current_pc_value2): 0x%016lX",
+            current_pc_value2);
+
+    }
+
+    dst_pc_value = (gint *)&code.bytes[patch_offset2];
+    *dst_pc_value = (gint)current_pc_value2;
+
+    gsize afl_area_ptr_value =
+        GPOINTER_TO_SIZE(__afl_area_ptr) -
+        (code_addr + offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
+         sizeof(code.data.assembly.lea_rdi_rip_off));
+    gssize afl_area_ptr_offset =
+        offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
+        sizeof(code.data.assembly.lea_rdi_rip_off) - sizeof(gint);
+
+    if (!instrument_coverage_in_range(afl_area_ptr_value)) {
+
+      FATAL("Patch out of range (afl_area_ptr_value): 0x%016lX",
+            afl_area_ptr_value);
+
+    }
+
+    gint *dst_afl_area_ptr_value = (gint *)&code.bytes[afl_area_ptr_offset];
+    *dst_afl_area_ptr_value = (gint)afl_area_ptr_value;
 
-    uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
-    gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr,
-                             sizeof(__afl_area_ptr));
-    gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
-                             sizeof(afl_prev_loc_ptr));
+    gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
 
     gum_x86_writer_put_label(cw, after_log_impl);
 
diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c
index 0efbc9bf..c30ca65c 100644
--- a/frida_mode/src/prefetch.c
+++ b/frida_mode/src/prefetch.c
@@ -44,8 +44,9 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
       sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size;
   if (sizeof(gsize) + size > remaining) { return; }
 
-  *(gsize *)(&prefetch_data->backpatch_data[prefetch_data->backpatch_size]) =
-      size;
+  gsize *dst_backpatch_size = (gsize *)
+      &prefetch_data->backpatch_data[prefetch_data->backpatch_size];
+  *dst_backpatch_size = size;
   prefetch_data->backpatch_size += sizeof(gsize);
 
   memcpy(&prefetch_data->backpatch_data[prefetch_data->backpatch_size],
@@ -115,7 +116,8 @@ static void prefetch_read_patches(void) {
        remaining > sizeof(gsize);
        remaining = prefetch_data->backpatch_size - offset) {
 
-    gsize size = *(gsize *)(&prefetch_data->backpatch_data[offset]);
+    gsize *src_backpatch_data = (gsize *)&prefetch_data->backpatch_data[offset];
+    gsize size = *src_backpatch_data;
     offset += sizeof(gsize);
 
     if (prefetch_data->backpatch_size - offset < size) {
diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c
index 4af2ed0c..7e1e2070 100644
--- a/frida_mode/src/seccomp/seccomp_callback.c
+++ b/frida_mode/src/seccomp/seccomp_callback.c
@@ -14,8 +14,12 @@ static void seccomp_callback_filter(struct seccomp_notif *     req,
   GumDebugSymbolDetails details = {0};
   if (req->data.nr == SYS_OPENAT) {
 
+#if UINTPTR_MAX == 0xffffffffffffffffu
     seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]);
-
+#endif
+#if UINTPTR_MAX == 0xffffffff
+    seccomp_print("SYS_OPENAT: (%s)\n", (char *)(__u32)req->data.args[1]);
+#endif
   }
 
   seccomp_print(
diff --git a/frida_mode/test/freetype2/GNUmakefile b/frida_mode/test/freetype2/GNUmakefile
new file mode 100644
index 00000000..891660ca
--- /dev/null
+++ b/frida_mode/test/freetype2/GNUmakefile
@@ -0,0 +1,192 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
+AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so
+
+# git clone git://git.sv.nongnu.org/freetype/freetype2.git
+# git clone https://github.com/unicode-org/text-rendering-tests.git TRT
+# wget https://github.com/libarchive/libarchive/releases/download/v3.4.3/libarchive-3.4.3.tar.xz
+
+# cp TRT/fonts/TestKERNOne.otf $OUT/seeds/
+# cp TRT/fonts/TestGLYFOne.ttf $OUT/seeds/
+
+# $CXX $CXXFLAGS -std=c++11 -I include -I . src/tools/ftfuzzer/ftfuzzer.cc \
+#     objs/.libs/libfreetype.a $FUZZER_LIB -L /usr/local/lib -larchive \
+#     -o $OUT/ftfuzzer
+
+LIBARCHIVE_URL:=https://github.com/libarchive/libarchive/releases/download/v3.4.3/libarchive-3.4.3.tar.xz
+LIBARCHIVE_BUILD_DIR:=$(BUILD_DIR)libarchive/
+LIBARCHIVE_TARBALL:=$(LIBARCHIVE_BUILD_DIR)libarchive-3.4.3.tar.xz
+LIBARCHIVE_DIR:=$(LIBARCHIVE_BUILD_DIR)libarchive-3.4.3/
+LIBARCHIVE_LIB:=$(LIBARCHIVE_DIR).libs/libarchive.a
+
+FREETYPE2_GIT_REPO:=git://git.sv.nongnu.org/freetype/freetype2.git
+FREETYPE2_BUILD_DIR:=$(BUILD_DIR)freetype2/
+FREETYPE2_DIR:=$(FREETYPE2_BUILD_DIR)freetype2/
+FREETYPE2_LIB:=$(FREETYPE2_DIR)objs/.libs/libfreetype.a
+
+HARNESS_URL:=https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c
+HARNESS_SRC:=$(BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(BUILD_DIR)StandaloneFuzzTargetMain.o
+
+TRT_GIT_REPO:=https://github.com/unicode-org/text-rendering-tests.git
+TRT_DIR:=$(BUILD_DIR)TRT/
+
+FUZZER_SRC:=$(FREETYPE2_DIR)src/tools/ftfuzzer/ftfuzzer.cc
+
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed
+
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
+
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
+endif
+
+.PHONY: all clean frida hook
+
+all: $(TEST_BIN)
+	make -C $(ROOT)frida_mode/
+
+32:
+	CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+	mkdir -p $@
+
+########## LIBARCHIVE #######
+
+$(LIBARCHIVE_BUILD_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(LIBARCHIVE_TARBALL): | $(LIBARCHIVE_BUILD_DIR)
+	wget -O $@ $(LIBARCHIVE_URL)
+
+$(LIBARCHIVE_DIR): | $(LIBARCHIVE_TARBALL)
+	tar Jxvf $(LIBARCHIVE_TARBALL) -C $(LIBARCHIVE_BUILD_DIR)
+
+$(LIBARCHIVE_DIR)Makefile: | $(LIBARCHIVE_DIR)
+	cd $(LIBARCHIVE_DIR) && ./configure --disable-shared
+
+$(LIBARCHIVE_LIB): $(LIBARCHIVE_DIR)Makefile
+	make -C $(LIBARCHIVE_DIR) clean all
+
+########## FREETYPE2 #######
+
+$(FREETYPE2_BUILD_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(FREETYPE2_DIR): | $(FREETYPE2_BUILD_DIR)
+	git clone $(FREETYPE2_GIT_REPO) $@
+	git -C $(FREETYPE2_DIR) checkout cd02d359a6d0455e9d16b87bf9665961c4699538
+
+$(FREETYPE2_LIB): | $(FREETYPE2_DIR)
+	cd $(FREETYPE2_DIR) && ./autogen.sh
+	cd $(FREETYPE2_DIR) && ./configure --with-harfbuzz=no --with-bzip2=no --with-png=no --without-zlib
+	make -C $(FREETYPE2_DIR) all
+
+########## HARNESS #######
+
+$(HARNESS_SRC):
+	wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_SRC)
+	$(CC) -o $@ -c $<
+
+########## TEST #######
+
+$(TEST_BIN): $(LIBARCHIVE_LIB) $(FREETYPE2_LIB) $(HARNESS_OBJ)
+	$(CXX) \
+		$(CXXFLAGS) \
+		-std=c++11 \
+		-I $(FREETYPE2_DIR)include \
+		-I $(FREETYPE2_DIR) \
+		-I $(LIBARCHIVE_DIR)/libarchive \
+		$(FUZZER_SRC) \
+     	$(FREETYPE2_LIB) \
+		$(LIBARCHIVE_LIB) \
+		$(HARNESS_OBJ) \
+	    -o $@
+
+########## DUMMY #######
+
+$(TRT_DIR): | $(BUILD_DIR)
+	git clone $(TRT_GIT_REPO) $@
+
+$(TEST_DATA_DIR): | $(TRT_DIR)
+	mkdir -p $@
+	cp $(TRT_DIR)fonts/TestKERNOne.otf $@
+	cp $(TRT_DIR)fonts/TestGLYFOne.ttf $@
+
+$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
+	dd if=/dev/zero bs=1048576 count=1 of=$@
+
+###### TEST DATA #######
+
+clean:
+	rm -rf $(BUILD_DIR)
+
+frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_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 \
+		-i $(TEST_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-m none \
+		-d \
+		-O \
+		-V 30 \
+		-- \
+			$(TEST_BIN) $(TEST_DATA_FILE)
+
+qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
+	AFL_QEMU_PERSISTENT_CNT=1000000 \
+	AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \
+	AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-i $(TEST_DATA_DIR) \
+		-o $(QEMU_OUT) \
+		-m none \
+		-d \
+		-Q \
+		-V 30 \
+		-- \
+			$(TEST_BIN) $(TEST_DATA_FILE)
diff --git a/frida_mode/test/freetype2/Makefile b/frida_mode/test/freetype2/Makefile
new file mode 100644
index 00000000..07b139e9
--- /dev/null
+++ b/frida_mode/test/freetype2/Makefile
@@ -0,0 +1,13 @@
+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
diff --git a/frida_mode/test/freetype2/get_symbol_addr.py b/frida_mode/test/freetype2/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/freetype2/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+    with open(file, 'rb') as f:
+        elf = ELFFile(f)
+        symtab = elf.get_section_by_name('.symtab')
+        mains = symtab.get_symbol_by_name(symbol)
+        if len(mains) != 1:
+            print ("Failed to find main")
+            return 1
+
+        main_addr = mains[0]['st_value']
+        main = base + main_addr
+        print ("0x%016x" % main)
+        return 0
+
+def hex_value(x):
+    return int(x, 16)
+
+def main():
+    parser = argparse.ArgumentParser(description='Process some integers.')
+    parser.add_argument('-f', '--file', dest='file', type=str,
+                    help='elf file name', required=True)
+    parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+                    help='symbol name', required=True)
+    parser.add_argument('-b', '--base', dest='base', type=hex_value,
+                    help='elf base address', required=True)
+
+    args = parser.parse_args()
+    return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+    ret = main()
+    exit(ret)
diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile
index 6f2b58af..f8dc3db7 100644
--- a/frida_mode/test/libpcap/GNUmakefile
+++ b/frida_mode/test/libpcap/GNUmakefile
@@ -59,7 +59,7 @@ GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
 
 AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
 
-ifeq "$(ARCH)" "aarch64"
+ifeq "$(ARCH)" "arm64"
  AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
 endif
 
diff --git a/include/config.h b/include/config.h
index da74989e..4630da0c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -237,11 +237,11 @@
    (note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c
    and afl-fuzz-state.c have to be changed as well! */
 
-#define MAX_FILE (1 * 1024 * 1024U)
+#define MAX_FILE (1 * 1024 * 1024L)
 
 /* The same, for the test case minimizer: */
 
-#define TMIN_MAX_FILE (10 * 1024 * 1024)
+#define TMIN_MAX_FILE (10 * 1024 * 1024L)
 
 /* Block normalization steps for afl-tmin: */
 
diff --git a/instrumentation/README.laf-intel.md b/instrumentation/README.laf-intel.md
index 229807e8..789055ed 100644
--- a/instrumentation/README.laf-intel.md
+++ b/instrumentation/README.laf-intel.md
@@ -3,9 +3,8 @@
 ## Introduction
 
 This originally is the work of an individual nicknamed laf-intel.
-His blog [Circumventing Fuzzing Roadblocks with Compiler Transformations]
-(https://lafintel.wordpress.com/) and gitlab repo [laf-llvm-pass]
-(https://gitlab.com/laf-intel/laf-llvm-pass/)
+His blog [Circumventing Fuzzing Roadblocks with Compiler Transformations](https://lafintel.wordpress.com/)
+and gitlab repo [laf-llvm-pass](https://gitlab.com/laf-intel/laf-llvm-pass/)
 describe some code transformations that
 help AFL++ to enter conditional blocks, where conditions consist of
 comparisons of large values.
diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md
index 6e210a7c..5b1e60cc 100644
--- a/instrumentation/README.llvm.md
+++ b/instrumentation/README.llvm.md
@@ -2,7 +2,7 @@
 
   (See [../README.md](../README.md) for the general instruction manual.)
 
-  (See [README.gcc_plugin.md](../README.gcc_plugin.md) for the GCC-based instrumentation.)
+  (See [README.gcc_plugin.md](README.gcc_plugin.md) for the GCC-based instrumentation.)
 
 ## 1) Introduction
 
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index e06f8b93..960eb783 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -250,7 +250,7 @@ class ModuleSanitizerCoverage {
   Module *                         Mo = NULL;
   GlobalVariable *                 AFLMapPtr = NULL;
   Value *                          MapPtrFixed = NULL;
-  FILE *                           documentFile = NULL;
+  std::ofstream                    dFile;
   size_t                           found = 0;
   // afl++ END
 
@@ -446,7 +446,8 @@ bool ModuleSanitizerCoverage::instrumentModule(
 
   if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
 
-    if ((documentFile = fopen(ptr, "a")) == NULL)
+    dFile.open(ptr, std::ofstream::out | std::ofstream::app);
+    if (dFile.is_open())
       WARNF("Cannot access document file %s", ptr);
 
   }
@@ -1003,12 +1004,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
     instrumentFunction(F, DTCallback, PDTCallback);
 
   // afl++ START
-  if (documentFile) {
-
-    fclose(documentFile);
-    documentFile = NULL;
-
-  }
+  if (dFile.is_open()) dFile.close();
 
   if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) {
 
@@ -1069,7 +1065,6 @@ bool ModuleSanitizerCoverage::instrumentModule(
     if (dictionary.size()) {
 
       size_t memlen = 0, count = 0, offset = 0;
-      char * ptr;
 
       // sort and unique the dictionary
       std::sort(dictionary.begin(), dictionary.end());
@@ -1089,13 +1084,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
 
       if (count) {
 
-        if ((ptr = (char *)malloc(memlen + count)) == NULL) {
-
-          fprintf(stderr, "Error: malloc for %lu bytes failed!\n",
-                  memlen + count);
-          exit(-1);
-
-        }
+        auto ptrhld = std::unique_ptr<char []>(new char[memlen + count]);
 
         count = 0;
 
@@ -1103,8 +1092,8 @@ bool ModuleSanitizerCoverage::instrumentModule(
 
           if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
 
-            ptr[offset++] = (uint8_t)token.length();
-            memcpy(ptr + offset, token.c_str(), token.length());
+            ptrhld.get()[offset++] = (uint8_t)token.length();
+            memcpy(ptrhld.get() + offset, token.c_str(), token.length());
             offset += token.length();
             count++;
 
@@ -1124,10 +1113,10 @@ bool ModuleSanitizerCoverage::instrumentModule(
         GlobalVariable *AFLInternalDictionary = new GlobalVariable(
             M, ArrayTy, true, GlobalValue::ExternalLinkage,
             ConstantDataArray::get(Ctx,
-                                   *(new ArrayRef<char>((char *)ptr, offset))),
+                                   *(new ArrayRef<char>(ptrhld.get(), offset))),
             "__afl_internal_dictionary");
         AFLInternalDictionary->setInitializer(ConstantDataArray::get(
-            Ctx, *(new ArrayRef<char>((char *)ptr, offset))));
+            Ctx, *(new ArrayRef<char>(ptrhld.get(), offset))));
         AFLInternalDictionary->setConstant(true);
 
         GlobalVariable *AFLDictionary = new GlobalVariable(
@@ -1509,12 +1498,11 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     // afl++ START
     ++afl_global_id;
 
-    if (documentFile) {
+    if (dFile.is_open()) {
 
       unsigned long long int moduleID =
           (((unsigned long long int)(rand() & 0xffffffff)) << 32) | getpid();
-      fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%u\n", moduleID,
-              F.getName().str().c_str(), afl_global_id);
+      dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str() << " edgeID=" << afl_global_id << "\n";
 
     }
 
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index 4622e488..c4ad1783 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -65,7 +65,8 @@ using namespace llvm;
 namespace {
 
 class AFLdict2filePass : public ModulePass {
-
+  std::ofstream of;
+  void dict2file(u8 *, u32);
  public:
   static char ID;
 
@@ -81,7 +82,7 @@ class AFLdict2filePass : public ModulePass {
 
 }  // namespace
 
-void dict2file(int fd, u8 *mem, u32 len) {
+void AFLdict2filePass::dict2file(u8 *mem, u32 len) {
 
   u32  i, j, binary = 0;
   char line[MAX_AUTO_EXTRA * 8], tmp[8];
@@ -113,9 +114,8 @@ void dict2file(int fd, u8 *mem, u32 len) {
 
   line[j] = 0;
   strcat(line, "\"\n");
-  if (write(fd, line, strlen(line)) <= 0)
-    PFATAL("Could not write to dictionary file");
-  fsync(fd);
+  of << line;
+  of.flush();
 
   if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line);
 
@@ -125,7 +125,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
   DenseMap<Value *, std::string *> valueMap;
   char *                           ptr;
-  int                              fd, found = 0;
+  int                              found = 0;
 
   /* Show a banner */
   setvbuf(stdout, NULL, _IONBF, 0);
@@ -146,7 +146,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
   if (!ptr || *ptr != '/')
     FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr);
 
-  if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0)
+  of.open(ptr, std::ofstream::out | std::ofstream::app);
+  if (!of.is_open())
     PFATAL("Could not open/create %s.", ptr);
 
   /* Instrument all the things! */
@@ -264,11 +265,11 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
               }
 
-              dict2file(fd, (u8 *)&val, len);
+              dict2file((u8 *)&val, len);
               found++;
               if (val2) {
 
-                dict2file(fd, (u8 *)&val2, len);
+                dict2file((u8 *)&val2, len);
                 found++;
 
               }
@@ -630,7 +631,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
           ptr = (char *)thestring.c_str();
 
-          dict2file(fd, (u8 *)ptr, optLen);
+          dict2file((u8 *)ptr, optLen);
           found++;
 
         }
@@ -641,7 +642,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
   }
 
-  close(fd);
+  of.close();
 
   /* Say something nice. */
 
diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc
index e300044c..73e41f60 100644
--- a/instrumentation/afl-llvm-lto-instrumentation.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc
@@ -28,6 +28,7 @@
 #include <sys/time.h>
 
 #include <list>
+#include <memory>
 #include <string>
 #include <fstream>
 #include <set>
@@ -107,8 +108,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
   //  std::vector<CallInst *>          calls;
   DenseMap<Value *, std::string *> valueMap;
   std::vector<BasicBlock *>        BlockList;
+  std::ofstream                    dFile;
   char *                           ptr;
-  FILE *                           documentFile = NULL;
   size_t                           found = 0;
 
   srand((unsigned int)time(NULL));
@@ -136,7 +137,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
 
-    if ((documentFile = fopen(ptr, "a")) == NULL)
+    dFile.open(ptr, std::ofstream::out | std::ofstream::app);
+    if (!dFile.is_open())
       WARNF("Cannot access document file %s", ptr);
 
   }
@@ -844,10 +846,9 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
           }
 
-          if (documentFile) {
+          if (dFile.is_open()) {
 
-            fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%u\n",
-                    moduleID, F.getName().str().c_str(), afl_global_id);
+             dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str() << " edgeID=" << afl_global_id << "\n";
 
           }
 
@@ -919,8 +920,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   }
 
-  if (documentFile) fclose(documentFile);
-  documentFile = NULL;
+  if (dFile.is_open()) dFile.close();
 
   // save highest location ID to global variable
   // do this after each function to fail faster
@@ -1015,13 +1015,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
       if (count) {
 
-        if ((ptr = (char *)malloc(memlen + count)) == NULL) {
-
-          fprintf(stderr, "Error: malloc for %zu bytes failed!\n",
-                  memlen + count);
-          exit(-1);
-
-        }
+        auto ptrhld = std::unique_ptr<char []>(new char[memlen + count]);
 
         count = 0;
 
@@ -1030,8 +1024,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
           if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
 
-            ptr[offset++] = (uint8_t)token.length();
-            memcpy(ptr + offset, token.c_str(), token.length());
+            ptrhld.get()[offset++] = (uint8_t)token.length();
+            memcpy(ptrhld.get() + offset, token.c_str(), token.length());
             offset += token.length();
             count++;
 
@@ -1051,10 +1045,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
         GlobalVariable *AFLInternalDictionary = new GlobalVariable(
             M, ArrayTy, true, GlobalValue::ExternalLinkage,
             ConstantDataArray::get(C,
-                                   *(new ArrayRef<char>((char *)ptr, offset))),
+                                   *(new ArrayRef<char>(ptrhld.get(), offset))),
             "__afl_internal_dictionary");
         AFLInternalDictionary->setInitializer(ConstantDataArray::get(
-            C, *(new ArrayRef<char>((char *)ptr, offset))));
+            C, *(new ArrayRef<char>(ptrhld.get(), offset))));
         AFLInternalDictionary->setConstant(true);
 
         GlobalVariable *AFLDictionary = new GlobalVariable(
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 215826cc..7bdedf7b 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-a6758d1cc3
+71ed0d206f
diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c
index 4fc84e62..24867cda 100644
--- a/qemu_mode/libcompcov/libcompcov.so.c
+++ b/qemu_mode/libcompcov/libcompcov.so.c
@@ -41,6 +41,13 @@
   #error "Sorry, this library is Linux-specific for now!"
 #endif                                                        /* !__linux__ */
 
+#ifndef likely
+#  define likely(x)       __builtin_expect((!!(x)),1)
+#endif
+#ifndef unlikely
+#  define unlikely(x)     __builtin_expect((!!(x)),0)
+#endif
+
 /* Change this value to tune the compare coverage */
 
 #define MAX_CMP_LENGTH 32
@@ -199,6 +206,7 @@ static u8 __compcov_is_in_bound(const void *ptr) {
 
 int strcmp(const char *str1, const char *str2) {
 
+  if (unlikely(!__libc_strcmp)) { __libc_strcmp = dlsym(RTLD_NEXT, "strcmp"); }
   void *retaddr = __builtin_return_address(0);
 
   if (__compcov_is_in_bound(retaddr) &&
@@ -227,6 +235,7 @@ int strcmp(const char *str1, const char *str2) {
 
 int strncmp(const char *str1, const char *str2, size_t len) {
 
+  if (unlikely(!__libc_strncmp)) { __libc_strncmp = dlsym(RTLD_NEXT, "strncmp"); }
   void *retaddr = __builtin_return_address(0);
 
   if (__compcov_is_in_bound(retaddr) &&
@@ -256,6 +265,7 @@ int strncmp(const char *str1, const char *str2, size_t len) {
 
 int strcasecmp(const char *str1, const char *str2) {
 
+  if (unlikely(!__libc_strcasecmp)) { __libc_strncasecmp = dlsym(RTLD_NEXT, "strcasecmp"); }
   void *retaddr = __builtin_return_address(0);
 
   if (__compcov_is_in_bound(retaddr) &&
@@ -286,6 +296,7 @@ int strcasecmp(const char *str1, const char *str2) {
 
 int strncasecmp(const char *str1, const char *str2, size_t len) {
 
+  if (unlikely(!__libc_strncasecmp)) { __libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp"); }
   void *retaddr = __builtin_return_address(0);
 
   if (__compcov_is_in_bound(retaddr) &&
@@ -317,6 +328,7 @@ int strncasecmp(const char *str1, const char *str2, size_t len) {
 
 int memcmp(const void *mem1, const void *mem2, size_t len) {
 
+  if (unlikely(!__libc_memcmp)) { __libc_memcmp = dlsym(RTLD_NEXT, "memcmp"); }
   void *retaddr = __builtin_return_address(0);
 
   if (__compcov_is_in_bound(retaddr) &&
diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl
-Subproject a6758d1cc3e4dde88fca3f0b3a903581b7c8b2e
+Subproject 71ed0d206fd3d877420dceb4993a1011a4637ae
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index eef08494..8295488d 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -184,7 +184,7 @@ static void read_initial_file(void) {
 
   if (st.st_size >= TMIN_MAX_FILE) {
 
-    FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
+    FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024);
 
   }
 
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index eb1fe2d9..870ba69a 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -560,8 +560,9 @@ void show_stats(afl_state_t *afl) {
 
   /* Roughly every minute, update fuzzer stats and save auto tokens. */
 
-  if (unlikely(afl->force_ui_update ||
-               cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000)) {
+  if (unlikely(!afl->non_instrumented_mode &&
+               (afl->force_ui_update ||
+                cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) {
 
     afl->stats_last_stats_ms = cur_ms;
     write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8ffc0e77..92a37697 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1348,7 +1348,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   } else if (afl->q_testcase_max_cache_size < 2 * MAX_FILE) {
 
-    FATAL("AFL_TESTCACHE_SIZE must be set to %u or more, or 0 to disable",
+    FATAL("AFL_TESTCACHE_SIZE must be set to %ld or more, or 0 to disable",
           (2 * MAX_FILE) % 1048576 == 0 ? (2 * MAX_FILE) / 1048576
                                         : 1 + ((2 * MAX_FILE) / 1048576));
 
@@ -1918,7 +1918,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  write_stats_file(afl, 0, 0, 0, 0);
+  if (!afl->non_instrumented_mode) { write_stats_file(afl, 0, 0, 0, 0); }
   maybe_update_plot_file(afl, 0, 0, 0);
   save_auto(afl);
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index e143371e..75b0ff99 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -413,7 +413,7 @@ static u32 read_file(u8 *in_file) {
 
     if (!be_quiet && !quiet_mode) {
 
-      WARNF("Input file '%s' is too large, only reading %u bytes.", in_file,
+      WARNF("Input file '%s' is too large, only reading %ld bytes.", in_file,
             MAX_FILE);
 
     }
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index dff51e84..4f3a6b80 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -221,7 +221,7 @@ static void read_initial_file(void) {
 
   if (st.st_size >= TMIN_MAX_FILE) {
 
-    FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
+    FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024);
 
   }
 
diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION
index 0d84243c..cbca63e5 100644
--- a/unicorn_mode/UNICORNAFL_VERSION
+++ b/unicorn_mode/UNICORNAFL_VERSION
@@ -1 +1 @@
-1c47d1ebc7e904ad4efc1370f23e269fb9ac3f93
+f1c853648a74b0157d233a2ef9f1693cfee78c11
diff --git a/unicorn_mode/samples/speedtest/rust/src/main.rs b/unicorn_mode/samples/speedtest/rust/src/main.rs
index 105ba4b4..77356a67 100644
--- a/unicorn_mode/samples/speedtest/rust/src/main.rs
+++ b/unicorn_mode/samples/speedtest/rust/src/main.rs
@@ -105,7 +105,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
     // Set the program counter to the start of the code
     let main_locs = parse_locs("main").unwrap();
     //println!("Entry Point: {:x}", main_locs[0]);
-    uc.reg_write(RegisterX86::RIP as i32, main_locs[0])?;
+    uc.reg_write(RIP, main_locs[0])?;
 
     // Setup the stack.
     uc.mem_map(
@@ -114,14 +114,14 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
         Permission::READ | Permission::WRITE,
     )?;
     // Setup the stack pointer, but allocate two pointers for the pointers to input.
-    uc.reg_write(RSP as i32, STACK_ADDRESS + STACK_SIZE - 16)?;
+    uc.reg_write(RSP, STACK_ADDRESS + STACK_SIZE - 16)?;
 
     // Setup our input space, and push the pointer to it in the function params
     uc.mem_map(INPUT_ADDRESS, INPUT_MAX as usize, Permission::READ)?;
     // We have argc = 2
-    uc.reg_write(RDI as i32, 2)?;
+    uc.reg_write(RDI, 2)?;
     // RSI points to our little 2 QWORD space at the beginning of the stack...
-    uc.reg_write(RSI as i32, STACK_ADDRESS + STACK_SIZE - 16)?;
+    uc.reg_write(RSI, STACK_ADDRESS + STACK_SIZE - 16)?;
     // ... which points to the Input. Write the ptr to mem in little endian.
     uc.mem_write(
         STACK_ADDRESS + STACK_SIZE - 16,
@@ -139,7 +139,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
             abort();
         }
         // read the first param
-        let malloc_size = uc.reg_read(RDI as i32).unwrap();
+        let malloc_size = uc.reg_read(RDI).unwrap();
         if malloc_size > HEAP_SIZE_MAX {
             println!(
                 "Tried to allocate {} bytes, but we may only allocate up to {}",
@@ -147,8 +147,8 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
             );
             abort();
         }
-        uc.reg_write(RAX as i32, HEAP_ADDRESS).unwrap();
-        uc.reg_write(RIP as i32, addr + size as u64).unwrap();
+        uc.reg_write(RAX, HEAP_ADDRESS).unwrap();
+        uc.reg_write(RIP, addr + size as u64).unwrap();
         already_allocated_malloc.set(true);
     };
 
@@ -160,7 +160,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
             abort();
         }
         // read the first param
-        let free_ptr = uc.reg_read(RDI as i32).unwrap();
+        let free_ptr = uc.reg_read(RDI).unwrap();
         if free_ptr != HEAP_ADDRESS {
             println!(
                 "Tried to free wrong mem region {:x} at code loc {:x}",
@@ -168,7 +168,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
             );
             abort();
         }
-        uc.reg_write(RIP as i32, addr + size as u64).unwrap();
+        uc.reg_write(RIP, addr + size as u64).unwrap();
         already_allocated_free.set(false);
     };
 
@@ -178,7 +178,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
 
     // This is a fancy print function that we're just going to skip for fuzzing.
     let hook_magicfn = move |mut uc: UnicornHandle<'_, _>, addr, size| {
-        uc.reg_write(RIP as i32, addr + size as u64).unwrap();
+        uc.reg_write(RIP, addr + size as u64).unwrap();
     };
 
     for addr in parse_locs("malloc").unwrap() {
diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl
-Subproject 019b871539fe9ed3f41d882385a8b02c243d49a
+Subproject f1c853648a74b0157d233a2ef9f1693cfee78c1