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/LLVMInsTrim.so.cc89
-rw-r--r--llvm_mode/Makefile8
-rw-r--r--llvm_mode/MarkNodes.cc30
-rw-r--r--llvm_mode/README.md21
-rw-r--r--llvm_mode/afl-clang-fast.c33
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc71
-rw-r--r--llvm_mode/compare-transform-pass.so.cc150
-rw-r--r--llvm_mode/split-compares-pass.so.cc270
-rw-r--r--llvm_mode/split-switches-pass.so.cc199
9 files changed, 752 insertions, 119 deletions
diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc
index 11451b43..5b7b79e1 100644
--- a/llvm_mode/LLVMInsTrim.so.cc
+++ b/llvm_mode/LLVMInsTrim.so.cc
@@ -3,10 +3,23 @@
 #include <stdarg.h>
 #include <unistd.h>
 
+#include "llvm/Config/llvm-config.h"
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
+typedef long double max_align_t;
+#endif
+
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/DebugInfo.h"
+#else
+#include "llvm/Support/CFG.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/DebugInfo.h"
+#endif
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LegacyPassManager.h"
@@ -16,9 +29,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/CFG.h"
 #include <unordered_set>
 #include <random>
 #include <list>
@@ -97,7 +108,7 @@ struct InsTrim : public ModulePass {
   // ripped from aflgo
   static bool isBlacklisted(const Function *F) {
 
-    static const SmallVector<std::string, 4> Blacklist = {
+    static const char *Blacklist[] = {
 
         "asan.",
         "llvm.",
@@ -144,19 +155,6 @@ struct InsTrim : public ModulePass {
     // this is our default
     MarkSetOpt = true;
 
-    /*    // I dont think this makes sense to port into LLVMInsTrim
-          char* inst_ratio_str = getenv("AFL_INST_RATIO");
-          unsigned int inst_ratio = 100;
-          if (inst_ratio_str) {
-
-           if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
-       inst_ratio > 100) FATAL("Bad value of AFL_INST_RATIO (must be between 1
-       and 100)");
-
-          }
-
-    */
-
     LLVMContext &C = M.getContext();
     IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
     IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
@@ -186,6 +184,8 @@ struct InsTrim : public ModulePass {
         StringRef    instFilename;
         unsigned int instLine = 0;
 
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
         for (auto &BB : F) {
 
           BasicBlock::iterator IP = BB.getFirstInsertionPt();
@@ -240,6 +240,48 @@ struct InsTrim : public ModulePass {
 
         }
 
+#else
+        for (auto &BB : F) {
+
+          BasicBlock::iterator IP = BB.getFirstInsertionPt();
+          IRBuilder<>          IRB(&(*IP));
+          if (Loc.isUnknown()) Loc = IP->getDebugLoc();
+
+        }
+
+        if (!Loc.isUnknown()) {
+
+          DILocation cDILoc(Loc.getAsMDNode(C));
+
+          instLine = cDILoc.getLineNumber();
+          instFilename = cDILoc.getFilename();
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.end(); ++it) {
+
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#endif
         /* Either we couldn't figure out our location or the location is
          * not whitelisted, so we skip instrumentation. */
         if (!instrumentBlock) {
@@ -432,28 +474,19 @@ struct InsTrim : public ModulePass {
         IRB.CreateStore(Incr, MapPtrIdx)
             ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
 
-        /* Set prev_loc to cur_loc >> 1 */
-        /*
-        StoreInst *Store = IRB.CreateStore(ConstantInt::get(Int32Ty, L >> 1),
-        OldPrev); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C,
-        None));
-        */
-
         total_instr++;
 
       }
 
     }
 
-    OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n" /*", ratio
-                                                                %u%%)."*/
-        ,
-        total_instr, total_rs, total_hs,
+    OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr,
+        total_rs, total_hs,
         getenv("AFL_HARDEN")
             ? "hardened"
             : ((getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN"))
                    ? "ASAN/MSAN"
-                   : "non-hardened") /*, inst_ratio*/);
+                   : "non-hardened"));
     return false;
 
   }
diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile
index 9ee6fc8b..6e0a27af 100644
--- a/llvm_mode/Makefile
+++ b/llvm_mode/Makefile
@@ -29,14 +29,14 @@ ifeq "$(shell uname)" "OpenBSD"
   LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
   HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
   ifeq "$(HAS_OPT)" "1"
-    $(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 10) -> e.g. "pkg_add llvm-7.0.1p9")
+    $(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 11) -> e.g. "pkg_add llvm-7.0.1p9")
   endif
 else
   LLVM_CONFIG ?= llvm-config
 endif
 
 LLVMVER  = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
-LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[1-9]' && echo 1 || echo 0 )
+LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[2-9]' && echo 1 || echo 0 )
 LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
 LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
 LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
@@ -48,7 +48,7 @@ ifeq "$(LLVMVER)" ""
 endif
 
 ifeq "$(LLVM_UNSUPPORTED)" "1"
-  $(warning llvm_mode only supports llvm versions 3.8.0 up to 10)
+  $(warning llvm_mode only supports llvm versions 3.8.0 up to 11)
 endif
 
 ifeq "$(LLVM_MAJOR)" "9"
@@ -201,7 +201,7 @@ endif
 	ln -sf afl-clang-fast ../afl-clang-fast++
 
 ../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
-	$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
+	-$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
 
 ../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
 	$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
diff --git a/llvm_mode/MarkNodes.cc b/llvm_mode/MarkNodes.cc
index 2aeeda8d..7b22bac0 100644
--- a/llvm_mode/MarkNodes.cc
+++ b/llvm_mode/MarkNodes.cc
@@ -3,11 +3,22 @@
 #include <queue>
 #include <set>
 #include <vector>
+
+#include "llvm/Config/llvm-config.h"
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
+typedef long double max_align_t;
+#endif
+
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/BasicBlock.h"
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
 #include "llvm/IR/CFG.h"
+#else
+#include "llvm/Support/CFG.h"
+#endif
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
@@ -65,16 +76,11 @@ void buildCFG(Function *F) {
 
   }
 
-  // uint32_t FakeID = 0;
   for (auto S = F->begin(), E = F->end(); S != E; ++S) {
 
     BasicBlock *BB = &*S;
     uint32_t    MyID = LMap[BB];
-    // if (succ_begin(BB) == succ_end(BB)) {
 
-    // Succs[MyID].push_back(FakeID);
-    // Marked.insert(MyID);
-    //}
     for (auto I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
 
       Succs[MyID].push_back(LMap[*I]);
@@ -113,7 +119,7 @@ void DFStree(size_t now_id) {
 
 }
 
-void turnCFGintoDAG(Function *F) {
+void turnCFGintoDAG() {
 
   tSuccs = Succs;
   tag.resize(Blocks.size());
@@ -176,7 +182,7 @@ void DFS(uint32_t now) {
 
 }
 
-void DominatorTree(Function *F) {
+void DominatorTree() {
 
   if (Blocks.empty()) return;
   uint32_t s = start_point;
@@ -390,7 +396,7 @@ void MarkSubGraph(uint32_t ss, uint32_t tt) {
 
 }
 
-void MarkVertice(Function *F) {
+void MarkVertice() {
 
   uint32_t s = start_point;
 
@@ -411,8 +417,6 @@ void MarkVertice(Function *F) {
 
   timeStamp = 0;
   uint32_t t = 0;
-  // MarkSubGraph(s, t);
-  // return;
 
   while (s != t) {
 
@@ -432,9 +436,9 @@ std::pair<std::vector<BasicBlock *>, std::vector<BasicBlock *> > markNodes(
   reset();
   labelEachBlock(F);
   buildCFG(F);
-  turnCFGintoDAG(F);
-  DominatorTree::DominatorTree(F);
-  MarkVertice(F);
+  turnCFGintoDAG();
+  DominatorTree::DominatorTree();
+  MarkVertice();
 
   std::vector<BasicBlock *> Result, ResultAbove;
   for (uint32_t x : Markabove) {
diff --git a/llvm_mode/README.md b/llvm_mode/README.md
index 5afa4dfd..54788aba 100644
--- a/llvm_mode/README.md
+++ b/llvm_mode/README.md
@@ -5,7 +5,7 @@
 
 ## 1) Introduction
 
-! llvm_mode works with llvm versions 3.8.0 up to 10 !
+! llvm_mode works with llvm versions 3.8.0 up to 11 !
 
 The code in this directory allows you to instrument programs for AFL using
 true compiler-level instrumentation, instead of the more crude
@@ -198,24 +198,23 @@ PS. Because there are task switches still involved, the mode isn't as fast as
 faster than the normal fork() model, and compared to in-process fuzzing,
 should be a lot more robust.
 
-## 8) Bonus feature #3: new 'trace-pc-guard' mode
+## 8) Bonus feature #3: 'trace-pc-guard' mode
 
-Recent versions of LLVM are shipping with a built-in execution tracing feature
+LLVM is shipping with a built-in execution tracing feature
 that provides AFL with the necessary tracing data without the need to
 post-process the assembly or install any compiler plugins. See:
 
   http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards
 
-If you have a sufficiently recent compiler and want to give it a try, build
-afl-clang-fast this way:
+If you have not an outdated compiler and want to give it a try, build
+targets this way:
 
 ```
-  AFL_TRACE_PC=1 make clean all
+ libtarget-1.0 $ AFL_LLVM_USE_TRACE_PC=1  make
 ```
 
-Note that this mode is currently about 20% slower than "vanilla" afl-clang-fast,
+Note that this mode is about 20% slower than "vanilla" afl-clang-fast,
 and about 5-10% slower than afl-clang. This is likely because the
-instrumentation is not inlined, and instead involves a function call. On systems
-that support it, compiling your target with -flto should help.
-
-
+instrumentation is not inlined, and instead involves a function call.
+On systems that support it, compiling your target with -flto can help
+a bit.
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index ddaa2388..4fbaf9ec 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -212,13 +212,24 @@ static void edit_params(u32 argc, char** argv) {
   // "-fsanitize-coverage=trace-cmp,trace-div,trace-gep";
   // cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0";
 #else
-  cc_params[cc_par_cnt++] = "-Xclang";
-  cc_params[cc_par_cnt++] = "-load";
-  cc_params[cc_par_cnt++] = "-Xclang";
-  if (getenv("AFL_LLVM_INSTRIM") != NULL || getenv("INSTRIM_LIB") != NULL)
-    cc_params[cc_par_cnt++] = alloc_printf("%s/libLLVMInsTrim.so", obj_path);
-  else
-    cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
+  if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") ||
+      getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) {
+
+    cc_params[cc_par_cnt++] =
+        "-fsanitize-coverage=trace-pc-guard";  // edge coverage by default
+
+  } else {
+
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = "-load";
+    cc_params[cc_par_cnt++] = "-Xclang";
+    if (getenv("AFL_LLVM_INSTRIM") != NULL || getenv("INSTRIM_LIB") != NULL)
+      cc_params[cc_par_cnt++] = alloc_printf("%s/libLLVMInsTrim.so", obj_path);
+    else
+      cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
+
+  }
+
 #endif                                                     /* ^USE_TRACE_PC */
 
   }
@@ -292,8 +303,10 @@ static void edit_params(u32 argc, char** argv) {
 
 #ifdef USE_TRACE_PC
 
-  if (getenv("AFL_INST_RATIO"))
-    FATAL("AFL_INST_RATIO not available at compile time with 'trace-pc'.");
+  if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") ||
+      getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC"))
+    if (getenv("AFL_INST_RATIO"))
+      FATAL("AFL_INST_RATIO not available at compile time with 'trace-pc'.");
 
 #endif                                                      /* USE_TRACE_PC */
 
@@ -474,6 +487,8 @@ int main(int argc, char** argv) {
 #ifdef USE_TRACE_PC
     SAYF(cCYA "afl-clang-fast" VERSION cRST
               " [tpcg] by <lszekeres@google.com>\n");
+#warning \
+    "You do not need to specifically compile with USE_TRACE_PC anymore, setting the environment variable AFL_LLVM_USE_TRACE_PC is enough."
 #else
     SAYF(cCYA "afl-clang-fast" VERSION cRST " by <lszekeres@google.com>\n");
 #endif                                                     /* ^USE_TRACE_PC */
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
index 15cc6127..2cd23adf 100644
--- a/llvm_mode/afl-llvm-pass.so.cc
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -37,14 +37,26 @@
 #include <fstream>
 #include <sys/time.h>
 
-#include "llvm/IR/DebugInfo.h"
-#include "llvm/IR/BasicBlock.h"
+#include "llvm/Config/llvm-config.h"
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
+typedef long double max_align_t;
+#endif
+
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/CFG.h"
+#else
+#include "llvm/DebugInfo.h"
+#include "llvm/Support/CFG.h"
+#endif
 
 using namespace llvm;
 
@@ -78,7 +90,7 @@ class AFLCoverage : public ModulePass {
   // ripped from aflgo
   static bool isBlacklisted(const Function *F) {
 
-    static const SmallVector<std::string, 4> Blacklist = {
+    static const char *Blacklist[] = {
 
         "asan.",
         "llvm.",
@@ -197,6 +209,8 @@ bool AFLCoverage::runOnModule(Module &M) {
          * For now, just instrument the block if we are not able
          * to determine our location. */
         DebugLoc Loc = IP->getDebugLoc();
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
         if (Loc) {
 
           DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
@@ -249,6 +263,47 @@ bool AFLCoverage::runOnModule(Module &M) {
 
         }
 
+#else
+        if (!Loc.isUnknown()) {
+
+          DILocation cDILoc(Loc.getAsMDNode(C));
+
+          unsigned int instLine = cDILoc.getLineNumber();
+          StringRef    instFilename = cDILoc.getFilename();
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#endif
+
         /* Either we couldn't figure out our location or the location is
          * not whitelisted, so we skip instrumentation. */
         if (!instrumentBlock) continue;
@@ -273,13 +328,19 @@ bool AFLCoverage::runOnModule(Module &M) {
       // result: a little more speed and less map pollution
       int more_than_one = -1;
       // fprintf(stderr, "BB %u: ", cur_loc);
-      for (BasicBlock *Pred : predecessors(&BB)) {
+      for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); PI != E;
+           ++PI) {
+
+        BasicBlock *Pred = *PI;
 
         int count = 0;
         if (more_than_one == -1) more_than_one = 0;
         // fprintf(stderr, " %p=>", Pred);
 
-        for (BasicBlock *Succ : successors(Pred)) {
+        for (succ_iterator SI = succ_begin(Pred), E = succ_end(Pred); SI != E;
+             ++SI) {
+
+          BasicBlock *Succ = *SI;
 
           // if (count > 0)
           //  fprintf(stderr, "|");
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
index 0ccce875..e1332a9d 100644
--- a/llvm_mode/compare-transform-pass.so.cc
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -18,6 +18,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <list>
+#include <string>
+#include <fstream>
+#include <sys/time.h>
+#include "llvm/Config/llvm-config.h"
+
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LegacyPassManager.h"
@@ -26,10 +32,19 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/Verifier.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
 
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
+#include "llvm/IR/Verifier.h"
+#include "llvm/IR/DebugInfo.h"
+#else
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/DebugInfo.h"
+#define nullptr 0
+#endif
+
 #include <set>
 
 using namespace llvm;
@@ -42,6 +57,23 @@ class CompareTransform : public ModulePass {
   static char ID;
   CompareTransform() : ModulePass(ID) {
 
+    char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST");
+    if (instWhiteListFilename) {
+
+      std::string   line;
+      std::ifstream fileStream;
+      fileStream.open(instWhiteListFilename);
+      if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST");
+      getline(fileStream, line);
+      while (fileStream) {
+
+        myWhitelist.push_back(line);
+        getline(fileStream, line);
+
+      }
+
+    }
+
   }
 
   bool runOnModule(Module &M) override;
@@ -57,6 +89,9 @@ class CompareTransform : public ModulePass {
 
   }
 
+ protected:
+  std::list<std::string> myWhitelist;
+
  private:
   bool transformCmps(Module &M, const bool processStrcmp,
                      const bool processMemcmp, const bool processStrncmp,
@@ -89,7 +124,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
       c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty
 #if LLVM_VERSION_MAJOR < 5
                                 ,
-                                nullptr
+                                NULL
 #endif
       );
 #if LLVM_VERSION_MAJOR < 9
@@ -104,6 +139,117 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 
     for (auto &BB : F) {
 
+      if (!myWhitelist.empty()) {
+
+        BasicBlock::iterator IP = BB.getFirstInsertionPt();
+
+        bool instrumentBlock = false;
+
+        /* Get the current location using debug information.
+         * For now, just instrument the block if we are not able
+         * to determine our location. */
+        DebugLoc Loc = IP->getDebugLoc();
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
+        if (Loc) {
+
+          DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+
+          unsigned int instLine = cDILoc->getLine();
+          StringRef    instFilename = cDILoc->getFilename();
+
+          if (instFilename.str().empty()) {
+
+            /* If the original location is empty, try using the inlined location
+             */
+            DILocation *oDILoc = cDILoc->getInlinedAt();
+            if (oDILoc) {
+
+              instFilename = oDILoc->getFilename();
+              instLine = oDILoc->getLine();
+
+            }
+
+          }
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#else
+        if (!Loc.isUnknown()) {
+
+          DILocation cDILoc(Loc.getAsMDNode(C));
+
+          unsigned int instLine = cDILoc.getLineNumber();
+          StringRef    instFilename = cDILoc.getFilename();
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#endif
+
+        /* Either we couldn't figure out our location or the location is
+         * not whitelisted, so we skip instrumentation. */
+        if (!instrumentBlock) continue;
+
+      }
+
       for (auto &IN : BB) {
 
         CallInst *callInst = nullptr;
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc
index eeac4a55..e16993d6 100644
--- a/llvm_mode/split-compares-pass.so.cc
+++ b/llvm_mode/split-compares-pass.so.cc
@@ -15,15 +15,34 @@
  * limitations under the License.
  */
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <list>
+#include <string>
+#include <fstream>
+#include <sys/time.h>
+
+#include "llvm/Config/llvm-config.h"
+
 #include "llvm/Pass.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/Verifier.h"
 #include "llvm/IR/Module.h"
 
 #include "llvm/IR/IRBuilder.h"
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
+#include "llvm/IR/Verifier.h"
+#include "llvm/IR/DebugInfo.h"
+#else
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/DebugInfo.h"
+#define nullptr 0
+#endif
 
 using namespace llvm;
 
@@ -35,6 +54,41 @@ class SplitComparesTransform : public ModulePass {
   static char ID;
   SplitComparesTransform() : ModulePass(ID) {
 
+    char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST");
+    if (instWhiteListFilename) {
+
+      std::string   line;
+      std::ifstream fileStream;
+      fileStream.open(instWhiteListFilename);
+      if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST");
+      getline(fileStream, line);
+      while (fileStream) {
+
+        myWhitelist.push_back(line);
+        getline(fileStream, line);
+
+      }
+
+    }
+
+  }
+
+  static bool isBlacklisted(const Function *F) {
+
+    static const char *Blacklist[] = {
+
+        "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign."
+
+    };
+
+    for (auto const &BlacklistFunc : Blacklist) {
+
+      if (F->getName().startswith(BlacklistFunc)) { return true; }
+
+    }
+
+    return false;
+
   }
 
   bool runOnModule(Module &M) override;
@@ -49,6 +103,9 @@ class SplitComparesTransform : public ModulePass {
 
   }
 
+ protected:
+  std::list<std::string> myWhitelist;
+
  private:
   int enableFPSplit;
 
@@ -77,8 +134,121 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
    * all integer comparisons with >= and <= predicates to the icomps vector */
   for (auto &F : M) {
 
+    if (isBlacklisted(&F)) continue;
+
     for (auto &BB : F) {
 
+      if (!myWhitelist.empty()) {
+
+        bool instrumentBlock = false;
+
+        BasicBlock::iterator IP = BB.getFirstInsertionPt();
+
+        /* Get the current location using debug information.
+         * For now, just instrument the block if we are not able
+         * to determine our location. */
+        DebugLoc Loc = IP->getDebugLoc();
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
+        if (Loc) {
+
+          DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+
+          unsigned int instLine = cDILoc->getLine();
+          StringRef    instFilename = cDILoc->getFilename();
+
+          if (instFilename.str().empty()) {
+
+            /* If the original location is empty, try using the inlined location
+             */
+            DILocation *oDILoc = cDILoc->getInlinedAt();
+            if (oDILoc) {
+
+              instFilename = oDILoc->getFilename();
+              instLine = oDILoc->getLine();
+
+            }
+
+          }
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#else
+        if (!Loc.isUnknown()) {
+
+          DILocation cDILoc(Loc.getAsMDNode(C));
+
+          unsigned int instLine = cDILoc.getLineNumber();
+          StringRef    instFilename = cDILoc.getFilename();
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#endif
+
+        /* Either we couldn't figure out our location or the location is
+         * not whitelisted, so we skip instrumentation. */
+        if (!instrumentBlock) continue;
+
+      }
+
       for (auto &IN : BB) {
 
         CmpInst *selectcmpInst = nullptr;
@@ -165,7 +335,8 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
      * block bb it is now at the position where the old IcmpInst was */
     Instruction *icmp_np;
     icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_np);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             icmp_np);
 
     /* create a new basic block which holds the new EQ icmp */
     Instruction *icmp_eq;
@@ -230,7 +401,8 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
      * block bb it is now at the position where the old IcmpInst was */
     Instruction *fcmp_np;
     fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), fcmp_np);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             fcmp_np);
 
     /* create a new basic block which holds the new EQ fcmp */
     Instruction *fcmp_eq;
@@ -351,20 +523,21 @@ bool SplitComparesTransform::simplifyIntSignedness(Module &M) {
 
     s_op0 = BinaryOperator::Create(Instruction::LShr, op0,
                                    ConstantInt::get(IntType, bitw - 1));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op0);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), s_op0);
     t_op0 = new TruncInst(s_op0, Int1Ty);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), t_op0);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), t_op0);
 
     s_op1 = BinaryOperator::Create(Instruction::LShr, op1,
                                    ConstantInt::get(IntType, bitw - 1));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op1);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), s_op1);
     t_op1 = new TruncInst(s_op1, Int1Ty);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), t_op1);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), t_op1);
 
     /* compare of the sign bits */
     icmp_sign_bit =
         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_op0, t_op1);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_sign_bit);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             icmp_sign_bit);
 
     /* create a new basic block which is executed if the signedness bit is
      * different */
@@ -439,6 +612,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
   LLVMContext &C = M.getContext();
 
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 7)
   const DataLayout &dl = M.getDataLayout();
 
   /* define unions with floating point and (sign, exponent, mantissa)  triples
@@ -453,6 +628,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
   }
 
+#endif
+
   std::vector<CmpInst *> fcomps;
 
   /* get all EQ, NE, GT, and LT fcmps. if the other two
@@ -551,11 +728,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     Instruction *b_op0, *b_op1;
     b_op0 = CastInst::Create(Instruction::BitCast, op0,
                              IntegerType::get(C, op_size));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), b_op0);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), b_op0);
 
     b_op1 = CastInst::Create(Instruction::BitCast, op1,
                              IntegerType::get(C, op_size));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), b_op1);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), b_op1);
 
     /* isolate signs of value of floating point type */
 
@@ -566,21 +743,22 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     s_s0 =
         BinaryOperator::Create(Instruction::LShr, b_op0,
                                ConstantInt::get(b_op0->getType(), op_size - 1));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_s0);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), s_s0);
     t_s0 = new TruncInst(s_s0, Int1Ty);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), t_s0);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), t_s0);
 
     s_s1 =
         BinaryOperator::Create(Instruction::LShr, b_op1,
                                ConstantInt::get(b_op1->getType(), op_size - 1));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_s1);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), s_s1);
     t_s1 = new TruncInst(s_s1, Int1Ty);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), t_s1);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), t_s1);
 
     /* compare of the sign bits */
     icmp_sign_bit =
         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_sign_bit);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             icmp_sign_bit);
 
     /* create a new basic block which is executed if the signedness bits are
      * equal */
