about summary refs log tree commit diff
path: root/llvm_mode
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_mode')
-rw-r--r--llvm_mode/GNUmakefile9
-rw-r--r--llvm_mode/LLVMInsTrim.so.cc8
-rw-r--r--llvm_mode/README.instrument_list.md18
-rw-r--r--llvm_mode/afl-clang-fast.c122
-rw-r--r--llvm_mode/afl-ld-lto.c2
-rw-r--r--llvm_mode/afl-llvm-common.cc357
-rw-r--r--llvm_mode/afl-llvm-common.h1
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc174
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc9
-rw-r--r--llvm_mode/afl-llvm-rt.o.c151
-rw-r--r--llvm_mode/cmplog-instructions-pass.cc6
-rw-r--r--llvm_mode/cmplog-routines-pass.cc6
-rw-r--r--llvm_mode/compare-transform-pass.so.cc10
-rw-r--r--llvm_mode/split-compares-pass.so.cc6
-rw-r--r--llvm_mode/split-switches-pass.so.cc6
15 files changed, 503 insertions, 382 deletions
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile
index 0fa9b12e..fb4e8537 100644
--- a/llvm_mode/GNUmakefile
+++ b/llvm_mode/GNUmakefile
@@ -206,6 +206,9 @@ AFL_CLANG_FUSELD=
 ifeq "$(LLVM_LTO)" "1"
   ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
     AFL_CLANG_FUSELD=1
+    ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(LLVM_BINDIR)/ld.lld -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+      AFL_CLANG_LDPATH=1
+    endif
   else
     $(warn -fuse-ld is not working, cannot enable LTO mode)
     LLVM_LTO = 0
@@ -218,7 +221,9 @@ CFLAGS_SAFE     := -Wall -g -Wno-pointer-sign -I ../include/ \
                    -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
                    -DLLVM_LIBDIR=\"$(LLVM_LIBDIR)\" -DLLVM_VERSION=\"$(LLVMVER)\" \
                    -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
-                   -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
+                   -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \
+                   -DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \
+                   -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
                    -DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function
 override CFLAGS += $(CFLAGS_SAFE)
 
@@ -236,7 +241,7 @@ endif
 ifneq "$(LLVM_CONFIG)" ""
   CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
 endif
-CLANG_CPPFL  = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS)
+CLANG_CPPFL  = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS) -Wno-deprecated-declarations
 CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
 
 
diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc
index 4d8c4719..206e2682 100644
--- a/llvm_mode/LLVMInsTrim.so.cc
+++ b/llvm_mode/LLVMInsTrim.so.cc
@@ -94,7 +94,7 @@ struct InsTrim : public ModulePass {
 
   }
 
-#if LLVM_VERSION_MAJOR >= 4 || \
+#if LLVM_VERSION_MAJOR > 4 || \
     (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
   #define AFL_HAVE_VECTOR_INTRINSICS 1
 #endif
@@ -144,7 +144,7 @@ struct InsTrim : public ModulePass {
 #ifdef AFL_HAVE_VECTOR_INTRINSICS
     unsigned int ngram_size = 0;
     /* Decide previous location vector size (must be a power of two) */
-    VectorType *PrevLocTy;
+    VectorType *PrevLocTy = NULL;
 
     if (ngram_size_str)
       if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
@@ -194,7 +194,7 @@ struct InsTrim : public ModulePass {
         new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
                            GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
     GlobalVariable *AFLPrevLoc;
-    GlobalVariable *AFLContext;
+    GlobalVariable *AFLContext = NULL;
     LoadInst *      PrevCtx = NULL;  // for CTX sensitive coverage
 
     if (ctx_str)
@@ -256,6 +256,8 @@ struct InsTrim : public ModulePass {
     u64 total_rs = 0;
     u64 total_hs = 0;
 
+    scanForDangerousFunctions(&M);
+
     for (Function &F : M) {
 
       if (debug) {
diff --git a/llvm_mode/README.instrument_list.md b/llvm_mode/README.instrument_list.md
index d4739dda..1fc06414 100644
--- a/llvm_mode/README.instrument_list.md
+++ b/llvm_mode/README.instrument_list.md
@@ -14,13 +14,13 @@ disturbance by uninteresting code being exercised.
 
 For this purpose, a "partial instrumentation" support en par with llvm sancov
 is provided by afl++ that allows you to specify on a source file and function
-level which should be compiled with or without instrumentation.
+level which function should be compiled with or without instrumentation.
 
 Note: When using PCGUARD mode - and have llvm 12+ - you can use this instead:
 https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
 
-the llvm sancov list format is fully supported by afl++, however afl++ has
-more flexbility.
+The llvm sancov list format is fully supported by afl++, however afl++ has
+more flexibility.
 
 ## 2) Building the LLVM module
 
@@ -35,13 +35,13 @@ The only required change is that you need to set either the environment variable
 AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST set with a filename.
 
 That file then contains the filenames or functions that should be instrumented
-(AFL_LLVM_ALLOWLIST) or should specifically NOT instrumentd (AFL_LLVM_DENYLIST).
+(AFL_LLVM_ALLOWLIST) or should specifically NOT be instrumented (AFL_LLVM_DENYLIST).
 
 For matching, the function/filename that is being compiled must end in the
-function/filename entry contained in this the instrument file list (to avoid
+function/filename entry contained in this instrument file list (to avoid
 breaking the matching when absolute paths are used during compilation).
 
-**NOTE:** In optimization functions might be inlined and then not match!
+**NOTE:** In builds with optimization enabled functions might be inlined and would not match!
 
 For example if your source tree looks like this:
 ```
@@ -52,7 +52,7 @@ project/feature_b/b1.cpp
 project/feature_b/b2.cpp
 ```
 
-and you only want to test feature_a, then create a the instrument file list file containing:
+and you only want to test feature_a, then create a instrument file list file containing:
 ```
 feature_a/a1.cpp
 feature_a/a2.cpp
@@ -69,7 +69,7 @@ exists somewhere else in the project directories.
 You can also specify function names. Note that for C++ the function names
 must be mangled to match!
 
-afl++ is intelligent to identify if an entry is a filename or a function.
+afl++ is able to identify if an entry is a filename or a function.
 However if you want to be sure (and compliant to the sancov allow/blocklist
 format), you can specify source file entries like this:
 ```
@@ -79,7 +79,7 @@ and function entries like this:
 ```
 fun: MallocFoo
 ```
-Note that whitespace is ignored and comments (`# foo`) supported.
+Note that whitespace is ignored and comments (`# foo`) are supported.
 
 ## 4) UNIX-style pattern matching
 You can add UNIX-style pattern matching in the the instrument file list entries.
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index efaba122..99b17430 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -246,33 +246,60 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   // laf
   if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
 
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] = "-load";
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] =
-        alloc_printf("%s/split-switches-pass.so", obj_path);
+    if (lto_mode) {
+
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
+
+    } else {
+
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/split-switches-pass.so", obj_path);
+
+    }
 
   }
 
   if (getenv("LAF_TRANSFORM_COMPARES") ||
       getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
 
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] = "-load";
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] =
-        alloc_printf("%s/compare-transform-pass.so", obj_path);
+    if (lto_mode) {
+
+      cc_params[cc_par_cnt++] = alloc_printf(
+          "-Wl,-mllvm=-load=%s/compare-transform-pass.so", obj_path);
+
+    } else {
+
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/compare-transform-pass.so", obj_path);
+
+    }
 
   }
 
   if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
       getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
 
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] = "-load";
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] =
-        alloc_printf("%s/split-compares-pass.so", obj_path);
+    if (lto_mode) {
+
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/split-compares-pass.so", obj_path);
+
+    } else {
+
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/split-compares-pass.so", obj_path);
+
+    }
 
   }
 
