about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c48
-rw-r--r--src/afl-as.c7
-rw-r--r--src/afl-cc.c64
-rw-r--r--src/afl-common.c101
-rw-r--r--src/afl-forkserver.c62
-rw-r--r--src/afl-fuzz-bitmap.c29
-rw-r--r--src/afl-fuzz-cmplog.c2
-rw-r--r--src/afl-fuzz-extras.c2
-rw-r--r--src/afl-fuzz-init.c51
-rw-r--r--src/afl-fuzz-mutators.c5
-rw-r--r--src/afl-fuzz-one.c27
-rw-r--r--src/afl-fuzz-python.c2
-rw-r--r--src/afl-fuzz-queue.c93
-rw-r--r--src/afl-fuzz-redqueen.c367
-rw-r--r--src/afl-fuzz-run.c32
-rw-r--r--src/afl-fuzz-state.c2
-rw-r--r--src/afl-fuzz-stats.c74
-rw-r--r--src/afl-fuzz.c102
-rw-r--r--src/afl-gotcpu.c2
-rw-r--r--src/afl-ld-lto.c2
-rw-r--r--src/afl-performance.c8
-rw-r--r--src/afl-sharedmem.c2
-rw-r--r--src/afl-showmap.c81
-rw-r--r--src/afl-tmin.c47
24 files changed, 894 insertions, 318 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index e19df3ce..ac5a324c 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    A nifty utility that grabs an input file and takes a stab at explaining
    its structure by observing how changes to it affect the execution path.
@@ -77,6 +77,7 @@ static volatile u8 stop_soon;          /* Ctrl-C pressed?                   */
 static u8 *target_path;
 static u8  frida_mode;
 static u8  qemu_mode;
+static u8  cs_mode;
 static u32 map_size = MAP_SIZE;
 
 static afl_forkserver_t fsrv = {0};   /* The forkserver                     */
@@ -120,6 +121,17 @@ static u8 count_class_lookup[256] = {
 #undef TIMES8
 #undef TIMES4
 
+static void kill_child() {
+
+  if (fsrv.child_pid > 0) {
+
+    kill(fsrv.child_pid, fsrv.kill_signal);
+    fsrv.child_pid = -1;
+
+  }
+
+}
+
 static void classify_counts(u8 *mem) {
 
   u32 i = map_size;
@@ -184,7 +196,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);
 
   }
 