@@ -612,16 +790,16 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         Instruction::LShr, b_op1,
         ConstantInt::get(b_op1->getType(), shiftR_exponent));
     signequal_bb->getInstList().insert(
-        signequal_bb->getTerminator()->getIterator(), s_e0);
+        BasicBlock::iterator(signequal_bb->getTerminator()), s_e0);
     signequal_bb->getInstList().insert(
-        signequal_bb->getTerminator()->getIterator(), s_e1);
+        BasicBlock::iterator(signequal_bb->getTerminator()), s_e1);
 
     t_e0 = new TruncInst(s_e0, IntExponentTy);
     t_e1 = new TruncInst(s_e1, IntExponentTy);
     signequal_bb->getInstList().insert(
-        signequal_bb->getTerminator()->getIterator(), t_e0);
+        BasicBlock::iterator(signequal_bb->getTerminator()), t_e0);
     signequal_bb->getInstList().insert(
-        signequal_bb->getTerminator()->getIterator(), t_e1);
+        BasicBlock::iterator(signequal_bb->getTerminator()), t_e1);
 
     if (sizeInBits - precision < exTySizeBytes * 8) {
 
@@ -632,9 +810,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
           Instruction::And, t_e1,
           ConstantInt::get(t_e1->getType(), mask_exponent));
       signequal_bb->getInstList().insert(
-          signequal_bb->getTerminator()->getIterator(), m_e0);
+          BasicBlock::iterator(signequal_bb->getTerminator()), m_e0);
       signequal_bb->getInstList().insert(
-          signequal_bb->getTerminator()->getIterator(), m_e1);
+          BasicBlock::iterator(signequal_bb->getTerminator()), m_e1);
 
     } else {
 
@@ -662,7 +840,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         icmp_exponent =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
         signequal_bb->getInstList().insert(
-            signequal_bb->getTerminator()->getIterator(), icmp_exponent);
+            BasicBlock::iterator(signequal_bb->getTerminator()), icmp_exponent);
         icmp_exponent_result =
             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
         break;