@@ -282,24 +309,37 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   unsetenv("AFL_LD_CALLER");
   if (cmplog_mode) {
 
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] = "-load";
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] =
-        alloc_printf("%s/cmplog-routines-pass.so", obj_path);
+    if (lto_mode) {
 
-    // reuse split switches from laf
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] = "-load";
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] =
-        alloc_printf("%s/split-switches-pass.so", obj_path);
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path);
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
+      cc_params[cc_par_cnt++] = alloc_printf(
+          "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path);
 
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] = "-load";
-    cc_params[cc_par_cnt++] = "-Xclang";
-    cc_params[cc_par_cnt++] =
-        alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
+    } else {
+
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/cmplog-routines-pass.so", obj_path);
+
+      // reuse split switches from laf
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/split-switches-pass.so", obj_path);
+
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
+
+    }
 
     cc_params[cc_par_cnt++] = "-fno-inline";
 
@@ -312,8 +352,17 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     else
       setenv("AFL_LLVM_LTO_AUTODICTIONARY", "1", 1);
 
+#if defined(AFL_CLANG_LDPATH) && LLVM_VERSION_MAJOR >= 12
+    u8 *ld_ptr = strrchr(AFL_REAL_LD, '/');
+    if (!ld_ptr) ld_ptr = "ld.lld";
+    cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_ptr);
+    cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", AFL_REAL_LD);
+#else
     cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", AFL_REAL_LD);
+#endif
+
     cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
+
     /*
         The current LTO instrim mode is not good, so we disable it
         if (instrument_mode == INSTRUMENT_CFG)
@@ -321,6 +370,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
               alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.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++] = lto_flag;
@@ -329,8 +379,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     if (instrument_mode == INSTRUMENT_PCGUARD) {
 
+#if LLVM_VERSION_MAJOR > 4 ||   \
+    (LLVM_VERSION_MAJOR == 4 && \
+     (LLVM_VERSION_MINOR > 0 || LLVM_VERSION_PATCH >= 1))
       cc_params[cc_par_cnt++] =
           "-fsanitize-coverage=trace-pc-guard";  // edge coverage by default
+#else
+      FATAL("pcguard instrumentation requires llvm 4.0.1+");
+#endif
 
     } else {
 
@@ -965,6 +1021,10 @@ int main(int argc, char **argv, char **envp) {
 #ifdef AFL_CLANG_FLTO
     SAYF(
         "\nafl-clang-lto specific environment variables:\n"
+        "AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), e.g. "
+        "0x10000\n"
+        "AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
+        "functions they are in into this file\n"
         "AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
         "global var\n"
         "AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
diff --git a/llvm_mode/afl-ld-lto.c b/llvm_mode/afl-ld-lto.c
index 1b59bb4a..771e2d0d 100644
--- a/llvm_mode/afl-ld-lto.c
+++ b/llvm_mode/afl-ld-lto.c
@@ -278,7 +278,7 @@ int main(int argc, char **argv) {
 
   if (debug) {
 
-    (void)getcwd(thecwd, sizeof(thecwd));
+    if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
 
     SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd);
     for (i = 0; i < argc; i++)
diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc
index 0b50c547..d9e63bd3 100644
--- a/llvm_mode/afl-llvm-common.cc
+++ b/llvm_mode/afl-llvm-common.cc
@@ -67,8 +67,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
       "__libc_csu",
       "__asan",
       "__msan",
+      "__cmplog",
+      "__sancov",
       "msan.",
       "LLVMFuzzer",
+      "__decide_deferred",
       "maybe_duplicate_stderr",
       "discard_output",
       "close_stdout",
@@ -253,101 +256,63 @@ void initInstrumentList() {
 
 }
 
-bool isInInstrumentList(llvm::Function *F) {
-
-  // is this a function with code? If it is external we dont instrument it
-  // anyway and cant be in the the instrument file list. Or if it is ignored.
-  if (!F->size() || isIgnoreFunction(F)) return false;
-
-  // if we do not have a the instrument file list return true
-  if (!allowListFiles.empty() || !allowListFunctions.empty()) {
-
-    if (!allowListFunctions.empty()) {
-
-      std::string instFunction = F->getName().str();
-
-      for (std::list<std::string>::iterator it = allowListFunctions.begin();
-           it != allowListFunctions.end(); ++it) {
-
-        /* We don't check for filename equality here because
-         * filenames might actually be full paths. Instead we
-         * check that the actual filename ends in the filename
-         * specified in the list. We also allow UNIX-style pattern
-         * matching */
-
-        if (instFunction.length() >= it->length()) {
-
-          if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
-
-            if (debug)
-              SAYF(cMGN "[D] " cRST
-                        "Function %s is in the allow function list, "
-                        "instrumenting ... \n",
-                   instFunction.c_str());
-            return true;
-
-          }
-
-        }
-
-      }
+void scanForDangerousFunctions(llvm::Module *M) {
 
-    }
+  if (!M) return;
 