@@ -779,6 +791,8 @@ static void set_up_environment(char **argv) {
 
     } else {
 
+      /* CoreSight mode uses the default behavior. */
+
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
       setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
 
@@ -834,11 +848,17 @@ static void usage(u8 *argv0) {
       "  -f file       - input file read by the tested program (stdin)\n"
       "  -t msec       - timeout for each run (%u ms)\n"
       "  -m megs       - memory limit for child process (%u MB)\n"
+#if defined(__linux__) && defined(__aarch64__)
+      "  -A            - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
       "  -O            - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
-      "mode)\n\n"
+      "mode)\n"
+#endif
+      "\n"
 
       "Analysis settings:\n"
 
@@ -879,7 +899,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   afl_fsrv_init(&fsrv);
 
-  while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) {
 
     switch (opt) {
 
@@ -978,13 +998,25 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
+      case 'A':                                           /* CoreSight mode */
+
+#if !defined(__aarch64__) || !defined(__linux__)
+        FATAL("-A option is not supported on this platform");
+#endif
+
+        if (cs_mode) { FATAL("Multiple -A options not supported"); }
+
+        cs_mode = 1;
+        fsrv.cs_mode = cs_mode;
+        break;
+
       case 'O':                                               /* FRIDA mode */
 
         if (frida_mode) { FATAL("Multiple -O options not supported"); }
 
         frida_mode = 1;
         fsrv.frida_mode = frida_mode;
-        setenv("AFL_FRIDA_INST_SEED", "0x0", 1);
+        setenv("AFL_FRIDA_INST_SEED", "1", 1);
 
         break;
 
@@ -1053,6 +1085,7 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv.target_path = find_binary(argv[optind]);
   fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
   detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
+  signal(SIGALRM, kill_child);
 
   if (qemu_mode) {
 
@@ -1068,6 +1101,10 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+  } else if (cs_mode) {
+
+    use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
+
   } else {
 
     use_argv = argv + optind;
@@ -1093,6 +1130,7 @@ int main(int argc, char **argv_orig, char **envp) {
       parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
 
   read_initial_file();
+  (void)check_binary_signatures(fsrv.target_path);
 
   ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
        mem_limit, exec_tmout, edges_only ? ", edges only" : "");
diff --git a/src/afl-as.c b/src/afl-as.c
index 7119d630..b644b82a 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    The sole purpose of this wrapper is to preprocess assembly files generated
    by GCC / clang and inject the instrumentation bits included from afl-as.h. It
@@ -101,7 +101,7 @@ static void edit_params(int argc, char **argv) {
 
   /* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work
      with the code generated by newer versions of clang that are hand-built
-     by the user. See the thread here: http://goo.gl/HBWDtn.
+     by the user. See the thread here: https://goo.gl/HBWDtn.
 
      To work around this, when using clang and running without AFL_AS
      specified, we will actually call 'clang -c' instead of 'as -q' to
@@ -517,10 +517,11 @@ static void add_instrumentation(void) {
     } else {
 
       char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
+      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s",
                getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
                getenv("AFL_USE_ASAN") ? ", ASAN" : "",
                getenv("AFL_USE_MSAN") ? ", MSAN" : "",
+               getenv("AFL_USE_TSAN") ? ", TSAN" : "",
                getenv("AFL_USE_UBSAN") ? ", UBSAN" : "",
                getenv("AFL_USE_LSAN") ? ", LSAN" : "");
 
diff --git a/src/afl-cc.c b/src/afl-cc.c
index e49addc4..6bdb9572 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -11,7 +11,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
  */
 
@@ -423,6 +423,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
     cc_params[cc_par_cnt++] = fplugin_arg;
+    cc_params[cc_par_cnt++] = "-fno-if-conversion";
+    cc_params[cc_par_cnt++] = "-fno-if-conversion2";
 
   }
 
@@ -564,22 +566,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
       free(ld_path);
 
       cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
-
-      if (instrument_mode == INSTRUMENT_CFG ||
-          instrument_mode == INSTRUMENT_PCGUARD)
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
-      else
-
-        cc_params[cc_par_cnt++] = alloc_printf(
-            "-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
       cc_params[cc_par_cnt++] = lto_flag;
 
     } else {
 
       if (instrument_mode == INSTRUMENT_PCGUARD) {
 
-#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
+#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR >= 1)
   #if defined __ANDROID__ || ANDROID
         cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
         instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -735,6 +730,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     }
 
+    if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
+        !strncmp(cur, "-stdlib=", 8)) {
+
+      if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+      continue;
+
+    }
+
     if ((!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) ||
          !strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
         (strncmp(cur, "sanitize-coverage-allow",
@@ -847,6 +850,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     cc_params[cc_par_cnt++] = "-fsanitize=undefined";
     cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error";
     cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all";
+    cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer";
+
+  }
+
+  if (getenv("AFL_USE_TSAN")) {
+
+    cc_params[cc_par_cnt++] = "-fsanitize=thread";
+    cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer";
 
   }
 
@@ -1007,7 +1018,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   }
 
   // prevent unnecessary build errors
-  cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
+  if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) {
+
+    cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
+
+  }
 
   if (preprocessor_only || have_c) {
 
@@ -1152,7 +1167,7 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
-#if (LLVM_MAJOR > 2)
+#if (LLVM_MAJOR >= 3)
 
   if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) {
 
@@ -1181,7 +1196,7 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
-#if (LLVM_MAJOR > 2)
+#if (LLVM_MAJOR >= 3)
 
   if (strncmp(callname, "afl-clang-fast", 14) == 0) {
 
@@ -1709,8 +1724,8 @@ int main(int argc, char **argv, char **envp) {
         compiler_mode == LTO ? " [SELECTED]" : "",
         have_llvm ? "AVAILABLE" : "unavailable!",
         compiler_mode == LLVM ? " [SELECTED]" : "",
-        LLVM_MAJOR > 6 ? "DEFAULT" : "       ",
-        LLVM_MAJOR > 6 ? "       " : "DEFAULT",
+        LLVM_MAJOR >= 7 ? "DEFAULT" : "       ",
+        LLVM_MAJOR >= 7 ? "       " : "DEFAULT",
         have_gcc_plugin ? "AVAILABLE" : "unavailable!",
         compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "",
         have_gcc ? "AVAILABLE" : "unavailable!",
@@ -1800,6 +1815,7 @@ int main(int argc, char **argv, char **envp) {
           "  AFL_USE_CFISAN: activate control flow sanitizer\n"
           "  AFL_USE_MSAN: activate memory sanitizer\n"
           "  AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
+          "  AFL_USE_TSAN: activate thread sanitizer\n"
           "  AFL_USE_LSAN: activate leak-checker sanitizer\n");
 
       if (have_gcc_plugin)
@@ -1810,12 +1826,12 @@ int main(int argc, char **argv, char **envp) {
             "  AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
             "filename\n");
 
-#if LLVM_MAJOR < 9
+#if LLVM_MAJOR >= 9
   #define COUNTER_BEHAVIOUR \
-    "  AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
+    "  AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
 #else
   #define COUNTER_BEHAVIOUR \
-    "  AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
+    "  AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
 #endif
       if (have_llvm)
         SAYF(
@@ -1889,7 +1905,7 @@ int main(int argc, char **argv, char **envp) {
         "consult the README.md, especially section 3.1 about instrumenting "
         "targets.\n\n");
 
-#if (LLVM_MAJOR > 2)
+#if (LLVM_MAJOR >= 3)
     if (have_lto)
       SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO);
     if (have_llvm)
@@ -1951,9 +1967,7 @@ int main(int argc, char **argv, char **envp) {
 
   if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) {
 
-#if LLVM_MAJOR <= 6
-    instrument_mode = INSTRUMENT_AFL;
-#else
+#if LLVM_MAJOR >= 7
   #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
     if (have_instr_env) {
 
@@ -1968,6 +1982,8 @@ int main(int argc, char **argv, char **envp) {
   #endif
       instrument_mode = INSTRUMENT_PCGUARD;
 
+#else
+    instrument_mode = INSTRUMENT_AFL;
 #endif
 
   }
@@ -2034,7 +2050,7 @@ int main(int argc, char **argv, char **envp) {
   if ((isatty(2) && !be_quiet) || debug) {
 
     SAYF(cCYA
-         "afl-cc " VERSION cRST
+         "afl-cc" VERSION cRST
          " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n",
          compiler_mode_string[compiler_mode], ptr);
 
diff --git a/src/afl-common.c b/src/afl-common.c
index 9ca2b3e8..6c2d0753 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    Gather some functions common to multiple executables
 
@@ -25,8 +25,12 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#define _GNU_SOURCE
+#define __USE_GNU
+#include <string.h>
 #include <strings.h>
 #include <math.h>
+#include <sys/mman.h>
 
 #include "debug.h"
 #include "alloc-inl.h"
@@ -51,6 +55,66 @@ u8  last_intr = 0;
   #define AFL_PATH "/usr/local/lib/afl/"
 #endif
 
+u32 check_binary_signatures(u8 *fn) {
+
+  int ret = 0, fd = open(fn, O_RDONLY);
+  if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
+  struct stat st;
+  if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
+  u32 f_len = st.st_size;
+  u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
+  close(fd);
+
+  if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
+
+    if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); }
+    setenv(PERSIST_ENV_VAR, "1", 1);
+    ret = 1;
+
+  } else if (getenv("AFL_PERSISTENT")) {
+
+    if (!be_quiet) {
+
+      WARNF("AFL_PERSISTENT is no longer supported and may misbehave!");
+
+    }
+
+  } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
+
+    if (!be_quiet) {
+
+      OKF("FRIDA Persistent mode configuration options detected.");
+
+    }
+
+    setenv(PERSIST_ENV_VAR, "1", 1);
+    ret = 1;
+
+  }
+
+  if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
+
+    if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); }
+    setenv(DEFER_ENV_VAR, "1", 1);
+    ret += 2;
+
+  } else if (getenv("AFL_DEFER_FORKSRV")) {
+
+    if (!be_quiet) {
+
+      WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!");
+
+    }
+
+  }
+
+  if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
+
+  return ret;
+
+}
+
 void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
 
   u32 i = 0;
@@ -140,6 +204,35 @@ void argv_cpy_free(char **argv) {
 
 }
 
+/* Rewrite argv for CoreSight process tracer. */
+
+char **get_cs_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
+
+  if (unlikely(getenv("AFL_CS_CUSTOM_BIN"))) {
+
+    WARNF(
+        "AFL_CS_CUSTOM_BIN is enabled. "
+        "You must run your target under afl-cs-proxy on your own!");
+    return argv;
+
+  }
+
+  char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
+  if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
+
+  memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
+  new_argv[argc + 3] = NULL;
+
+  new_argv[2] = *target_path_p;
+  new_argv[1] = "--";
+
+  /* Now we need to actually find the cs-proxy binary to put in argv[0]. */
+
+  *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-cs-proxy");
+  return new_argv;
+
+}
+
 /* Rewrite argv for QEMU. */
 
 char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
@@ -153,11 +246,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
 
   }
 
-  char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
+  char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
   if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
 
   memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
-  new_argv[argc + 3] = NULL;
 
   new_argv[2] = *target_path_p;
   new_argv[1] = "--";
@@ -173,11 +265,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
 
 char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
 
-  char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
+  char **new_argv = ck_alloc(sizeof(char *) * (argc + 2));
   if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
 
   memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
-  new_argv[argc + 2] = NULL;
 
   new_argv[1] = *target_path_p;
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c8c94c08..b871ea8c 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -19,7 +19,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    Shared code that implements a forkserver. This is used by the fuzzer
    as well the other components like afl-tmin.
@@ -342,6 +342,16 @@ static void report_error_and_exit(int error) {
           "the fuzzing target reports that the mmap() call to the shared "
           "memory failed.");
       break;
+    case FS_ERROR_OLD_CMPLOG:
+      FATAL(
+          "the -c cmplog target was instrumented with an too old afl++ "
+          "version, you need to recompile it.");
+      break;
+    case FS_ERROR_OLD_CMPLOG_QEMU:
+      FATAL(
+          "The AFL++ QEMU/FRIDA loaders are from an older version, for -c you "
+          "need to recompile it.\n");
+      break;
     default:
       FATAL("unknown error code %d from fuzzing target!", error);
 
@@ -351,7 +361,7 @@ static void report_error_and_exit(int error) {
 
 /* Spins up fork server. The idea is explained here:
 
-   http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
+   https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
 
    In essence, the instrumentation allows us to skip execve(), and just keep
    cloning a stopped child. So, we just execute once, and then send commands
@@ -603,19 +613,31 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
   /* Wait for the fork server to come up, but don't wait too long. */
 
   rlen = 0;
-  if (fsrv->exec_tmout) {
+  if (fsrv->init_tmout) {
 
     u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
                                  stop_soon_p);
 
     if (!time_ms) {
 
-      kill(fsrv->fsrv_pid, fsrv->kill_signal);
+      s32 tmp_pid = fsrv->fsrv_pid;
+      if (tmp_pid > 0) {
+
+        kill(tmp_pid, fsrv->kill_signal);
+        fsrv->fsrv_pid = -1;
+
+      }
 
     } else if (time_ms > fsrv->init_tmout) {
 
       fsrv->last_run_timed_out = 1;
-      kill(fsrv->fsrv_pid, fsrv->kill_signal);
+      s32 tmp_pid = fsrv->fsrv_pid;
+      if (tmp_pid > 0) {
+
+        kill(tmp_pid, fsrv->kill_signal);
+        fsrv->fsrv_pid = -1;
+
+      }
 
     } else {
 
@@ -651,6 +673,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
       if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
         status = (status & 0xf0ffffff);
 
+      if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
+
+        if (fsrv->qemu_mode || fsrv->frida_mode) {
+
+          report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
+
+        } else {
+
+          report_error_and_exit(FS_ERROR_OLD_CMPLOG);
+
+        }
+
+      }
+
       if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
 
         fsrv->snapshot = 1;
@@ -905,8 +941,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
            MSG_ULIMIT_USAGE
            " /path/to/fuzzed_app )\n\n"
 
-           "      Tip: you can use http://jwilk.net/software/recidivm to "
-           "quickly\n"
+           "      Tip: you can use https://jwilk.net/software/recidivm to\n"
            "      estimate the required amount of virtual memory for the "
            "binary.\n\n"
 
@@ -1005,7 +1040,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
         MSG_ULIMIT_USAGE
         " /path/to/fuzzed_app )\n\n"
 
-        "      Tip: you can use http://jwilk.net/software/recidivm to quickly\n"
+        "      Tip: you can use https://jwilk.net/software/recidivm to\n"
         "      estimate the required amount of virtual memory for the "
         "binary.\n\n"
 
@@ -1248,7 +1283,14 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
     /* If there was no response from forkserver after timeout seconds,
     we kill the child. The forkserver should inform us afterwards */
 
-    kill(fsrv->child_pid, fsrv->kill_signal);
+    s32 tmp_pid = fsrv->child_pid;
+    if (tmp_pid > 0) {
+
+      kill(tmp_pid, fsrv->kill_signal);
+      fsrv->child_pid = -1;
+
+    }
+
     fsrv->last_run_timed_out = 1;
     if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; }
 
@@ -1282,7 +1324,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
 
   }
 
-  if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = 0; }
+  if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = -1; }
 
   fsrv->total_execs++;
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 0ae4d607..fa413dcf 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -58,7 +58,7 @@ void write_bitmap(afl_state_t *afl) {
 u32 count_bits(afl_state_t *afl, u8 *mem) {
 
   u32 *ptr = (u32 *)mem;
-  u32  i = (afl->fsrv.map_size >> 2);
+  u32  i = ((afl->fsrv.real_map_size + 3) >> 2);
   u32  ret = 0;
 
   while (i--) {
@@ -68,7 +68,7 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
     /* This gets called on the inverse, virgin bitmap; optimize for sparse
        data. */
 
-    if (v == 0xffffffff) {
+    if (likely(v == 0xffffffff)) {
 
       ret += 32;
       continue;
@@ -92,14 +92,14 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
 u32 count_bytes(afl_state_t *afl, u8 *mem) {
 
   u32 *ptr = (u32 *)mem;
-  u32  i = (afl->fsrv.map_size >> 2);
+  u32  i = ((afl->fsrv.real_map_size + 3) >> 2);
   u32  ret = 0;
 
   while (i--) {
 
     u32 v = *(ptr++);
 
-    if (!v) { continue; }
+    if (likely(!v)) { continue; }
     if (v & 0x000000ffU) { ++ret; }
     if (v & 0x0000ff00U) { ++ret; }
     if (v & 0x00ff0000U) { ++ret; }
@@ -117,7 +117,7 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) {
 u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
 
   u32 *ptr = (u32 *)mem;
-  u32  i = (afl->fsrv.map_size >> 2);
+  u32  i = ((afl->fsrv.real_map_size + 3) >> 2);
   u32  ret = 0;
 
   while (i--) {
@@ -127,7 +127,7 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
     /* This is called on the virgin bitmap, so optimize for the most likely
        case. */
 
-    if (v == 0xffffffffU) { continue; }
+    if (likely(v == 0xffffffffU)) { continue; }
     if ((v & 0x000000ffU) != 0x000000ffU) { ++ret; }
     if ((v & 0x0000ff00U) != 0x0000ff00U) { ++ret; }
     if ((v & 0x00ff0000U) != 0x00ff0000U) { ++ret; }
@@ -216,14 +216,14 @@ inline u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
   u64 *current = (u64 *)afl->fsrv.trace_bits;
   u64 *virgin = (u64 *)virgin_map;
 
-  u32 i = (afl->fsrv.map_size >> 3);
+  u32 i = ((afl->fsrv.real_map_size + 7) >> 3);
 
 #else
 
   u32 *current = (u32 *)afl->fsrv.trace_bits;
   u32 *virgin = (u32 *)virgin_map;
 
-  u32 i = (afl->fsrv.map_size >> 2);
+  u32 i = ((afl->fsrv.real_map_size + 3) >> 2);
 
 #endif                                                     /* ^WORD_SIZE_64 */
 
@@ -317,8 +317,9 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
 
     }
 
-    sprintf(ret + strlen(ret), ",time:%llu",
-            get_cur_time() + afl->prev_run_time - afl->start_time);
+    sprintf(ret + strlen(ret), ",time:%llu,execs:%llu",
+            get_cur_time() + afl->prev_run_time - afl->start_time,
+            afl->fsrv.total_execs);
 
     if (afl->current_custom_fuzz &&
         afl->current_custom_fuzz->afl_custom_describe) {
@@ -451,14 +452,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   if (unlikely(len == 0)) { return 0; }
 
+  u8  fn[PATH_MAX];
   u8 *queue_fn = "";
-  u8  new_bits = '\0';
+  u8  new_bits = 0, keeping = 0, res, classified = 0;
   s32 fd;
-  u8  keeping = 0, res, classified = 0;
   u64 cksum = 0;
 
-  u8 fn[PATH_MAX];
-
   /* Update path frequency. */
 
   /* Generating a hash on every input is super expensive. Bad idea and should
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index c2e9c80f..6fc926f0 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -17,7 +17,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    Shared code to handle the shared memory. This is used by the fuzzer
    as well the other components like afl-tmin, afl-showmap, etc...
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 584241d4..0f0fe331 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 9bb25785..4c030c0a 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -974,8 +974,7 @@ void perform_dry_run(afl_state_t *afl) {
                MSG_ULIMIT_USAGE
                " /path/to/binary [...] <testcase )\n\n"
 
-               "      Tip: you can use http://jwilk.net/software/recidivm to "
-               "quickly\n"
+               "      Tip: you can use https://jwilk.net/software/recidivm to\n"
                "      estimate the required amount of virtual memory for the "
                "binary. Also,\n"
                "      if you are using ASAN, set '-m 0'.\n\n"
@@ -1325,8 +1324,8 @@ void pivot_inputs(afl_state_t *afl) {
 
       }
 
-      nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", afl->out_dir, id,
-                         use_name);
+      nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
+                         afl->out_dir, id, afl->fsrv.total_execs, use_name);
 
 #else
 
@@ -2645,6 +2644,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
       (afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
+      (afl->fsrv.cs_mode && getenv("AFL_CS_CUSTOM_BIN")) ||
       afl->non_instrumented_mode) {
 
     return;
@@ -2721,7 +2721,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 #endif                                                       /* ^!__APPLE__ */
 
   if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode &&
-      !afl->non_instrumented_mode &&
+      !afl->fsrv.cs_mode && !afl->non_instrumented_mode &&
       !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
 
     SAYF("\n" cLRD "[-] " cRST
@@ -2752,7 +2752,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if ((afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
+  if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
       memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
 
     SAYF("\n" cLRD "[-] " cRST
@@ -2815,43 +2815,6 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
 }
 
-/* Trim and possibly create a banner for the run. */
-
-void fix_up_banner(afl_state_t *afl, u8 *name) {
-
-  if (!afl->use_banner) {
-
-    if (afl->sync_id) {
-
-      afl->use_banner = afl->sync_id;
-
-    } else {
-
-      u8 *trim = strrchr(name, '/');
-      if (!trim) {
-
-        afl->use_banner = name;
-
-      } else {
-
-        afl->use_banner = trim + 1;
-
-      }
-
-    }
-
-  }
-
-  if (strlen(afl->use_banner) > 32) {
-
-    u8 *tmp = ck_alloc(36);
-    sprintf(tmp, "%.32s...", afl->use_banner);
-    afl->use_banner = tmp;
-
-  }
-
-}
-
 /* Check if we're on TTY. */
 
 void check_if_tty(afl_state_t *afl) {
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 5332b9fe..e0dfd6b0 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -16,7 +16,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -255,6 +255,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
   mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
   if (!mutator->afl_custom_init_trim) {
 
+    notrim = 1;
     ACTF("optional symbol 'afl_custom_init_trim' not found.");
 
   }
@@ -263,6 +264,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
   mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
   if (!mutator->afl_custom_trim) {
 
+    notrim = 1;
     ACTF("optional symbol 'afl_custom_trim' not found.");
 
   }
@@ -271,6 +273,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
   mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
   if (!mutator->afl_custom_post_trim) {
 
+    notrim = 1;
     ACTF("optional symbol 'afl_custom_post_trim' not found.");
 
   }
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 17749601..f4d3b77f 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -448,11 +448,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     ACTF(
         "Fuzzing test case #%u (%u total, %llu uniq crashes found, "
-        "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...",
+        "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
         afl->current_entry, afl->queued_paths, afl->unique_crashes,
         afl->queue_cur->perf_score, afl->queue_cur->exec_us,
         likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
-        afl->queue_cur->bitmap_size);
+        afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii);
     fflush(stdout);
 
   }
@@ -2003,11 +2003,16 @@ havoc_stage:
      where we take the input file and make random stacked tweaks. */
 
 #define MAX_HAVOC_ENTRY 59                                      /* 55 to 60 */
+#define MUTATE_ASCII_DICT 64
 
   u32 r_max, r;
 
   r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
-          (afl->a_extras_cnt ? 4 : 0);
+          (afl->a_extras_cnt
+               ? (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)
+                      ? MUTATE_ASCII_DICT
+                      : 4)
+               : 0);
 
   if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
 
@@ -2592,7 +2597,15 @@ havoc_stage:
 
           if (afl->a_extras_cnt) {
 
-            if (r < 2) {
+            u32 r_cmp = 2;
+
+            if (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)) {
+
+              r_cmp = MUTATE_ASCII_DICT >> 1;
+
+            }
+
+            if (r < r_cmp) {
 
               /* Use the dictionary. */
 
@@ -2612,7 +2625,7 @@ havoc_stage:
 
               break;
 
-            } else if (r < 4) {
+            } else if (r < (r_cmp << 1)) {
 
               u32 use_extra = rand_below(afl, afl->a_extras_cnt);
               u32 extra_len = afl->a_extras[use_extra].len;
@@ -2641,7 +2654,7 @@ havoc_stage:
 
             } else {
 
-              r -= 4;
+              r -= (r_cmp << 1);
 
             }
 
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 065977c0..6484768b 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 16af2c6b..1523d556 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -14,7 +14,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -315,7 +315,96 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
 
 }
 
-/* check if ascii or UTF-8 */
+/* check if pointer is ascii or UTF-8 */
+
+u8 check_if_text_buf(u8 *buf, u32 len) {
+
+  u32 offset = 0, ascii = 0, utf8 = 0;
+
+  while (offset < len) {
+
+    // ASCII: <= 0x7F to allow ASCII control characters
+    if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A ||
+         buf[offset + 0] == 0x0D ||
+         (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) {
+
+      offset++;
+      utf8++;
+      ascii++;
+      continue;
+
+    }
+
+    if (isascii((int)buf[offset]) || isprint((int)buf[offset])) {
+
+      ascii++;
+      // we continue though as it can also be a valid utf8
+
+    }
+
+    // non-overlong 2-byte
+    if (len - offset > 1 &&
+        ((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) &&
+         (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) {
+
+      offset += 2;
+      utf8++;
+      continue;
+
+    }
+
+    // excluding overlongs
+    if ((len - offset > 2) &&
+        ((buf[offset + 0] == 0xE0 &&
+          (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+          (0x80 <= buf[offset + 2] &&
+           buf[offset + 2] <= 0xBF)) ||  // straight 3-byte
+         (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) ||
+           buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) &&
+          (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+          (0x80 <= buf[offset + 2] &&
+           buf[offset + 2] <= 0xBF)) ||  // excluding surrogates
+         (buf[offset + 0] == 0xED &&
+          (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) &&
+          (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF)))) {
+
+      offset += 3;
+      utf8++;
+      continue;
+
+    }
+
+    // planes 1-3
+    if ((len - offset > 3) &&
+        ((buf[offset + 0] == 0xF0 &&
+          (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+          (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+          (0x80 <= buf[offset + 3] &&
+           buf[offset + 3] <= 0xBF)) ||  // planes 4-15
+         ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) &&
+          (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+          (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+          (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) ||  // plane 16
+         (buf[offset + 0] == 0xF4 &&
+          (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) &&
+          (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+          (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)))) {
+
+      offset += 4;
+      utf8++;
+      continue;
+
+    }
+
+    offset++;
+
+  }
+
+  return (utf8 > ascii ? utf8 : ascii);
+
+}
+
+/* check if queue entry is ascii or UTF-8 */
 
 static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) {
 
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 268f726c..0a6e5eee 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -17,7 +17,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    Shared code to handle the shared memory. This is used by the fuzzer
    as well the other components like afl-tmin, afl-showmap, etc...
@@ -45,6 +45,23 @@ enum {
 
 };
 
+// add to dictionary enum
+// DEFAULT = 1, notTXT = 2, FOUND = 4, notSAME = 8
+enum {
+
+  DICT_ADD_NEVER = 0,
+  DICT_ADD_NOTFOUND_SAME_TXT = 1,
+  DICT_ADD_NOTFOUND_SAME = 3,
+  DICT_ADD_FOUND_SAME_TXT = 5,
+  DICT_ADD_FOUND_SAME = 7,
+  DICT_ADD_NOTFOUND_TXT = 9,
+  DICT_ADD_NOTFOUND = 11,
+  DICT_ADD_FOUND_TXT = 13,
+  DICT_ADD_FOUND = 15,
+  DICT_ADD_ANY = DICT_ADD_FOUND
+
+};
+
 // CMPLOG LVL
 enum {
 
@@ -54,6 +71,8 @@ enum {
 
 };
 
+#define DICT_ADD_STRATEGY DICT_ADD_FOUND_SAME
+
 struct range {
 
   u32           start;
@@ -64,6 +83,10 @@ struct range {
 
 };
 
+static u32 hshape;
+static u64 screen_update;
+static u64 last_update;
+
 static struct range *add_range(struct range *ranges, u32 start, u32 end) {
 
   struct range *r = ck_alloc_nozero(sizeof(struct range));
@@ -252,7 +275,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
   u64 start_time = get_cur_time();
 #endif
 
-  u32 screen_update;
   u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
@@ -261,24 +283,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
   afl->stage_max = (len << 1);
   afl->stage_cur = 0;
 
-  if (likely(afl->queue_cur->exec_us)) {
-
-    if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
-
-      screen_update = 100000 / afl->queue_cur->exec_us;
-
-    } else {
-
-      screen_update = 1;
-
-    }
-
-  } else {
-
-    screen_update = 100000;
-
-  }
-
   // in colorization we do not classify counts, hence we have to calculate
   // the original checksum.
   if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
@@ -348,7 +352,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
 
     }
 
-    if (++afl->stage_cur % screen_update) { show_stats(afl); };
+    if (++afl->stage_cur % screen_update == 0) { show_stats(afl); };
 
   }
 
@@ -440,10 +444,10 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
     fprintf(
         f,
         "Colorization: fname=%s len=%u ms=%llu result=%u execs=%u found=%llu "
-        "taint=%u\n",
+        "taint=%u ascii=%u auto_extra_before=%u\n",
         afl->queue_cur->fname, len, get_cur_time() - start_time,
         afl->queue_cur->colorized, afl->stage_cur, new_hit_cnt - orig_hit_cnt,
-        positions);
+        positions, afl->queue_cur->is_ascii ? 1 : 0, afl->a_extras_cnt);
 
   #ifndef _DEBUG
     if (afl->not_on_tty) { fclose(f); }
@@ -759,11 +763,18 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   u32 its_len = MIN(len - idx, taint_len);
 
+  if (afl->fsrv.total_execs - last_update > screen_update) {
+
+    show_stats(afl);
+    last_update = afl->fsrv.total_execs;
+
+  }
+
   // fprintf(stderr,
   //         "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
   //         "taint_len=%u shape=%u attr=%u\n",
   //         o_pattern, pattern, repl, changed_val, idx, taint_len,
-  //         h->shape + 1, attr);
+  //         hshape, attr);
 
   //#ifdef CMPLOG_SOLVE_TRANSFORM
   // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
@@ -845,7 +856,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
       u64 b_val, o_b_val, mask;
       u8  bytes;
 
-      switch (SHAPE_BYTES(h->shape)) {
+      switch (hshape) {
 
         case 0:
         case 1:
@@ -924,7 +935,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
       s64 diff = pattern - b_val;
       s64 o_diff = o_pattern - o_b_val;
       /* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
-                 h->shape + 1, o_pattern, o_b_val, o_diff);
+                 hshape, o_pattern, o_b_val, o_diff);
          fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
                  b_val, diff); */
       if (diff == o_diff && diff) {
@@ -953,7 +964,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
         s64 o_diff = o_pattern ^ o_b_val;
 
         /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
-                   idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+                   idx, hshape, o_pattern, o_b_val, o_diff);
            fprintf(stderr,
                    "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
         */
@@ -1002,7 +1013,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
         }
 
         /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
-                   idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+                   idx, hshape, o_pattern, o_b_val, o_diff);
            fprintf(stderr,
                    "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
         */
@@ -1051,7 +1062,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
         }
 
         /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
-                   idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+                   idx, hshape, o_pattern, o_b_val, o_diff);
            fprintf(stderr,
                    "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
         */
@@ -1089,7 +1100,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   if ((lvl & LVL1) || attr >= IS_FP_MOD) {
 
-    if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) {
+    if (hshape >= 8 && *status != 1) {
 
       // if (its_len >= 8)
       //   fprintf(stderr,
@@ -1132,7 +1143,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
     }
 
-    if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) {
+    if (hshape >= 4 && *status != 1) {
 
       // if (its_len >= 4 && (attr <= 1 || attr >= 8))
       //   fprintf(stderr,
@@ -1173,7 +1184,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
     }
 
-    if (SHAPE_BYTES(h->shape) >= 2 && *status != 1) {
+    if (hshape >= 2 && *status != 1) {
 
       if (its_len >= 2 &&
           ((*buf_16 == (u16)pattern && *o_buf_16 == (u16)o_pattern) ||
@@ -1244,11 +1255,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   }
 
-  if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) {
-
-    return 0;
-
-  }
+  if (!(attr & (IS_GREATER | IS_LESSER)) || hshape < 4) { return 0; }
 
   // transform >= to < and <= to >
   if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) {
@@ -1272,7 +1279,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
     if (attr & IS_GREATER) {
 
-      if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) {
+      if (hshape == 4 && its_len >= 4) {
 
         float *f = (float *)&repl;
         float  g = *f;
@@ -1280,7 +1287,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
         u32 *r = (u32 *)&g;
         repl_new = (u32)*r;
 
-      } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) {
+      } else if (hshape == 8 && its_len >= 8) {
 
         double *f = (double *)&repl;
         double  g = *f;
@@ -1307,7 +1314,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
     } else {
 
-      if (SHAPE_BYTES(h->shape) == 4) {
+      if (hshape == 4) {
 
         float *f = (float *)&repl;
         float  g = *f;
@@ -1315,7 +1322,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
         u32 *r = (u32 *)&g;
         repl_new = (u32)*r;
 
-      } else if (SHAPE_BYTES(h->shape) == 8) {
+      } else if (hshape == 8) {
 
         double *f = (double *)&repl;
         double  g = *f;
@@ -1342,7 +1349,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
     }
 
     // transform double to float, llvm likes to do that internally ...
-    if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) {
+    if (hshape == 8 && its_len >= 4) {
 
       double *f = (double *)&repl;
       float   g = (float)*f;
@@ -1353,7 +1360,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
       memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
 #endif
       changed_val = repl_new;
-      h->shape = 3;  // modify shape
+      hshape = 4;  // modify shape
 
       // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
 
@@ -1361,12 +1368,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
               afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
               taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
 
-        h->shape = 7;  // recover shape
+        hshape = 8;  // recover shape
         return 1;
 
       }
 
-      h->shape = 7;  // recover shape
+      hshape = 8;  // recover shape
 
     }
 
@@ -1421,6 +1428,13 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
                                u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
                                u32 len, u8 do_reverse, u8 lvl, u8 *status) {
 
+  if (afl->fsrv.total_execs - last_update > screen_update) {
+
+    show_stats(afl);
+    last_update = afl->fsrv.total_execs;
+
+  }
+
   u8 *ptr = (u8 *)&buf[idx];
   u8 *o_ptr = (u8 *)&orig_buf[idx];
   u8 *p = (u8 *)&pattern;
@@ -1428,52 +1442,51 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
   u8 *r = (u8 *)&repl;
   u8  backup[16];
   u32 its_len = MIN(len - idx, taint_len);
-  u32 shape = h->shape + 1;
   #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
   size_t off = 0;
   #else
-  size_t off = 16 - shape;
+  size_t off = 16 - hshape;
   #endif
 
-  if (its_len >= shape) {
+  if (its_len >= hshape) {
 
   #ifdef _DEBUG
     fprintf(stderr, "TestUN: %u>=%u (len=%u idx=%u attr=%u off=%lu) (%u) ",
-            its_len, shape, len, idx, attr, off, do_reverse);
+            its_len, hshape, len, idx, attr, off, do_reverse);
     u32 i;
     u8 *o_r = (u8 *)&changed_val;
-    for (i = 0; i < shape; i++)
+    for (i = 0; i < hshape; i++)
       fprintf(stderr, "%02x", ptr[i]);
     fprintf(stderr, "==");
-    for (i = 0; i < shape; i++)
+    for (i = 0; i < hshape; i++)
       fprintf(stderr, "%02x", p[off + i]);
     fprintf(stderr, " ");
-    for (i = 0; i < shape; i++)
+    for (i = 0; i < hshape; i++)
       fprintf(stderr, "%02x", o_ptr[i]);
     fprintf(stderr, "==");
-    for (i = 0; i < shape; i++)
+    for (i = 0; i < hshape; i++)
       fprintf(stderr, "%02x", o_p[off + i]);
     fprintf(stderr, " <= ");
-    for (i = 0; i < shape; i++)
+    for (i = 0; i < hshape; i++)
       fprintf(stderr, "%02x", r[off + i]);
     fprintf(stderr, "<-");
-    for (i = 0; i < shape; i++)
+    for (i = 0; i < hshape; i++)
       fprintf(stderr, "%02x", o_r[off + i]);
     fprintf(stderr, "\n");
   #endif
 
-    if (!memcmp(ptr, p + off, shape) && !memcmp(o_ptr, o_p + off, shape)) {
+    if (!memcmp(ptr, p + off, hshape) && !memcmp(o_ptr, o_p + off, hshape)) {
 
-      memcpy(backup, ptr, shape);
-      memcpy(ptr, r + off, shape);
+      memcpy(backup, ptr, hshape);
+      memcpy(ptr, r + off, hshape);
 
       if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
 
   #ifdef CMPLOG_COMBINE
-      if (*status == 1) { memcpy(cbuf + idx, r, shape); }
+      if (*status == 1) { memcpy(cbuf + idx, r, hshape); }
   #endif
 
-      memcpy(ptr, backup, shape);
+      memcpy(ptr, backup, hshape);
 
   #ifdef _DEBUG
       fprintf(stderr, "Status=%u\n", *status);
@@ -1485,10 +1498,10 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
     if (do_reverse && *status != 1) {
 
       if (unlikely(cmp_extend_encodingN(
-              afl, h, SWAPN(pattern, (shape << 3)), SWAPN(repl, (shape << 3)),
-              SWAPN(o_pattern, (shape << 3)), SWAPN(changed_val, (shape << 3)),
-              attr, idx, taint_len, orig_buf, buf, cbuf, len, 0, lvl,
-              status))) {
+              afl, h, SWAPN(pattern, (hshape << 3)), SWAPN(repl, (hshape << 3)),
+              SWAPN(o_pattern, (hshape << 3)),
+              SWAPN(changed_val, (hshape << 3)), attr, idx, taint_len, orig_buf,
+              buf, cbuf, len, 0, lvl, status))) {
 
         return 1;
 
@@ -1615,6 +1628,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
   u8  s_v0_inc = 1, s_v1_inc = 1;
   u8  s_v0_dec = 1, s_v1_dec = 1;
 
+  hshape = SHAPE_BYTES(h->shape);
+
   if (h->hits > CMP_MAP_H) {
 
     loggeds = CMP_MAP_H;
@@ -1626,7 +1641,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
   }
 
 #ifdef WORD_SIZE_64
-  switch (SHAPE_BYTES(h->shape)) {
+  switch (hshape) {
 
     case 1:
     case 2:
@@ -1669,7 +1684,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
     for (j = 0; j < i; ++j) {
 
       if (afl->shm.cmp_map->log[key][j].v0 == o->v0 &&
-          afl->shm.cmp_map->log[key][i].v1 == o->v1) {
+          afl->shm.cmp_map->log[key][j].v1 == o->v1) {
 
         goto cmp_fuzz_next_iter;
 
@@ -1679,8 +1694,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
 #ifdef _DEBUG
     fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
-            orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute,
-            SHAPE_BYTES(h->shape));
+            orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
 #endif
 
     t = taint;
@@ -1830,27 +1844,41 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
             "END: %llx->%llx vs %llx->%llx attr=%u i=%u found=%u "
             "isN=%u size=%u\n",
             orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, i, found_one,
-            is_n, SHAPE_BYTES(h->shape));
+            is_n, hshape);
 #endif
 
-    // If failed, add to dictionary
-    if (!found_one) {
+    // we only learn 16 bit +
+    if (hshape > 1) {
 
-      if (afl->pass_stats[key].total == 0) {
+      if (!found_one || afl->queue_cur->is_ascii) {
 
 #ifdef WORD_SIZE_64
         if (unlikely(is_n)) {
 
-          try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
-          try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
+          if (!found_one ||
+              check_if_text_buf((u8 *)&s128_v0, SHAPE_BYTES(h->shape)) ==
+                  SHAPE_BYTES(h->shape))
+            try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
+          if (!found_one ||
+              check_if_text_buf((u8 *)&s128_v1, SHAPE_BYTES(h->shape)) ==
+                  SHAPE_BYTES(h->shape))
+            try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
 
         } else
 
 #endif
         {
 
-          try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
-          try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
+          if (!memcmp((u8 *)&o->v0, (u8 *)&orig_o->v0, SHAPE_BYTES(h->shape)) &&
+              (!found_one ||
+               check_if_text_buf((u8 *)&o->v0, SHAPE_BYTES(h->shape)) ==
+                   SHAPE_BYTES(h->shape)))
+            try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
+          if (!memcmp((u8 *)&o->v1, (u8 *)&orig_o->v1, SHAPE_BYTES(h->shape)) &&
+              (!found_one ||
+               check_if_text_buf((u8 *)&o->v1, SHAPE_BYTES(h->shape)) ==
+                   SHAPE_BYTES(h->shape)))
+            try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
 
         }
 
@@ -1882,8 +1910,9 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
 }
 
-static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
-                              u8 *o_pattern, u8 *changed_val, u8 plen, u32 idx,
+static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
+                              struct cmpfn_operands *o,
+                              struct cmpfn_operands *orig_o, u32 idx,
                               u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
                               u32 len, u8 lvl, u8 *status) {
 
@@ -1894,9 +1923,60 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
   //  (void)(changed_val);
   //#endif
 
+  if (afl->fsrv.total_execs - last_update > screen_update) {
+
+    show_stats(afl);
+    last_update = afl->fsrv.total_execs;
+
+  }
+
+  u8 *pattern, *repl, *o_pattern, *changed_val;
+  u8  l0, l1, ol0, ol1;
+
+  if (entry == 0) {
+
+    pattern = o->v0;
+    repl = o->v1;
+    o_pattern = orig_o->v0;
+    changed_val = orig_o->v1;
+    l0 = o->v0_len;
+    ol0 = orig_o->v0_len;
+    l1 = o->v1_len;
+    ol1 = orig_o->v1_len;
+
+  } else {
+
+    pattern = o->v1;
+    repl = o->v0;
+    o_pattern = orig_o->v1;
+    changed_val = orig_o->v0;
+    l0 = o->v1_len;
+    ol0 = orig_o->v1_len;
+    l1 = o->v0_len;
+    ol1 = orig_o->v0_len;
+
+  }
+
+  if (l0 >= 0x80 || ol0 >= 0x80) {
+
+    l0 -= 0x80;
+    l1 -= 0x80;
+    ol0 -= 0x80;
+    ol1 -= 0x80;
+
+  }
+
+  if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
+      ol0 > 31 || ol1 > 31) {
+
+    l0 = l1 = ol0 = ol1 = hshape;
+
+  }
+
+  u8  lmax = MAX(l0, ol0);
   u8  save[40];
   u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
-  u32 its_len = MIN((u32)plen, len - idx);
+  u32 its_len = MIN(MIN(lmax, hshape), len - idx);
   its_len = MIN(its_len, taint_len);
   u32 saved_its_len = its_len;
 
@@ -1912,7 +1992,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
   (void)(j);
 
 #ifdef _DEBUG
-  fprintf(stderr, "RTN T idx=%u lvl=%02x ", idx, lvl);
+  fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl,
+          o->v0_len >= 0x80 ? 1 : 0, hshape, l0);
   for (j = 0; j < 8; j++)
     fprintf(stderr, "%02x", orig_buf[idx + j]);
   fprintf(stderr, " -> ");
@@ -1972,10 +2053,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
 
   }
 
-  //#ifdef CMPLOG_SOLVE_TRANSFORM
-
   if (*status == 1) return 0;
 
+  // transform solving
+
   if (afl->cmplog_enable_transform && (lvl & LVL3)) {
 
     u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
@@ -2322,6 +2403,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
   u32                i, j, idx, have_taint = 1, taint_len, loggeds;
   u8                 status = 0, found_one = 0;
 
+  hshape = SHAPE_BYTES(h->shape);
+
   if (h->hits > CMP_MAP_RTN_H) {
 
     loggeds = CMP_MAP_RTN_H;
@@ -2353,18 +2436,22 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
     }
 
     /*
-      struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
-      fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits,
-              h->id, h->shape, h->attribute);
-      for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]);
-      fprintf(stderr, " v1=");
-      for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]);
-      fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=",
-              hh->hits, hh->id, hh->shape, hh->attribute);
-      for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]);
-      fprintf(stderr, " o1=");
-      for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]);
-      fprintf(stderr, "\n");
+    struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
+    fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
+            hshape, h->attribute);
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", o->v0[j]);
+    fprintf(stderr, " v1=");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", o->v1[j]);
+    fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
+            hh->id, hshape, hh->attribute);
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", orig_o->v0[j]);
+    fprintf(stderr, " o1=");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", orig_o->v1[j]);
+    fprintf(stderr, "\n");
     */
 
     t = taint;
@@ -2400,25 +2487,24 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
 #ifdef _DEBUG
       int w;
-      fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx,
-              SHAPE_BYTES(h->shape));
-      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+      fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, hshape);
+      for (w = 0; w < hshape; ++w)
         fprintf(stderr, "%02x", orig_o->v0[w]);
       fprintf(stderr, " v0=");
-      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+      for (w = 0; w < hshape; ++w)
         fprintf(stderr, "%02x", o->v0[w]);
       fprintf(stderr, " o1=");
-      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+      for (w = 0; w < hshape; ++w)
         fprintf(stderr, "%02x", orig_o->v1[w]);
       fprintf(stderr, " v1=");
-      for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
+      for (w = 0; w < hshape; ++w)
         fprintf(stderr, "%02x", o->v1[w]);
       fprintf(stderr, "\n");
 #endif
 
-      if (unlikely(rtn_extend_encoding(
-              afl, o->v0, o->v1, orig_o->v0, orig_o->v1, SHAPE_BYTES(h->shape),
-              idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
+      if (unlikely(rtn_extend_encoding(afl, 0, o, orig_o, idx, taint_len,
+                                       orig_buf, buf, cbuf, len, lvl,
+                                       &status))) {
 
         return 1;
 
@@ -2433,9 +2519,9 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
       status = 0;
 
-      if (unlikely(rtn_extend_encoding(
-              afl, o->v1, o->v0, orig_o->v1, orig_o->v0, SHAPE_BYTES(h->shape),
-              idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
+      if (unlikely(rtn_extend_encoding(afl, 1, o, orig_o, idx, taint_len,
+                                       orig_buf, buf, cbuf, len, lvl,
+                                       &status))) {
 
         return 1;
 
@@ -2450,16 +2536,42 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
     }
 
-    // If failed, add to dictionary
-    if (!found_one && (lvl & LVL1)) {
+    //  if (unlikely(!afl->pass_stats[key].total)) {
+
+    if ((!found_one && (lvl & LVL1)) || afl->queue_cur->is_ascii) {
+
+      // if (unlikely(!afl->pass_stats[key].total)) {
+
+      u32 shape_len = SHAPE_BYTES(h->shape);
+      u32 v0_len = shape_len, v1_len = shape_len;
+      if (afl->queue_cur->is_ascii ||
+          check_if_text_buf((u8 *)&o->v0, shape_len) == shape_len) {
+
+        if (strlen(o->v0)) v0_len = strlen(o->v0);
+
+      }
 
-      if (unlikely(!afl->pass_stats[key].total)) {
+      if (afl->queue_cur->is_ascii ||
+          check_if_text_buf((u8 *)&o->v1, shape_len) == shape_len) {
 
-        maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape));
-        maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape));
+        if (strlen(o->v1)) v1_len = strlen(o->v1);
 
       }
 
+      // fprintf(stderr, "SHOULD: found:%u ascii:%u text?%u:%u %u:%s %u:%s \n",
+      // found_one, afl->queue_cur->is_ascii, check_if_text_buf((u8 *)&o->v0,
+      // shape_len), check_if_text_buf((u8 *)&o->v1, shape_len), v0_len,
+      // o->v0, v1_len, o->v1);
+
+      if (!memcmp(o->v0, orig_o->v0, v0_len) ||
+          (!found_one || check_if_text_buf((u8 *)&o->v0, v0_len) == v0_len))
+        maybe_add_auto(afl, o->v0, v0_len);
+      if (!memcmp(o->v1, orig_o->v1, v1_len) ||
+          (!found_one || check_if_text_buf((u8 *)&o->v1, v1_len) == v1_len))
+        maybe_add_auto(afl, o->v1, v1_len);
+
+      //}
+
     }
 
   rtn_fuzz_next_iter:
@@ -2492,6 +2604,23 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
   }
 
   struct tainted *taint = NULL;
+  if (likely(afl->queue_cur->exec_us)) {
+
+    if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
+
+      screen_update = 100000 / afl->queue_cur->exec_us;
+
+    } else {
+
+      screen_update = 1;
+
+    }
+
+  } else {
+
+    screen_update = 100000;
+
+  }
 
   if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
 
@@ -2592,8 +2721,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
   u64 orig_hit_cnt, new_hit_cnt;
   u64 orig_execs = afl->fsrv.total_execs;
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
-  u64 screen_update = 100000 / afl->queue_cur->exec_us,
-      execs = afl->fsrv.total_execs;
 
   afl->stage_name = "input-to-state";
   afl->stage_short = "its";
@@ -2630,11 +2757,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
 
     if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
 
+      // fprintf(stderr, "INS %u\n", k);
       afl->stage_max +=
           MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H);
 
     } else {
 
+      // fprintf(stderr, "RTN %u\n", k);
       afl->stage_max +=
           MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H);
 
@@ -2673,13 +2802,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
 
     }
 
-    if (afl->fsrv.total_execs - execs > screen_update) {
-
-      execs = afl->fsrv.total_execs;
-      show_stats(afl);
-
-    }
-
   }
 
   r = 0;
@@ -2795,9 +2917,10 @@ exit_its:
   if (f) {
 
     fprintf(f,
-            "Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u\n",
+            "Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u "
+            "auto_extra_after=%u\n",
             afl->queue_cur->fname, len, get_cur_time() - start_time, r,
-            new_hit_cnt - orig_hit_cnt, cmp_locations);
+            new_hit_cnt - orig_hit_cnt, cmp_locations, afl->a_extras_cnt);
 
   #ifndef _DEBUG
     if (afl->not_on_tty) { fclose(f); }
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 4173f4e1..2789b56f 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -16,7 +16,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -291,8 +291,6 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
 u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
                   u32 handicap, u8 from_queue) {
 
-  if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
-
   u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0,
      first_run = (q->exec_cksum == 0);
   u64 start_us, stop_us, diff_us;
@@ -300,6 +298,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
   u32 use_tmout = afl->fsrv.exec_tmout;
   u8 *old_sn = afl->stage_name;
 
+  if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
+
   /* Be a bit more generous about timeouts when resuming sessions, or when
      trying to calibrate already-added finds. This helps avoid trouble due
      to intermittent latency. */
@@ -343,6 +343,32 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
 
   }
 
+  /* we need a dummy run if this is LTO + cmplog */
+  if (unlikely(afl->shm.cmplog_mode)) {
+
+    write_to_testcase(afl, use_mem, q->len);
+
+    fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
+
+    /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
+       we want to bail out quickly. */
+
+    if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
+
+    if (!afl->non_instrumented_mode && !afl->stage_cur &&
+        !count_bytes(afl, afl->fsrv.trace_bits)) {
+
+      fault = FSRV_RUN_NOINST;
+      goto abort_calibration;
+
+    }
+
+#ifdef INTROSPECTION
+    if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
+#endif
+
+  }
+
   if (q->exec_cksum) {
 
     memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 24ccc108..737a49a7 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index eb1fe2d9..152bebe9 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -278,13 +278,14 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
           "total_edges       : %u\n"
           "var_byte_count    : %u\n"
           "havoc_expansion   : %u\n"
+          "auto_dict_entries : %u\n"
           "testcache_size    : %llu\n"
           "testcache_count   : %u\n"
           "testcache_evict   : %u\n"
           "afl_banner        : %s\n"
           "afl_version       : " VERSION
           "\n"
-          "target_mode       : %s%s%s%s%s%s%s%s%s\n"
+          "target_mode       : %s%s%s%s%s%s%s%s%s%s\n"
           "command_line      : %s\n",
           (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
           (afl->prev_run_time + cur_time - afl->start_time) / 1000,
@@ -316,16 +317,17 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
           -1,
 #endif
           t_bytes, afl->fsrv.real_map_size, afl->var_byte_count,
-          afl->expand_havoc, afl->q_testcase_cache_size,
+          afl->expand_havoc, afl->a_extras_cnt, afl->q_testcase_cache_size,
           afl->q_testcase_cache_count, afl->q_testcase_evictions,
           afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
           afl->fsrv.qemu_mode ? "qemu " : "",
+          afl->fsrv.cs_mode ? "coresight" : "",
           afl->non_instrumented_mode ? " non_instrumented " : "",
           afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
           afl->persistent_mode ? "persistent " : "",
           afl->shmem_testcase_mode ? "shmem_testcase " : "",
           afl->deferred_mode ? "deferred " : "",
-          (afl->unicorn_mode || afl->fsrv.qemu_mode ||
+          (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->fsrv.cs_mode ||
            afl->non_instrumented_mode || afl->no_forkserver ||
            afl->crash_mode || afl->persistent_mode || afl->deferred_mode)
               ? ""
@@ -441,9 +443,10 @@ void show_stats(afl_state_t *afl) {
   u64 cur_ms;
   u32 t_bytes, t_bits;
 
-  u32 banner_len, banner_pad;
-  u8  tmp[256];
-  u8  time_tmp[64];
+  static u8 banner[128];
+  u32       banner_len, banner_pad;
+  u8        tmp[256];
+  u8        time_tmp[64];
 
   u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
 #define IB(i) (val_buf[(i)])
@@ -540,9 +543,11 @@ void show_stats(afl_state_t *afl) {
 
       FATAL(
           "Incorrect fuzzing setup detected. Your target seems to have loaded "
-          "incorrectly instrumented shared libraries. If you use LTO mode "
+          "incorrectly instrumented shared libraries (%u of %u/%u). If you use "
+          "LTO mode "
           "please see instrumentation/README.lto.md. To ignore this problem "
-          "and continue fuzzing just set 'AFL_IGNORE_PROBLEMS=1'.\n");
+          "and continue fuzzing just set 'AFL_IGNORE_PROBLEMS=1'.\n",
+          t_bytes, afl->fsrv.real_map_size, afl->fsrv.map_size);
 
     }
 
@@ -560,8 +565,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,
@@ -655,26 +661,34 @@ void show_stats(afl_state_t *afl) {
   }
 
   /* Let's start by drawing a centered banner. */
+  if (unlikely(!banner[0])) {
 
-  banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) +
-               strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5;
-  banner_pad = (79 - banner_len) / 2;
-  memset(tmp, ' ', banner_pad);
+    char *si = "";
+    if (afl->sync_id) { si = afl->sync_id; }
+    memset(banner, 0, sizeof(banner));
+    banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
+                 strlen(afl->power_name) + 4 + 6;
 
-#ifdef HAVE_AFFINITY
-  sprintf(
-      tmp + banner_pad,
-      "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}",
-      afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
-      afl->use_banner, afl->power_name, afl->cpu_aff);
-#else
-  sprintf(
-      tmp + banner_pad, "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]",
-      afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
-      afl->use_banner, afl->power_name);
-#endif                                                     /* HAVE_AFFINITY */
+    if (strlen(afl->use_banner) + banner_len > 75) {
+
+      afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76;
+      memset(afl->use_banner, '.', 3);
+
+    }
+
+    banner_len += strlen(afl->use_banner);
+    banner_pad = (79 - banner_len) / 2;
+    memset(banner, ' ', banner_pad);
+
+    sprintf(banner + banner_pad,
+            "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+            afl->crash_mode ? cPIN "peruvian were-rabbit"
+                            : cYEL "american fuzzy lop",
+            si, afl->use_banner, afl->power_name);
+
+  }
 
-  SAYF("\n%s\n", tmp);
+  SAYF("\n%s\n", banner);
 
   /* "Handy" shortcuts for drawing boxes... */
 
@@ -1227,7 +1241,9 @@ void show_init_stats(afl_state_t *afl) {
 
   // SAYF("\n");
 
-  if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) {
+  if (avg_us > ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->unicorn_mode)
+                    ? 50000
+                    : 10000)) {
 
     WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
           doc_path);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8ffc0e77..195366bd 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This is the real deal: the program takes an instrumented binary and
    attempts a variety of basic fuzzing tricks, paying close attention to
@@ -113,11 +113,17 @@ static void usage(u8 *argv0, int more_help) {
       "maximum.\n"
       "  -m megs       - memory limit for child process (%u MB, 0 = no limit "
       "[default])\n"
+#if defined(__linux__) && defined(__aarch64__)
+      "  -A            - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
       "  -O            - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
-      "mode)\n\n"
+      "mode)\n"
+#endif
+      "\n"
 
       "Mutator settings:\n"
       "  -D            - enable deterministic fuzzing (once per queue entry)\n"
@@ -434,7 +440,8 @@ int main(int argc, char **argv_orig, char **envp) {
 
   while ((opt = getopt(
               argc, argv,
-              "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
+              "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) >
+         0) {
 
     switch (opt) {
 
@@ -563,6 +570,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
         }
 
+        if (afl->fsrv.cs_mode) {
+
+          FATAL("-M is not supported in ARM CoreSight mode");
+
+        }
+
         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
 
         /* sanity check for argument: should not begin with '-' (possible
@@ -609,6 +622,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
         }
 
+        if (afl->fsrv.cs_mode) {
+
+          FATAL("-S is not supported in ARM CoreSight mode");
+
+        }
+
         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
 
         /* sanity check for argument: should not begin with '-' (possible
@@ -825,6 +844,24 @@ int main(int argc, char **argv_orig, char **envp) {
         afl->use_banner = optarg;
         break;
 
+      case 'A':                                           /* CoreSight mode */
+
+  #if !defined(__aarch64__) || !defined(__linux__)
+        FATAL("-A option is not supported on this platform");
+  #endif
+
+        if (afl->is_main_node || afl->is_secondary_node) {
+
+          FATAL("ARM CoreSight mode is not supported with -M / -S");
+
+        }
+
+        if (afl->fsrv.cs_mode) { FATAL("Multiple -A options not supported"); }
+
+        afl->fsrv.cs_mode = 1;
+
+        break;
+
       case 'O':                                               /* FRIDA mode */
 
         if (afl->fsrv.frida_mode) {
@@ -1189,7 +1226,17 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (afl->sync_id) { fix_up_sync(afl); }
+  if (afl->sync_id) {
+
+    if (strlen(afl->sync_id) > 24) {
+
+      FATAL("sync_id max length is 24 characters");
+
+    }
+
+    fix_up_sync(afl);
+
+  }
 
   if (!strcmp(afl->in_dir, afl->out_dir)) {
 
@@ -1202,6 +1249,7 @@ int main(int argc, char **argv_orig, char **envp) {
     if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
     if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
     if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
+    if (afl->fsrv.cs_mode) { FATAL("-A and -n are mutually exclusive"); }
     if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
 
   }
@@ -1218,6 +1266,8 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
 
+  if (!afl->use_banner) { afl->use_banner = argv[optind]; }
+
   if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
 
     WARNF(cLRD
@@ -1348,7 +1398,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));
 
@@ -1446,6 +1496,8 @@ int main(int argc, char **argv_orig, char **envp) {
 
     } else {
 
+      /* CoreSight mode uses the default behavior. */
+
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
       setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
 
@@ -1486,9 +1538,6 @@ int main(int argc, char **argv_orig, char **envp) {
   }
 
   save_cmdline(afl, argc, argv);
-
-  fix_up_banner(afl, argv[optind]);
-
   check_if_tty(afl);
   if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
 
@@ -1642,7 +1691,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode &&
+    if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
         !afl->non_instrumented_mode) {
 
       check_binary(afl, afl->cmplog_binary);
@@ -1688,6 +1737,11 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+  } else if (afl->fsrv.cs_mode) {
+
+    use_argv = get_cs_argv(argv[0], &afl->fsrv.target_path, argc - optind,
+                           argv + optind);
+
   } else {
 
     use_argv = argv + optind;
@@ -1695,9 +1749,9 @@ int main(int argc, char **argv_orig, char **envp) {
   }
 
   if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
-      afl->fsrv.frida_mode || afl->unicorn_mode) {
+      afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
 
-    map_size = afl->fsrv.map_size = MAP_SIZE;
+    map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
     afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
     afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
     afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
@@ -1715,7 +1769,7 @@ int main(int argc, char **argv_orig, char **envp) {
       afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
 
   if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
-      !afl->unicorn_mode && !afl->fsrv.frida_mode &&
+      !afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
       !afl->afl_env.afl_skip_bin_check) {
 
     if (map_size <= DEFAULT_SHMEM_SIZE) {
@@ -1768,6 +1822,7 @@ int main(int argc, char **argv_orig, char **envp) {
     afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
     // TODO: this is semi-nice
     afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
+    afl->cmplog_fsrv.cs_mode = afl->fsrv.cs_mode;
     afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
     afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
     afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
@@ -1776,7 +1831,7 @@ int main(int argc, char **argv_orig, char **envp) {
     if ((map_size <= DEFAULT_SHMEM_SIZE ||
          afl->cmplog_fsrv.map_size < map_size) &&
         !afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
-        !afl->fsrv.frida_mode && !afl->unicorn_mode &&
+        !afl->fsrv.frida_mode && !afl->unicorn_mode && !afl->fsrv.cs_mode &&
         !afl->afl_env.afl_skip_bin_check) {
 
       afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
@@ -1918,7 +1973,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);
 
@@ -2226,13 +2281,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  write_bitmap(afl);
-  save_auto(afl);
-
 stop_fuzzing:
 
   afl->force_ui_update = 1;  // ensure the screen is reprinted
   show_stats(afl);           // print the screen one last time
+  write_bitmap(afl);
+  save_auto(afl);
 
   SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
        afl->stop_soon == 2 ? "programmatically" : "by user");
@@ -2261,6 +2315,20 @@ stop_fuzzing:
 
   }
 
+  if (afl->not_on_tty) {
+
+    u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
+    u8  time_tmp[64];
+    u_stringify_time_diff(time_tmp, get_cur_time(), afl->start_time);
+    ACTF(
+        "Statistics: %u new paths found, %.02f%% coverage achieved, %llu "
+        "crashes found, %llu timeouts found, total runtime %s",
+        afl->queued_discovered,
+        ((double)t_bytes * 100) / afl->fsrv.real_map_size, afl->unique_crashes,
+        afl->unique_hangs, time_tmp);
+
+  }
+
   #ifdef PROFILING
   SAYF(cYEL "[!] " cRST
             "Profiling information: %llu ms total work, %llu ns/run\n",
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index ac002a93..f8466680 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -15,7 +15,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    This tool provides a fairly accurate measurement of CPU preemption rate.
    It is meant to complement the quick-and-dirty load average widget shown
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 1ce97649..1dcdb176 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -15,7 +15,7 @@
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at:
 
-    http://www.apache.org/licenses/LICENSE-2.0
+    https://www.apache.org/licenses/LICENSE-2.0
 
   The sole purpose of this wrapper is to preprocess clang LTO files when
   linking with lld and performing the instrumentation on the whole program.
diff --git a/src/afl-performance.c b/src/afl-performance.c
index 89b170eb..04507410 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -5,7 +5,7 @@
    and related and neighboring rights to this software to the public domain
    worldwide. This software is distributed without any warranty.
 
-   See <http://creativecommons.org/publicdomain/zero/1.0/>.
+   See <https://creativecommons.org/publicdomain/zero/1.0/>.
 
    This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
    It has excellent (sub-ns) speed, a state (256 bits) that is large
@@ -90,7 +90,8 @@ inline u32 hash32(u8 *key, u32 len, u32 seed) {
 
 #endif
 
-  return (u32)XXH64(key, len, seed);
+  (void)seed;
+  return (u32)XXH3_64bits(key, len);
 
 }
 
@@ -102,7 +103,8 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
 
 #endif
 
-  return XXH64(key, len, seed);
+  (void)seed;
+  return XXH3_64bits(key, len);
 
 }
 
diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c
index 22fe5a62..7fb8f821 100644
--- a/src/afl-sharedmem.c
+++ b/src/afl-sharedmem.c
@@ -17,7 +17,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    Shared code to handle the shared memory. This is used by the fuzzer
    as well the other components like afl-tmin, afl-showmap, etc...
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 9122cd25..8cddcb32 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -18,7 +18,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    A very simple tool that runs the targeted binary and displays
    the contents of the trace bitmap in a human-readable form. Useful in
@@ -77,7 +77,7 @@ static u32 tcnt, highest;              /* tuple content information         */
 
 static u32 in_len;                     /* Input data length                 */
 
-static u32 map_size = MAP_SIZE;
+static u32 map_size = MAP_SIZE, timed_out = 0;
 
 static bool quiet_mode,                /* Hide non-essential messages?      */
     edges_only,                        /* Ignore hit counts?                */
@@ -146,6 +146,18 @@ static const u8 count_class_binary[256] = {
 #undef TIMES8
 #undef TIMES4
 
+static void kill_child() {
+
+  timed_out = 1;
+  if (fsrv->child_pid > 0) {
+
+    kill(fsrv->child_pid, fsrv->kill_signal);
+    fsrv->child_pid = -1;
+
+  }
+
+}
+
 static void classify_counts(afl_forkserver_t *fsrv) {
 
   u8 *      mem = fsrv->trace_bits;
@@ -242,9 +254,14 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
   if (cmin_mode &&
       (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
 
-    // create empty file to prevent error messages in afl-cmin
-    fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
-    close(fd);
+    if (strcmp(outfile, "-")) {
+
+      // create empty file to prevent error messages in afl-cmin
+      fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+      close(fd);
+
+    }
+
     return ret;
 
   }
@@ -357,9 +374,10 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
 
   if (!quiet_mode) {
 
-    if (fsrv->last_run_timed_out) {
+    if (timed_out || fsrv->last_run_timed_out) {
 
       SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
+      timed_out = 0;
 
     } else if (stop_soon) {
 
@@ -413,7 +431,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);
 
     }
@@ -521,6 +539,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
 
   }
 
+  signal(SIGALRM, kill_child);
+
   setitimer(ITIMER_REAL, &it, NULL);
 
   if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
@@ -563,9 +583,10 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
 
   if (!quiet_mode) {
 
-    if (fsrv->last_run_timed_out) {
+    if (timed_out || fsrv->last_run_timed_out) {
 
       SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
+      timed_out = 0;
 
     } else if (stop_soon) {
 
@@ -669,6 +690,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
 
     } else {
 
+      /* CoreSight mode uses the default behavior. */
+
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
       setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
 
@@ -821,12 +844,18 @@ static void usage(u8 *argv0) {
       "Execution control settings:\n"
       "  -t msec    - timeout for each run (none)\n"
       "  -m megs    - memory limit for child process (%u MB)\n"
+#if defined(__linux__) && defined(__aarch64__)
+      "  -A         - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
       "  -O         - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
       "  -Q         - use binary-only instrumentation (QEMU mode)\n"
       "  -U         - use Unicorn-based instrumentation (Unicorn mode)\n"
       "  -W         - use qemu-based instrumentation with Wine (Wine mode)\n"
       "               (Not necessary, here for consistency with other afl-* "
-      "tools)\n\n"
+      "tools)\n"
+#endif
+      "\n"
       "Other settings:\n"
       "  -i dir     - process all files below this directory, must be combined "
       "with -o.\n"
@@ -896,7 +925,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) {
 
     switch (opt) {
 
@@ -1025,7 +1054,7 @@ int main(int argc, char **argv_orig, char **envp) {
         quiet_mode = true;
         break;
 
-      case 'A':
+      case 'H':
         /* Another afl-cmin specific feature. */
         at_file = optarg;
         break;
@@ -1035,10 +1064,23 @@ int main(int argc, char **argv_orig, char **envp) {
         if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
 
         fsrv->frida_mode = true;
-        setenv("AFL_FRIDA_INST_SEED", "0x0", 1);
+        setenv("AFL_FRIDA_INST_SEED", "1", 1);
 
         break;
 
+      /* FIXME: We want to use -P for consistency, but it is already unsed for
+       * undocumenetd feature "Another afl-cmin specific feature." */
+      case 'A':                                           /* CoreSight mode */
+
+#if !defined(__aarch64__) || !defined(__linux__)
+        FATAL("-A option is not supported on this platform");
+#endif
+
+        if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
+
+        fsrv->cs_mode = true;
+        break;
+
       case 'Q':
 
         if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@@ -1183,12 +1225,19 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+  } else if (fsrv->cs_mode) {
+
+    use_argv =
+        get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+
   } else {
 
     use_argv = argv + optind;
 
   }
 
+  if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
+
   shm_fuzz = ck_alloc(sizeof(sharedmem_t));
 
   /* initialize cmplog_mode */
@@ -1207,7 +1256,7 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv->shmem_fuzz_len = (u32 *)map;
   fsrv->shmem_fuzz = map + sizeof(u32);
 
-  if (!fsrv->qemu_mode && !unicorn_mode) {
+  if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
 
     u32 save_be_quiet = be_quiet;
     be_quiet = !debug;
@@ -1386,9 +1435,9 @@ int main(int argc, char **argv_orig, char **envp) {
   if (!quiet_mode || collect_coverage) {
 
     if (!tcnt && !have_coverage) { FATAL("No instrumentation detected" cRST); }
-    OKF("Captured %u tuples (highest value %u, total values %llu) in "
-        "'%s'." cRST,
-        tcnt, highest, total, out_file);
+    OKF("Captured %u tuples (map size %u, highest value %u, total values %llu) "
+        "in '%s'." cRST,
+        tcnt, fsrv->real_map_size, highest, total, out_file);
     if (collect_coverage)
       OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
           "with %llu input files.",
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 792770e0..89546c45 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -18,7 +18,7 @@
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at:
 
-     http://www.apache.org/licenses/LICENSE-2.0
+     https://www.apache.org/licenses/LICENSE-2.0
 
    A simple test case minimizer that takes an input file and tries to remove
    as much data as possible while keeping the binary in a crashing state
@@ -120,6 +120,17 @@ static const u8 count_class_lookup[256] = {
 #undef TIMES8
 #undef TIMES4
 
+static void kill_child() {
+
+  if (fsrv->child_pid > 0) {
+
+    kill(fsrv->child_pid, fsrv->kill_signal);
+    fsrv->child_pid = -1;
+
+  }
+
+}
+
 static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
                                  sharedmem_t *     shm_fuzz) {
 
@@ -221,7 +232,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);
 
   }
 
@@ -797,6 +808,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
 
     } else {
 
+      /* CoreSight mode uses the default behavior. */
+
       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
       setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
 
@@ -853,13 +866,19 @@ static void usage(u8 *argv0) {
       "  -f file       - input file read by the tested program (stdin)\n"
       "  -t msec       - timeout for each run (%u ms)\n"
       "  -m megs       - memory limit for child process (%u MB)\n"
+#if defined(__linux__) && defined(__aarch64__)
+      "  -A            - use binary-only instrumentation (ARM CoreSight mode)\n"
+#endif
       "  -O            - use binary-only instrumentation (FRIDA mode)\n"
+#if defined(__linux__)
       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
       "mode)\n"
       "                  (Not necessary, here for consistency with other afl-* "
-      "tools)\n\n"
+      "tools)\n"
+#endif
+      "\n"
 
       "Minimization settings:\n"
 
@@ -910,7 +929,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeOQUWHh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) {
 
     switch (opt) {
 
@@ -1022,12 +1041,23 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
+      case 'A':                                           /* CoreSight mode */
+
+#if !defined(__aarch64__) || !defined(__linux__)
+        FATAL("-A option is not supported on this platform");
+#endif
+
+        if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
+
+        fsrv->cs_mode = 1;
+        break;
+
       case 'O':                                               /* FRIDA mode */
 
         if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
 
         fsrv->frida_mode = 1;
-        setenv("AFL_FRIDA_INST_SEED", "0x0", 1);
+        setenv("AFL_FRIDA_INST_SEED", "1", 1);
 
         break;
 
@@ -1125,6 +1155,7 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv->target_path = find_binary(argv[optind]);
   fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
   detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
+  signal(SIGALRM, kill_child);
 
   if (fsrv->qemu_mode) {
 
@@ -1140,6 +1171,11 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+  } else if (fsrv->cs_mode) {
+
+    use_argv =
+        get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+
   } else {
 
     use_argv = argv + optind;
@@ -1209,6 +1245,7 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv->shmem_fuzz = map + sizeof(u32);
 
   read_initial_file();
+  (void)check_binary_signatures(fsrv->target_path);
 
   if (!fsrv->qemu_mode && !unicorn_mode) {