@@ -671,7 +849,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         icmp_exponent =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
         signequal_bb->getInstList().insert(
-            signequal_bb->getTerminator()->getIterator(), icmp_exponent);
+            BasicBlock::iterator(signequal_bb->getTerminator()), icmp_exponent);
         icmp_exponent_result =
             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
         break;
@@ -680,7 +858,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     }
 
     signequal_bb->getInstList().insert(
-        signequal_bb->getTerminator()->getIterator(), icmp_exponent_result);
+        BasicBlock::iterator(signequal_bb->getTerminator()),
+        icmp_exponent_result);
 
     {
 
@@ -704,19 +883,19 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
       m_f1 = BinaryOperator::Create(
           Instruction::And, b_op1,
           ConstantInt::get(b_op1->getType(), mask_fraction));
-      middle_bb->getInstList().insert(middle_bb->getTerminator()->getIterator(),
-                                      m_f0);
-      middle_bb->getInstList().insert(middle_bb->getTerminator()->getIterator(),
-                                      m_f1);
+      middle_bb->getInstList().insert(
+          BasicBlock::iterator(middle_bb->getTerminator()), m_f0);
+      middle_bb->getInstList().insert(
+          BasicBlock::iterator(middle_bb->getTerminator()), m_f1);
 
       if (needTrunc) {
 
         t_f0 = new TruncInst(m_f0, IntFractionTy);
         t_f1 = new TruncInst(m_f1, IntFractionTy);
         middle_bb->getInstList().insert(
-            middle_bb->getTerminator()->getIterator(), t_f0);
+            BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
         middle_bb->getInstList().insert(
-            middle_bb->getTerminator()->getIterator(), t_f1);
+            BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
 
       } else {
 
@@ -732,9 +911,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         t_f0 = new TruncInst(b_op0, IntFractionTy);
         t_f1 = new TruncInst(b_op1, IntFractionTy);
         middle_bb->getInstList().insert(
-            middle_bb->getTerminator()->getIterator(), t_f0);
+            BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
         middle_bb->getInstList().insert(
-            middle_bb->getTerminator()->getIterator(), t_f1);
+            BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
 
       } else {
 
@@ -764,7 +943,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         icmp_fraction =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
         middle_bb->getInstList().insert(
-            middle_bb->getTerminator()->getIterator(), icmp_fraction);
+            BasicBlock::iterator(middle_bb->getTerminator()), icmp_fraction);
         icmp_fraction_result =
             BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
         break;
@@ -773,7 +952,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         icmp_fraction =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
         middle_bb->getInstList().insert(
-            middle_bb->getTerminator()->getIterator(), icmp_fraction);
+            BasicBlock::iterator(middle_bb->getTerminator()), icmp_fraction);
         icmp_fraction_result =
             BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
         break;