-    if (!allowListFiles.empty()) {
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 9)
 
-      // let's try to get the filename for the function
-      auto                 bb = &F->getEntryBlock();
-      BasicBlock::iterator IP = bb->getFirstInsertionPt();
-      IRBuilder<>          IRB(&(*IP));
-      DebugLoc             Loc = IP->getDebugLoc();
+  for (GlobalIFunc &IF : M->ifuncs()) {
 
-#if LLVM_VERSION_MAJOR >= 4 || \
-    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
-      if (Loc) {
+    StringRef ifunc_name = IF.getName();
+    Constant *r = IF.getResolver();
+    StringRef r_name = cast<Function>(r->getOperand(0))->getName();
+    if (!be_quiet)
+      fprintf(stderr,
+              "Info: Found an ifunc with name %s that points to resolver "
+              "function %s, we will not instrument this, putting it into the "
+              "block list.\n",
+              ifunc_name.str().c_str(), r_name.str().c_str());
+    denyListFunctions.push_back(r_name.str());
 
-        DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
-
-        unsigned int instLine = cDILoc->getLine();
-        StringRef    instFilename = cDILoc->getFilename();
+  }
 
-        if (instFilename.str().empty()) {
+  GlobalVariable *GV = M->getNamedGlobal("llvm.global_ctors");
+  if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) {
 
-          /* If the original location is empty, try using the inlined location
-           */
-          DILocation *oDILoc = cDILoc->getInlinedAt();
-          if (oDILoc) {
+    ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
 
-            instFilename = oDILoc->getFilename();
-            instLine = oDILoc->getLine();
+    if (InitList) {
 
-          }
+      for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
 
-        }
+        if (ConstantStruct *CS =
+                dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
 
-        /* Continue only if we know where we actually are */
-        if (!instFilename.str().empty()) {
+          if (CS->getNumOperands() >= 2) {
 
-          for (std::list<std::string>::iterator it = allowListFiles.begin();
-               it != allowListFiles.end(); ++it) {
+            if (CS->getOperand(1)->isNullValue())
+              break;  // Found a null terminator, stop here.
 
-            /* We don't check for filename equality here because
-             * filenames might actually be full paths. Instead we
-             * check that the actual filename ends in the filename
-             * specified in the list. We also allow UNIX-style pattern
-             * matching */
+            ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
+            int          Priority = CI ? CI->getSExtValue() : 0;
 
-            if (instFilename.str().length() >= it->length()) {
+            Constant *FP = CS->getOperand(1);
+            if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
+              if (CE->isCast()) FP = CE->getOperand(0);
+            if (Function *F = dyn_cast<Function>(FP)) {
 
-              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-                  0) {
+              if (!F->isDeclaration() &&
+                  strncmp(F->getName().str().c_str(), "__afl", 5) != 0) {
 
-                if (debug)
-                  SAYF(cMGN "[D] " cRST
-                            "Function %s is in the allowlist (%s), "
-                            "instrumenting ... \n",
-                       F->getName().str().c_str(), instFilename.str().c_str());
-                return true;
+                if (!be_quiet)
+                  fprintf(stderr,
+                          "Info: Found constructor function %s with prio "
+                          "%u, we will not instrument this, putting it into a "
+                          "block list.\n",
+                          F->getName().str().c_str(), Priority);
+                denyListFunctions.push_back(F->getName().str());
 
               }
 
@@ -361,63 +326,67 @@ bool isInInstrumentList(llvm::Function *F) {
 
     }
 
-#else
-      if (!Loc.isUnknown()) {
+  }
 
-        DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+#endif
 
-        unsigned int instLine = cDILoc.getLineNumber();
-        StringRef    instFilename = cDILoc.getFilename();
+}
 
-        (void)instLine;
-        /* Continue only if we know where we actually are */
-        if (!instFilename.str().empty()) {
+static std::string getSourceName(llvm::Function *F) {
 
-          for (std::list<std::string>::iterator it = allowListFiles.begin();
-               it != allowListFiles.end(); ++it) {
+  // let's try to get the filename for the function
+  auto                 bb = &F->getEntryBlock();
+  BasicBlock::iterator IP = bb->getFirstInsertionPt();
+  IRBuilder<>          IRB(&(*IP));
+  DebugLoc             Loc = IP->getDebugLoc();
 
-            /* We don't check for filename equality here because
-             * filenames might actually be full paths. Instead we
-             * check that the actual filename ends in the filename
-             * specified in the list. We also allow UNIX-style pattern
-             * matching */
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
+  if (Loc) {
 
-            if (instFilename.str().length() >= it->length()) {
+    DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
 
-              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-                  0) {
+    StringRef instFilename = cDILoc->getFilename();
 
-                return true;
+    if (instFilename.str().empty()) {
 
-              }
+      /* If the original location is empty, try using the inlined location
+       */
+      DILocation *oDILoc = cDILoc->getInlinedAt();
+      if (oDILoc) { instFilename = oDILoc->getFilename(); }
 
-            }
+    }
 
-          }
+    return instFilename.str();
 
-        }
+  }
 
-      }
+#else
+  if (!Loc.isUnknown()) {
 
-    }
+    DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+
+    StringRef instFilename = cDILoc.getFilename();
+
+    /* Continue only if we know where we actually are */
+    return instFilename.str();
+
+  }
 
 #endif
-    else {
 
-      // we could not find out the location. in this case we say it is not
-      // in the the instrument file list
-      if (!be_quiet)
-        WARNF(
-            "No debug information found for function %s, will not be "
-            "instrumented (recompile with -g -O[1-3]).",
-            F->getName().str().c_str());
-      return false;
+  return std::string("");
 
-    }
+}
 
-    return false;
+bool isInInstrumentList(llvm::Function *F) {
 
-  }
+  bool return_default = true;
+
+  // is this a function with code? If it is external we don't instrument it
+  // anyway and it can't be in the instrument file list. Or if it is it is
+  // ignored.
+  if (!F->size() || isIgnoreFunction(F)) return false;
 
   if (!denyListFiles.empty() || !denyListFunctions.empty()) {
 
@@ -455,62 +424,75 @@ bool isInInstrumentList(llvm::Function *F) {
 
     if (!denyListFiles.empty()) {
 
-      // let's try to get the filename for the function
-      auto                 bb = &F->getEntryBlock();
-      BasicBlock::iterator IP = bb->getFirstInsertionPt();
-      IRBuilder<>          IRB(&(*IP));
-      DebugLoc             Loc = IP->getDebugLoc();
+      std::string source_file = getSourceName(F);
 
-#if LLVM_VERSION_MAJOR >= 4 || \
-    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
-      if (Loc) {
+      if (!source_file.empty()) {
 
-        DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+        for (std::list<std::string>::iterator it = denyListFiles.begin();
+             it != denyListFiles.end(); ++it) {
 
-        unsigned int instLine = cDILoc->getLine();
-        StringRef    instFilename = cDILoc->getFilename();
+          /* We don't check for filename equality here because
+           * filenames might actually be full paths. Instead we
+           * check that the actual filename ends in the filename
+           * specified in the list. We also allow UNIX-style pattern
+           * matching */
 
-        if (instFilename.str().empty()) {
+          if (source_file.length() >= it->length()) {
 
-          /* If the original location is empty, try using the inlined location
-           */
-          DILocation *oDILoc = cDILoc->getInlinedAt();
-          if (oDILoc) {
+            if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
 
-            instFilename = oDILoc->getFilename();
-            instLine = oDILoc->getLine();
+              return false;
+
+            }
 
           }
 
         }
 
-        /* Continue only if we know where we actually are */
-        if (!instFilename.str().empty()) {
+      } else {
 
-          for (std::list<std::string>::iterator it = denyListFiles.begin();
-               it != denyListFiles.end(); ++it) {
+        // we could not find out the location. in this case we say it is not
+        // in the instrument file list
+        if (!be_quiet)
+          WARNF(
+              "No debug information found for function %s, will be "
+              "instrumented (recompile with -g -O[1-3]).",
+              F->getName().str().c_str());
 
-            /* We don't check for filename equality here because
-             * filenames might actually be full paths. Instead we
-             * check that the actual filename ends in the filename
-             * specified in the list. We also allow UNIX-style pattern
-             * matching */
+      }
 
-            if (instFilename.str().length() >= it->length()) {
+    }
 
-              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-                  0) {
+  }
 
-                if (debug)
-                  SAYF(cMGN "[D] " cRST
-                            "Function %s is in the denylist (%s), not "
-                            "instrumenting ... \n",
-                       F->getName().str().c_str(), instFilename.str().c_str());
-                return false;
+  // if we do not have a instrument file list return true
+  if (!allowListFiles.empty() || !allowListFunctions.empty()) {
 
-              }
+    return_default = false;
 
-            }
+    if (!allowListFunctions.empty()) {
+
+      std::string instFunction = F->getName().str();
+
+      for (std::list<std::string>::iterator it = allowListFunctions.begin();
+           it != allowListFunctions.end(); ++it) {
+
+        /* We don't check for filename equality here because
+         * filenames might actually be full paths. Instead we
+         * check that the actual filename ends in the filename
+         * specified in the list. We also allow UNIX-style pattern
+         * matching */
+
+        if (instFunction.length() >= it->length()) {
+
+          if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
+
+            if (debug)
+              SAYF(cMGN "[D] " cRST
+                        "Function %s is in the allow function list, "
+                        "instrumenting ... \n",
+                   instFunction.c_str());
+            return true;
 
           }
 
@@ -520,35 +502,31 @@ bool isInInstrumentList(llvm::Function *F) {
 
     }
 
-#else
-      if (!Loc.isUnknown()) {
-
-        DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
-
-        unsigned int instLine = cDILoc.getLineNumber();
-        StringRef instFilename = cDILoc.getFilename();
+    if (!allowListFiles.empty()) {
 
-        (void)instLine;
-        /* Continue only if we know where we actually are */
-        if (!instFilename.str().empty()) {
+      std::string source_file = getSourceName(F);
 
-          for (std::list<std::string>::iterator it = denyListFiles.begin();
-               it != denyListFiles.end(); ++it) {
+      if (!source_file.empty()) {
 
-            /* We don't check for filename equality here because
-             * filenames might actually be full paths. Instead we
-             * check that the actual filename ends in the filename
-             * specified in the list. We also allow UNIX-style pattern
-             * matching */
+        for (std::list<std::string>::iterator it = allowListFiles.begin();
+             it != allowListFiles.end(); ++it) {
 
-            if (instFilename.str().length() >= it->length()) {
+          /* We don't check for filename equality here because
+           * filenames might actually be full paths. Instead we
+           * check that the actual filename ends in the filename
+           * specified in the list. We also allow UNIX-style pattern
+           * matching */
 
-              if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
-                  0) {
+          if (source_file.length() >= it->length()) {
 
-                return false;
+            if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
 
-              }
+              if (debug)
+                SAYF(cMGN "[D] " cRST
+                          "Function %s is in the allowlist (%s), "
+                          "instrumenting ... \n",
+                     F->getName().str().c_str(), source_file.c_str());
+              return true;
 
             }
 
@@ -556,29 +534,24 @@ bool isInInstrumentList(llvm::Function *F) {
 
         }
 
-      }
+      } else {
 
-    }
+        // we could not find out the location. In this case we say it is not
+        // in the instrument file list
+        if (!be_quiet)
+          WARNF(
+              "No debug information found for function %s, will not be "
+              "instrumented (recompile with -g -O[1-3]).",
+              F->getName().str().c_str());
+        return false;
 
-#endif
-    else {
-
-      // we could not find out the location. in this case we say it is not
-      // in the the instrument file list
-      if (!be_quiet)
-        WARNF(
-            "No debug information found for function %s, will be "
-            "instrumented (recompile with -g -O[1-3]).",
-            F->getName().str().c_str());
-      return true;
+      }
 
     }
 
-    return true;
-
   }
 
-  return true;  // not reached
+  return return_default;
 
 }
 
diff --git a/llvm_mode/afl-llvm-common.h b/llvm_mode/afl-llvm-common.h
index 5b96be43..a1561d9c 100644
--- a/llvm_mode/afl-llvm-common.h
+++ b/llvm_mode/afl-llvm-common.h
@@ -37,6 +37,7 @@ bool                   isIgnoreFunction(const llvm::Function *F);
 void                   initInstrumentList();
 bool                   isInInstrumentList(llvm::Function *F);
 unsigned long long int calculateCollisions(uint32_t edges);
+void                   scanForDangerousFunctions(llvm::Module *M);
 
 #ifndef IS_EXTERN
   #define IS_EXTERN
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index fd8e48a7..300951fb 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -103,6 +103,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
   std::vector<std::string>         dictionary;
   std::vector<CallInst *>          calls;
   DenseMap<Value *, std::string *> valueMap;
+  std::vector<BasicBlock *>        BlockList;
   char *                           ptr;
   FILE *                           documentFile = NULL;
 
@@ -150,7 +151,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
       map_addr = 0;
 
-    } else if (map_addr == 0) {
+    } else if (getenv("AFL_LLVM_MAP_DYNAMIC")) {
 
       FATAL(
           "AFL_LLVM_MAP_ADDR and AFL_LLVM_MAP_DYNAMIC cannot be used together");
@@ -217,79 +218,9 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   }
 
-    */
-
-  std::vector<std::string> module_block_list;
-
-  if (map_addr) {
-
-    for (GlobalIFunc &IF : M.ifuncs()) {
-
-      StringRef ifunc_name = IF.getName();
-      Constant *r = IF.getResolver();
-      StringRef r_name = cast<Function>(r->getOperand(0))->getName();
-      if (!be_quiet)
-        fprintf(stderr,
-                "Warning: Found an ifunc with name %s that points to resolver "
-                "function %s, we cannot instrument this, putting it into a "
-                "block list.\n",
-                ifunc_name.str().c_str(), r_name.str().c_str());
-      module_block_list.push_back(r_name.str());
-
-    }
-
-    GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors");
-    if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) {
-
-      ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
-
-      if (InitList) {
-
-        for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
-
-          if (ConstantStruct *CS =
-                  dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
-
-            if (CS->getNumOperands() >= 2) {
-
-              if (CS->getOperand(1)->isNullValue())
-                break;  // Found a null terminator, stop here.
-
-              ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
-              int          Priority = CI ? CI->getSExtValue() : 0;
-
-              Constant *FP = CS->getOperand(1);
-              if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
-                if (CE->isCast()) FP = CE->getOperand(0);
-              if (Function *F = dyn_cast<Function>(FP)) {
-
-                if (!F->isDeclaration() &&
-                    strncmp(F->getName().str().c_str(), "__afl", 5) != 0 &&
-                    Priority <= 5) {
-
-                  if (!be_quiet)
-                    fprintf(stderr,
-                            "Warning: Found constructor function %s with prio "
-                            "%u, we cannot instrument this, putting it into a "
-                            "block list.\n",
-                            F->getName().str().c_str(), Priority);
-                  module_block_list.push_back(F->getName().str());
-
-                }
-
-              }
-
-            }
-
-          }
-
-        }
-
-      }
-
-    }
+  */
 
-  }
+  scanForDangerousFunctions(&M);
 
   /* Instrument all the things! */
 
@@ -307,26 +238,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
     if (F.size() < function_minimum_size) continue;
     if (isIgnoreFunction(&F)) continue;
 
-    if (module_block_list.size()) {
-
-      for (auto bname : module_block_list) {
-
-        std::string fname = F.getName().str();
-
-        if (fname.compare(bname) == 0) {
-
-          if (!be_quiet)
-            WARNF(
-                "Skipping instrumentation of dangerous early running function "
-                "%s",
-                fname.c_str());
-
-        }
-
-      }
-
-    }
-
     // the instrument file list check
     AttributeList Attrs = F.getAttributes();
     if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
@@ -380,14 +291,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
           if ((callInst = dyn_cast<CallInst>(&IN))) {
 
-            bool    isStrcmp = true;
-            bool    isMemcmp = true;
-            bool    isStrncmp = true;
-            bool    isStrcasecmp = true;
-            bool    isStrncasecmp = true;
-            bool    isIntMemcpy = true;
-            bool    addedNull = false;
-            uint8_t optLen = 0;
+            bool   isStrcmp = true;
+            bool   isMemcmp = true;
+            bool   isStrncmp = true;
+            bool   isStrcasecmp = true;
+            bool   isStrncasecmp = true;
+            bool   isIntMemcpy = true;
+            bool   addedNull = false;
+            size_t optLen = 0;
 
             Function *Callee = callInst->getCalledFunction();
             if (!Callee) continue;
@@ -400,6 +311,24 @@ bool AFLLTOPass::runOnModule(Module &M) {
             isStrncasecmp &= !FuncName.compare("strncasecmp");
             isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
 
+            /* we do something different here, putting this BB and the
+               successors in a block map */
+            if (!FuncName.compare("__afl_persistent_loop")) {
+
+              BlockList.push_back(&BB);
+              /*
+                            for (succ_iterator SI = succ_begin(&BB), SE =
+                 succ_end(&BB); SI != SE; ++SI) {
+
+                              BasicBlock *succ = *SI;
+                              BlockList.push_back(succ);
+
+                            }
+
+              */
+
+            }
+
             if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
                 !isStrncasecmp && !isIntMemcpy)
               continue;
@@ -617,18 +546,27 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
             // add null byte if this is a string compare function and a null
             // was not already added
-            if (addedNull == false && !isMemcmp) {
+            if (!isMemcmp) {
+
+              if (addedNull == false) {
 
-              thestring.append("\0", 1);  // add null byte
-              optLen++;
+                thestring.append("\0", 1);  // add null byte
+                optLen++;
+
+              }
+
+              // ensure we do not have garbage
+              size_t offset = thestring.find('\0', 0);
+              if (offset + 1 < optLen) optLen = offset + 1;
+              thestring = thestring.substr(0, optLen);
 
             }
 
             if (!be_quiet) {
 
               std::string outstring;
-              fprintf(stderr, "%s: length %u/%u \"", FuncName.c_str(), optLen,
-                      (unsigned int)thestring.length());
+              fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen,
+                      thestring.length());
               for (uint8_t i = 0; i < thestring.length(); i++) {
 
                 uint8_t c = thestring[i];
@@ -686,13 +624,35 @@ bool AFLLTOPass::runOnModule(Module &M) {
       do {
 
         --i;
-        BasicBlock *              newBB;
+        BasicBlock *              newBB = NULL;
         BasicBlock *              origBB = &(*InsBlocks[i]);
         std::vector<BasicBlock *> Successors;
         Instruction *             TI = origBB->getTerminator();
         uint32_t                  fs = origBB->getParent()->size();
         uint32_t                  countto;
 
+        if (BlockList.size()) {
+
+          int skip = 0;
+          for (uint32_t k = 0; k < BlockList.size(); k++) {
+
+            if (origBB == BlockList[k]) {
+
+              if (debug)
+                fprintf(
+                    stderr,
+                    "DEBUG: Function %s skipping BB with/after __afl_loop\n",
+                    F.getName().str().c_str());
+              skip = 1;
+
+            }
+
+          }
+
+          if (skip) continue;
+
+        }
+
         for (succ_iterator SI = succ_begin(origBB), SE = succ_end(origBB);
              SI != SE; ++SI) {
 
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
index 618abe48..a791d720 100644
--- a/llvm_mode/afl-llvm-pass.so.cc
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -112,7 +112,7 @@ uint64_t PowerOf2Ceil(unsigned in) {
 #endif
 
 /* #if LLVM_VERSION_STRING >= "4.0.1" */
-#if LLVM_VERSION_MAJOR >= 4 || \
+#if LLVM_VERSION_MAJOR > 4 || \
     (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
   #define AFL_HAVE_VECTOR_INTRINSICS 1
 #endif
@@ -194,7 +194,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
 #ifdef AFL_HAVE_VECTOR_INTRINSICS
   /* Decide previous location vector size (must be a power of two) */
-  VectorType *PrevLocTy;
+  VectorType *PrevLocTy = NULL;
 
   if (ngram_size_str)
     if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
@@ -236,7 +236,7 @@ bool AFLCoverage::runOnModule(Module &M) {
       new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
                          GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
   GlobalVariable *AFLPrevLoc;
-  GlobalVariable *AFLContext;
+  GlobalVariable *AFLContext = NULL;
 
   if (ctx_str)
 #ifdef __ANDROID__
@@ -292,11 +292,12 @@ bool AFLCoverage::runOnModule(Module &M) {
   ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
   ConstantInt *One = ConstantInt::get(Int8Ty, 1);
 
-  LoadInst *PrevCtx;  // CTX sensitive coverage
+  LoadInst *PrevCtx = NULL;  // CTX sensitive coverage
 
   /* Instrument all the things! */
 
   int inst_blocks = 0;
+  scanForDangerousFunctions(&M);
 
   for (auto &F : M) {
 
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
index a567593e..d00fd26f 100644
--- a/llvm_mode/afl-llvm-rt.o.c
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -35,6 +35,8 @@
 #include <string.h>
 #include <assert.h>
 #include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
 #include <errno.h>
 
 #include <sys/mman.h>
@@ -52,8 +54,6 @@
    Basically, we need to make sure that the forkserver is initialized after
    the LLVM-generated runtime initialization pass, not before. */
 
-#define CONST_PRIO 5
-
 #ifndef MAP_FIXED_NOREPLACE
   #ifdef MAP_EXCL
     #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
@@ -62,6 +62,8 @@
   #endif
 #endif
 
+#define CTOR_PRIO 3
+
 #include <sys/mman.h>
 #include <fcntl.h>
 
@@ -75,11 +77,7 @@
   #define MAP_INITIAL_SIZE MAP_SIZE
 #endif
 
-#ifdef AFL_REAL_LD
-u8 __afl_area_initial[MAP_INITIAL_SIZE];
-#else
-u8                  __afl_area_initial[MAP_SIZE];
-#endif
+u8   __afl_area_initial[MAP_INITIAL_SIZE];
 u8 * __afl_area_ptr = __afl_area_initial;
 u8 * __afl_dictionary;
 u8 * __afl_fuzz_ptr;
@@ -109,6 +107,10 @@ struct cmp_map *__afl_cmp_map;
 
 static u8 is_persistent;
 
+/* Are we in sancov mode? */
+
+static u8 _is_sancov;
+
 /* Error reporting to forkserver controller */
 
 void send_forkserver_error(int error) {
@@ -186,7 +188,7 @@ static void __afl_map_shm_fuzz() {
 static void __afl_map_shm(void) {
 
   // we we are not running in afl ensure the map exists
-  if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+  if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_initial; }
 
   char *id_str = getenv(SHM_ENV_VAR);
 
@@ -194,8 +196,8 @@ static void __afl_map_shm(void) {
 
     if (__afl_final_loc % 8)
       __afl_final_loc = (((__afl_final_loc + 7) >> 3) << 3);
-
     __afl_map_size = __afl_final_loc;
+
     if (__afl_final_loc > MAP_SIZE) {
 
       char *ptr;
@@ -205,10 +207,12 @@ static void __afl_map_shm(void) {
 
         if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
 
-          fprintf(stderr,
-                  "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
-                  "be able to run this instrumented program!\n",
-                  __afl_final_loc);
+          if (!getenv("AFL_QUIET"))
+            fprintf(stderr,
+                    "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
+                    "to be able to run this instrumented program!\n",
+                    __afl_final_loc);
+
           if (id_str) {
 
             send_forkserver_error(FS_ERROR_MAP_SIZE);
@@ -218,10 +222,11 @@ static void __afl_map_shm(void) {
 
         } else {
 
-          fprintf(stderr,
-                  "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
-                  "be able to run this instrumented program!\n",
-                  __afl_final_loc);
+          if (!getenv("AFL_QUIET"))
+            fprintf(stderr,
+                    "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u "
+                    "to be able to run this instrumented program!\n",
+                    __afl_final_loc);
 
         }
 
@@ -237,13 +242,25 @@ static void __afl_map_shm(void) {
 
   if (getenv("AFL_DEBUG"))
     fprintf(stderr,
-            "DEBUG: id_str %s, __afl_map_addr 0x%llx, MAP_SIZE %u, "
-            "__afl_final_loc %u, max_size_forkserver %u/0x%x\n",
-            id_str == NULL ? "<null>" : id_str, __afl_map_addr, MAP_SIZE,
-            __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
+            "DEBUG: id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
+            "__afl_map_addr 0x%llx, MAP_SIZE %u, __afl_final_loc %u, "
+            "max_size_forkserver %u/0x%x\n",
+            id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
+            __afl_area_initial, __afl_map_addr, MAP_SIZE, __afl_final_loc,
+            FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
 
   if (id_str) {
 
+    if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
+
+      if (__afl_map_addr)
+        munmap((void *)__afl_map_addr, __afl_final_loc);
+      else
+        free(__afl_area_ptr);
+      __afl_area_ptr = __afl_area_initial;
+
+    }
+
 #ifdef USEMMAP
     const char *   shm_file_path = id_str;
     int            shm_fd = -1;
@@ -312,11 +329,14 @@ static void __afl_map_shm(void) {
 
     __afl_area_ptr[0] = 1;
 
-  } else if (__afl_map_addr) {
+  } else if ((!__afl_area_ptr || __afl_area_ptr == __afl_area_initial) &&
+
+             __afl_map_addr) {
 
     __afl_area_ptr =
         mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE,
              MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
     if (__afl_area_ptr == MAP_FAILED) {
 
       fprintf(stderr, "can not aquire mmap for address %p\n",
@@ -325,6 +345,14 @@ static void __afl_map_shm(void) {
 
     }
 
+  } else if (_is_sancov && __afl_area_ptr != __afl_area_initial) {
+
+    free(__afl_area_ptr);
+    __afl_area_ptr = NULL;
+    if (__afl_final_loc > MAP_INITIAL_SIZE)
+      __afl_area_ptr = malloc(__afl_final_loc);
+    if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+
   }
 
   id_str = getenv(CMPLOG_SHM_ENV_VAR);
@@ -842,9 +870,22 @@ void __afl_manual_init(void) {
 
   static u8 init_done;
 
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) {
+
+    init_done = 1;
+    is_persistent = 0;
+    __afl_sharedmem_fuzzing = 0;
+    if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial;
+
+    if (getenv("AFL_DEBUG"))
+      fprintf(stderr,
+              "DEBUG: disabled instrumentation because of "
+              "AFL_DISABLE_LLVM_INSTRUMENTATION\n");
+
+  }
+
   if (!init_done) {
 
-    __afl_map_shm();
     __afl_start_forkserver();
     init_done = 1;
 
@@ -852,11 +893,11 @@ void __afl_manual_init(void) {
 
 }
 
-/* Proper initialization routine. */
+/* Initialization of the forkserver - latest possible */
 
-__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
+__attribute__((constructor())) void __afl_auto_init(void) {
 
-  is_persistent = !!getenv(PERSIST_ENV_VAR);
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
 
   if (getenv(DEFER_ENV_VAR)) return;
 
@@ -864,6 +905,57 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
 
 }
 
+/* Initialization of the shmem - earliest possible because of LTO fixed mem. */
+
+__attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) {
+
+  is_persistent = !!getenv(PERSIST_ENV_VAR);
+
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+
+  __afl_map_shm();
+
+}
+
+/* preset __afl_area_ptr #2 */
+
+__attribute__((constructor(1))) void __afl_auto_second(void) {
+
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+  u8 *ptr;
+
+  if (__afl_final_loc) {
+
+    if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial)
+      free(__afl_area_ptr);
+
+    if (__afl_map_addr)
+      ptr = (u8 *)mmap((void *)__afl_map_addr, __afl_final_loc,
+                       PROT_READ | PROT_WRITE,
+                       MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    else
+      ptr = (u8 *)malloc(__afl_final_loc);
+
+    if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+
+  }
+
+}
+
+/* preset __afl_area_ptr #1 - at constructor level 0 global variables have
+   not been set */
+
+__attribute__((constructor(0))) void __afl_auto_first(void) {
+
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+  u8 *ptr;
+
+  ptr = (u8 *)malloc(1024000);
+
+  if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+
+}
+
 /* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard.
    It remains non-operational in the traditional, plugin-backed LLVM mode.
    For more info about 'trace-pc-guard', see llvm_mode/README.md.
@@ -874,7 +966,7 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
 void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
 
   // For stability analysis, if you want to know to which function unstable
-  // edge IDs belong to - uncomment, recompile+install llvm_mode, recompile
+  // edge IDs belong - uncomment, recompile+install llvm_mode, recompile
   // the target. libunwind and libbacktrace are better solutions.
   // Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture
   // the backtrace output
@@ -912,7 +1004,8 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
 
 #else
 
-  __afl_area_ptr[*guard] = __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0);
+  __afl_area_ptr[*guard] =
+      __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0);
 
 #endif
 
@@ -927,6 +1020,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
   u32   inst_ratio = 100;
   char *x;
 
+  _is_sancov = 1;
+
   if (getenv("AFL_DEBUG")) {
 
     fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n",
diff --git a/llvm_mode/cmplog-instructions-pass.cc b/llvm_mode/cmplog-instructions-pass.cc
index 7c48d906..d5de3dbb 100644
--- a/llvm_mode/cmplog-instructions-pass.cc
+++ b/llvm_mode/cmplog-instructions-pass.cc
@@ -284,3 +284,9 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPass(
 static RegisterStandardPasses RegisterCmpLogInstructionsPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass);
 
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO(
+    PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+    registerCmpLogInstructionsPass);
+#endif
+
diff --git a/llvm_mode/cmplog-routines-pass.cc b/llvm_mode/cmplog-routines-pass.cc
index a0f8f64f..c44f38c4 100644
--- a/llvm_mode/cmplog-routines-pass.cc
+++ b/llvm_mode/cmplog-routines-pass.cc
@@ -204,3 +204,9 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPass(
 static RegisterStandardPasses RegisterCmpLogRoutinesPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass);
 
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO(
+    PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+    registerCmpLogRoutinesPass);
+#endif
+
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
index bed3597a..acdd0f3b 100644
--- a/llvm_mode/compare-transform-pass.so.cc
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -137,7 +137,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
           bool isStrcasecmp = processStrcasecmp;
           bool isStrncasecmp = processStrncasecmp;
           bool isIntMemcpy = true;
-          bool indirect = false;
 
           Function *Callee = callInst->getCalledFunction();
           if (!Callee) continue;
@@ -264,8 +263,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 
             }
 
-            if ((HasStr1 || HasStr2)) indirect = true;
-
           }
 
           if (isIntMemcpy) continue;
@@ -278,7 +275,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 
               Str1 = StringRef(*val);
               HasStr1 = true;
-              indirect = true;
               // fprintf(stderr, "loaded1 %s\n", Str1.str().c_str());
 
             } else {
@@ -288,7 +284,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 
                 Str2 = StringRef(*val);
                 HasStr2 = true;
-                indirect = true;
                 // fprintf(stderr, "loaded2 %s\n", Str2.str().c_str());
 
               }
@@ -585,3 +580,8 @@ static RegisterStandardPasses RegisterCompTransPass(
 static RegisterStandardPasses RegisterCompTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
 
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCompTransPassLTO(
+    PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass);
+#endif
+
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc
index 3630bd8c..617b55de 100644
--- a/llvm_mode/split-compares-pass.so.cc
+++ b/llvm_mode/split-compares-pass.so.cc
@@ -1342,3 +1342,9 @@ static RegisterStandardPasses RegisterSplitComparesPass(
 static RegisterStandardPasses RegisterSplitComparesTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
 
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterSplitComparesTransPassLTO(
+    PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+    registerSplitComparesPass);
+#endif
+
diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc
index f025df77..a79d4114 100644
--- a/llvm_mode/split-switches-pass.so.cc
+++ b/llvm_mode/split-switches-pass.so.cc
@@ -439,3 +439,9 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass(
 static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);
 
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO(
+    PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+    registerSplitSwitchesTransPass);
+#endif
+