@@ -781,8 +960,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
     }
 
-    middle_bb->getInstList().insert(middle_bb->getTerminator()->getIterator(),
-                                    icmp_fraction_result);
+    middle_bb->getInstList().insert(
+        BasicBlock::iterator(middle_bb->getTerminator()), icmp_fraction_result);
 
     PHINode *PN = PHINode::Create(Int1Ty, 3, "");
 
@@ -919,18 +1098,21 @@ size_t SplitComparesTransform::splitIntCompares(Module &M, unsigned bitw) {
 
     s_op0 = BinaryOperator::Create(Instruction::LShr, op0,
                                    ConstantInt::get(OldIntType, bitw / 2));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op0);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), s_op0);
     op0_high = new TruncInst(s_op0, NewIntType);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), op0_high);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             op0_high);
 
     s_op1 = BinaryOperator::Create(Instruction::LShr, op1,
                                    ConstantInt::get(OldIntType, bitw / 2));
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op1);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), s_op1);
     op1_high = new TruncInst(s_op1, NewIntType);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), op1_high);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             op1_high);
 
     icmp_high = CmpInst::Create(Instruction::ICmp, pred, op0_high, op1_high);
-    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_high);
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             icmp_high);
 
     /* now we have to destinguish between == != and > < */
     if (pred == CmpInst::ICMP_EQ || pred == CmpInst::ICMP_NE) {
@@ -1076,13 +1258,19 @@ bool SplitComparesTransform::runOnModule(Module &M) {
              << "bit: " << splitIntCompares(M, bitw) << " splitted\n";
 
       bitw >>= 1;
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 7)
       [[clang::fallthrough]]; /*FALLTHRU*/                   /* FALLTHROUGH */
+#endif
     case 32:
       errs() << "Split-integer-compare-pass " << bitw
              << "bit: " << splitIntCompares(M, bitw) << " splitted\n";
 
       bitw >>= 1;
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 7)
       [[clang::fallthrough]]; /*FALLTHRU*/                   /* FALLTHROUGH */
+#endif
     case 16:
       errs() << "Split-integer-compare-pass " << bitw
              << "bit: " << splitIntCompares(M, bitw) << " splitted\n";
diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc
index 2743a71a..9101dc26 100644
--- a/llvm_mode/split-switches-pass.so.cc
+++ b/llvm_mode/split-switches-pass.so.cc
@@ -18,6 +18,13 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <list>
+#include <string>
+#include <fstream>
+#include <sys/time.h>
+
+#include "llvm/Config/llvm-config.h"
+
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LegacyPassManager.h"
@@ -26,10 +33,20 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/Verifier.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
 
+#include "llvm/IR/IRBuilder.h"
+#if LLVM_VERSION_MAJOR > 3 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
+#include "llvm/IR/Verifier.h"
+#include "llvm/IR/DebugInfo.h"
+#else
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/DebugInfo.h"
+#define nullptr 0
+#endif
+
 #include <set>
 
 using namespace llvm;
@@ -42,6 +59,41 @@ class SplitSwitchesTransform : public ModulePass {
   static char ID;
   SplitSwitchesTransform() : ModulePass(ID) {
 
+    char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST");
+    if (instWhiteListFilename) {
+
+      std::string   line;
+      std::ifstream fileStream;
+      fileStream.open(instWhiteListFilename);
+      if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST");
+      getline(fileStream, line);
+      while (fileStream) {
+
+        myWhitelist.push_back(line);
+        getline(fileStream, line);
+
+      }
+
+    }
+
+  }
+
+  static bool isBlacklisted(const Function *F) {
+
+    static const char *Blacklist[] = {
+
+        "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign."
+
+    };
+
+    for (auto const &BlacklistFunc : Blacklist) {
+
+      if (F->getName().startswith(BlacklistFunc)) { return true; }
+
+    }
+
+    return false;
+
   }
 
   bool runOnModule(Module &M) override;
@@ -71,6 +123,9 @@ class SplitSwitchesTransform : public ModulePass {
 
   typedef std::vector<CaseExpr> CaseVector;
 
+ protected:
+  std::list<std::string> myWhitelist;
+
  private:
   bool        splitSwitches(Module &M);
   bool        transformCmps(Module &M, const bool processStrcmp,
@@ -96,7 +151,7 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
   IntegerType *        ByteType = IntegerType::get(OrigBlock->getContext(), 8);
   unsigned             BytesInValue = bytesChecked.size();
   std::vector<uint8_t> setSizes;
-  std::vector<std::set<uint8_t>> byteSets(BytesInValue, std::set<uint8_t>());
+  std::vector<std::set<uint8_t> > byteSets(BytesInValue, std::set<uint8_t>());
 
   assert(ValTypeBitWidth >= 8 && ValTypeBitWidth <= 64);
 
@@ -169,8 +224,25 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
     NewNode->getInstList().push_back(Comp);
 
     bytesChecked[smallestIndex] = true;
-    if (std::all_of(bytesChecked.begin(), bytesChecked.end(),
-                    [](bool b) { return b; })) {
+    bool allBytesAreChecked = true;
+
+    for (std::vector<bool>::iterator BCI = bytesChecked.begin(),
+                                     E = bytesChecked.end();
+         BCI != E; ++BCI) {
+
+      if (!*BCI) {
+
+        allBytesAreChecked = false;
+        break;
+
+      }
+
+    }
+
+    //    if (std::all_of(bytesChecked.begin(), bytesChecked.end(),
+    //                    [](bool b) { return b; })) {
+
+    if (allBytesAreChecked) {
 
       assert(Cases.size() == 1);
       BranchInst::Create(Cases[0].BB, NewDefault, Comp, NewNode);
@@ -262,16 +334,132 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
 
 bool SplitSwitchesTransform::splitSwitches(Module &M) {
 
+#if (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7)
+  LLVMContext &C = M.getContext();
+#endif
+
   std::vector<SwitchInst *> switches;
 
   /* iterate over all functions, bbs and instruction and add
    * all switches to switches vector for later processing */
   for (auto &F : M) {
 
+    if (isBlacklisted(&F)) continue;
+
     for (auto &BB : F) {
 
       SwitchInst *switchInst = nullptr;
 
+      if (!myWhitelist.empty()) {
+
+        bool                 instrumentBlock = false;
+        BasicBlock::iterator IP = BB.getFirstInsertionPt();
+
+        /* Get the current location using debug information.
+         * For now, just instrument the block if we are not able
+         * to determine our location. */
+        DebugLoc Loc = IP->getDebugLoc();
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
+        if (Loc) {
+
+          DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+
+          unsigned int instLine = cDILoc->getLine();
+          StringRef    instFilename = cDILoc->getFilename();
+
+          if (instFilename.str().empty()) {
+
+            /* If the original location is empty, try using the inlined location
+             */
+            DILocation *oDILoc = cDILoc->getInlinedAt();
+            if (oDILoc) {
+
+              instFilename = oDILoc->getFilename();
+              instLine = oDILoc->getLine();
+
+            }
+
+          }
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#else
+        if (!Loc.isUnknown()) {
+
+          DILocation cDILoc(Loc.getAsMDNode(C));
+
+          unsigned int instLine = cDILoc.getLineNumber();
+          StringRef    instFilename = cDILoc.getFilename();
+
+          (void)instLine;
+
+          /* Continue only if we know where we actually are */
+          if (!instFilename.str().empty()) {
+
+            for (std::list<std::string>::iterator it = myWhitelist.begin();
+                 it != myWhitelist.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. */
+              if (instFilename.str().length() >= it->length()) {
+
+                if (instFilename.str().compare(
+                        instFilename.str().length() - it->length(),
+                        it->length(), *it) == 0) {
+
+                  instrumentBlock = true;
+                  break;
+
+                }
+
+              }
+
+            }
+
+          }
+
+        }
+
+#endif
+
+        /* Either we couldn't figure out our location or the location is
+         * not whitelisted, so we skip instrumentation. */
+        if (!instrumentBlock) continue;
+
+      }
+
       if ((switchInst = dyn_cast<SwitchInst>(BB.getTerminator()))) {
 
         if (switchInst->getNumCases() < 1) continue;
@@ -313,8 +501,7 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
      * if the default block is set as an unreachable we avoid creating one
      * because will never be a valid target.*/
     BasicBlock *NewDefault = nullptr;
-    NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault");
-    NewDefault->insertInto(F, Default);
+    NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault", F, Default);
     BranchInst::Create(Default, NewDefault);
 
     /* Prepare cases vector. */