about summary refs log tree commit diff
path: root/instrumentation
diff options
context:
space:
mode:
Diffstat (limited to 'instrumentation')
-rw-r--r--instrumentation/LLVMInsTrim.so.cc599
-rw-r--r--instrumentation/MarkNodes.cc481
-rw-r--r--instrumentation/MarkNodes.h12
-rw-r--r--instrumentation/README.instrim.md30
-rw-r--r--instrumentation/README.llvm.md26
-rw-r--r--instrumentation/README.neverzero.md14
-rw-r--r--instrumentation/README.snapshot.md2
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc50
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc135
-rw-r--r--instrumentation/afl-compiler-rt.o.c27
-rw-r--r--instrumentation/afl-gcc-pass.so.cc4
-rw-r--r--instrumentation/afl-llvm-common.cc7
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc5
-rw-r--r--instrumentation/afl-llvm-lto-instrumentation.so.cc47
-rw-r--r--instrumentation/afl-llvm-pass.so.cc234
-rw-r--r--instrumentation/split-switches-pass.so.cc2
16 files changed, 392 insertions, 1283 deletions
diff --git a/instrumentation/LLVMInsTrim.so.cc b/instrumentation/LLVMInsTrim.so.cc
deleted file mode 100644
index 62de6ec5..00000000
--- a/instrumentation/LLVMInsTrim.so.cc
+++ /dev/null
@@ -1,599 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#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"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/BasicBlock.h"
-#include <unordered_set>
-#include <random>
-#include <list>
-#include <string>
-#include <fstream>
-
-#include "MarkNodes.h"
-#include "afl-llvm-common.h"
-#include "llvm-alternative-coverage.h"
-
-#include "config.h"
-#include "debug.h"
-
-using namespace llvm;
-
-static cl::opt<bool> MarkSetOpt("markset", cl::desc("MarkSet"),
-                                cl::init(false));
-static cl::opt<bool> LoopHeadOpt("loophead", cl::desc("LoopHead"),
-                                 cl::init(false));
-
-namespace {
-
-struct InsTrim : public ModulePass {
-
- protected:
-  uint32_t function_minimum_size = 1;
-  char *   skip_nozero = NULL;
-
- private:
-  std::mt19937 generator;
-  int          total_instr = 0;
-
-  unsigned int genLabel() {
-
-    return generator() & (MAP_SIZE - 1);
-
-  }
-
- public:
-  static char ID;
-
-  InsTrim() : ModulePass(ID), generator(0) {
-
-    initInstrumentList();
-
-  }
-
-  void getAnalysisUsage(AnalysisUsage &AU) const override {
-
-    AU.addRequired<DominatorTreeWrapperPass>();
-
-  }
-
-#if LLVM_VERSION_MAJOR < 4
-  const char *
-#else
-  StringRef
-#endif
-  getPassName() const override {
-
-    return "InstTrim Instrumentation";
-
-  }
-
-#if LLVM_VERSION_MAJOR > 4 || \
-    (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
-  #define AFL_HAVE_VECTOR_INTRINSICS 1
-#endif
-
-  bool runOnModule(Module &M) override {
-
-    setvbuf(stdout, NULL, _IONBF, 0);
-
-    if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
-
-      SAYF(cCYA "LLVMInsTrim" VERSION cRST " by csienslab\n");
-
-    } else
-
-      be_quiet = 1;
-
-    if (getenv("AFL_DEBUG") != NULL) debug = 1;
-
-    LLVMContext &C = M.getContext();
-
-    IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
-    IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
-
-#if LLVM_VERSION_MAJOR < 9
-    char *neverZero_counters_str;
-    if ((neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO")) != NULL)
-      if (!be_quiet) OKF("LLVM neverZero activated (by hexcoder)\n");
-#endif
-    skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
-
-    if (getenv("AFL_LLVM_INSTRIM_LOOPHEAD") != NULL ||
-        getenv("LOOPHEAD") != NULL) {
-
-      LoopHeadOpt = true;
-
-    }
-
-    unsigned int PrevLocSize = 0;
-    char *       ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
-    if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
-    char *caller_str = getenv("AFL_LLVM_CALLER");
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    unsigned int ngram_size = 0;
-    /* Decide previous location vector size (must be a power of two) */
-    VectorType *PrevLocTy = NULL;
-
-    if (ngram_size_str)
-      if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
-          ngram_size > NGRAM_SIZE_MAX)
-        FATAL(
-            "Bad value of AFL_NGRAM_SIZE (must be between 2 and NGRAM_SIZE_MAX "
-            "(%u))",
-            NGRAM_SIZE_MAX);
-
-    if (ngram_size)
-      PrevLocSize = ngram_size - 1;
-    else
-#else
-    if (ngram_size_str)
-  #ifdef LLVM_VERSION_STRING
-      FATAL(
-          "Sorry, NGRAM branch coverage is not supported with llvm version %s!",
-          LLVM_VERSION_STRING);
-  #else
-    #ifndef LLVM_VERSION_PATCH
-      FATAL(
-          "Sorry, NGRAM branch coverage is not supported with llvm version "
-          "%d.%d.%d!",
-          LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, 0);
-    #else
-      FATAL(
-          "Sorry, NGRAM branch coverage is not supported with llvm version "
-          "%d.%d.%d!",
-          LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, LLVM_VERISON_PATCH);
-    #endif
-  #endif
-#endif
-      PrevLocSize = 1;
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    // IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
-    int          PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
-    IntegerType *IntLocTy =
-        IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT);
-    if (ngram_size)
-      PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize
-  #if LLVM_VERSION_MAJOR >= 12
-                                  ,
-                                  false
-  #endif
-      );
-#endif
-
-    /* Get globals for the SHM region and the previous location. Note that
-       __afl_prev_loc is thread-local. */
-
-    GlobalVariable *AFLMapPtr =
-        new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
-                           GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
-    GlobalVariable *AFLPrevLoc;
-    GlobalVariable *AFLContext = NULL;
-    LoadInst *      PrevCaller = NULL;  // for CALLER sensitive coverage
-
-    if (caller_str)
-#if defined(__ANDROID__) || defined(__HAIKU__)
-      AFLContext = new GlobalVariable(
-          M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
-#else
-      AFLContext = new GlobalVariable(
-          M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx",
-          0, GlobalVariable::GeneralDynamicTLSModel, 0, false);
-#endif
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    if (ngram_size)
-  #if defined(__ANDROID__) || defined(__HAIKU__)
-      AFLPrevLoc = new GlobalVariable(
-          M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
-          /* Initializer */ nullptr, "__afl_prev_loc");
-  #else
-      AFLPrevLoc = new GlobalVariable(
-          M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
-          /* Initializer */ nullptr, "__afl_prev_loc",
-          /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel,
-          /* AddressSpace */ 0, /* IsExternallyInitialized */ false);
-  #endif
-    else
-#endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
-      AFLPrevLoc = new GlobalVariable(
-          M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
-#else
-    AFLPrevLoc = new GlobalVariable(
-        M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
-        GlobalVariable::GeneralDynamicTLSModel, 0, false);
-#endif
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-    /* Create the vector shuffle mask for updating the previous block history.
-       Note that the first element of the vector will store cur_loc, so just set
-       it to undef to allow the optimizer to do its thing. */
-
-    SmallVector<Constant *, 32> PrevLocShuffle = {UndefValue::get(Int32Ty)};
-
-    for (unsigned I = 0; I < PrevLocSize - 1; ++I)
-      PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
-
-    for (int I = PrevLocSize; I < PrevLocVecSize; ++I)
-      PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
-
-    Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
-#endif
-
-    // this is our default
-    MarkSetOpt = true;
-
-    ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
-    ConstantInt *One = ConstantInt::get(Int8Ty, 1);
-
-    u64 total_rs = 0;
-    u64 total_hs = 0;
-
-    scanForDangerousFunctions(&M);
-
-    for (Function &F : M) {
-
-      if (debug) {
-
-        uint32_t bb_cnt = 0;
-
-        for (auto &BB : F)
-          if (BB.size() > 0) ++bb_cnt;
-        DEBUGF("Function %s size %zu %u\n", F.getName().str().c_str(), F.size(),
-               bb_cnt);
-
-      }
-
-      if (!isInInstrumentList(&F)) continue;
-
-      // if the function below our minimum size skip it (1 or 2)
-      if (F.size() < function_minimum_size) { continue; }
-
-      std::unordered_set<BasicBlock *> MS;
-      if (!MarkSetOpt) {
-
-        for (auto &BB : F) {
-
-          MS.insert(&BB);
-
-        }
-
-        total_rs += F.size();
-
-      } else {
-
-        auto Result = markNodes(&F);
-        auto RS = Result.first;
-        auto HS = Result.second;
-
-        MS.insert(RS.begin(), RS.end());
-        if (!LoopHeadOpt) {
-
-          MS.insert(HS.begin(), HS.end());
-          total_rs += MS.size();
-
-        } else {
-
-          DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeSet;
-          DominatorTreeWrapperPass *                      DTWP =
-              &getAnalysis<DominatorTreeWrapperPass>(F);
-          auto DT = &DTWP->getDomTree();
-
-          total_rs += RS.size();
-          total_hs += HS.size();
-
-          for (BasicBlock *BB : HS) {
-
-            bool Inserted = false;
-            for (auto BI = pred_begin(BB), BE = pred_end(BB); BI != BE; ++BI) {
-
-              auto Edge = BasicBlockEdge(*BI, BB);
-              if (Edge.isSingleEdge() && DT->dominates(Edge, BB)) {
-
-                EdgeSet.insert({*BI, BB});
-                Inserted = true;
-                break;
-
-              }
-
-            }
-
-            if (!Inserted) {
-
-              MS.insert(BB);
-              total_rs += 1;
-              total_hs -= 1;
-
-            }
-
-          }
-
-          for (auto I = EdgeSet.begin(), E = EdgeSet.end(); I != E; ++I) {
-
-            auto PredBB = I->first;
-            auto SuccBB = I->second;
-            auto NewBB =
-                SplitBlockPredecessors(SuccBB, {PredBB}, ".split", DT, nullptr,
-#if LLVM_VERSION_MAJOR >= 8
-                                       nullptr,
-#endif
-                                       false);
-            MS.insert(NewBB);
-
-          }
-
-        }
-
-        for (BasicBlock &BB : F) {
-
-          if (MS.find(&BB) == MS.end()) { continue; }
-          IRBuilder<> IRB(&*BB.getFirstInsertionPt());
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-          if (ngram_size) {
-
-            LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
-            PrevLoc->setMetadata(M.getMDKindID("nosanitize"),
-                                 MDNode::get(C, None));
-
-            Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
-                PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask);
-            Value *UpdatedPrevLoc = IRB.CreateInsertElement(
-                ShuffledPrevLoc, ConstantInt::get(Int32Ty, genLabel()),
-                (uint64_t)0);
-
-            IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc)
-                ->setMetadata(M.getMDKindID("nosanitize"),
-                              MDNode::get(C, None));
-
-          } else
-
-#endif
-          {
-
-            IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), AFLPrevLoc);
-
-          }
-
-        }
-
-      }
-
-      int has_calls = 0;
-      for (BasicBlock &BB : F) {
-
-        auto         PI = pred_begin(&BB);
-        auto         PE = pred_end(&BB);
-        IRBuilder<>  IRB(&*BB.getFirstInsertionPt());
-        Value *      L = NULL;
-        unsigned int cur_loc;
-
-        // Context sensitive coverage
-        if (caller_str && &BB == &F.getEntryBlock()) {
-
-          PrevCaller = IRB.CreateLoad(AFLContext);
-          PrevCaller->setMetadata(M.getMDKindID("nosanitize"),
-                                  MDNode::get(C, None));
-
-          // does the function have calls? and is any of the calls larger than
-          // one basic block?
-          has_calls = 0;
-          for (auto &BB2 : F) {
-
-            if (has_calls) break;
-            for (auto &IN : BB2) {
-
-              CallInst *callInst = nullptr;
-              if ((callInst = dyn_cast<CallInst>(&IN))) {
-
-                Function *Callee = callInst->getCalledFunction();
-                if (!Callee || Callee->size() < function_minimum_size)
-                  continue;
-                else {
-
-                  has_calls = 1;
-                  break;
-
-                }
-
-              }
-
-            }
-
-          }
-
-          // if yes we store a context ID for this function in the global var
-          if (has_calls) {
-
-            ConstantInt *NewCtx = ConstantInt::get(Int32Ty, genLabel());
-            StoreInst *  StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
-            StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
-                                  MDNode::get(C, None));
-
-          }
-
-        }  // END of caller_str
-
-        if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; }
-
-        if (PI == PE) {
-
-          cur_loc = genLabel();
-          L = ConstantInt::get(Int32Ty, cur_loc);
-
-        } else {
-
-          auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
-          DenseMap<BasicBlock *, unsigned> PredMap;
-          for (PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
-
-            BasicBlock *PBB = *PI;
-            auto        It = PredMap.insert({PBB, genLabel()});
-            unsigned    Label = It.first->second;
-            // cur_loc = Label;
-            PN->addIncoming(ConstantInt::get(Int32Ty, Label), PBB);
-
-          }
-
-          L = PN;
-
-        }
-
-        /* Load prev_loc */
-        LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
-        PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-        Value *PrevLocTrans;
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-        /* "For efficiency, we propose to hash the tuple as a key into the
-           hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where
-           prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */
-
-        if (ngram_size)
-          PrevLocTrans =
-              IRB.CreateZExt(IRB.CreateXorReduce(PrevLoc), IRB.getInt32Ty());
-        else
-#endif
-          PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
-
-        if (caller_str)
-          PrevLocTrans =
-              IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCaller), Int32Ty);
-
-        /* Load SHM pointer */
-        LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
-        MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-        Value *MapPtrIdx;
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
-        if (ngram_size)
-          MapPtrIdx = IRB.CreateGEP(
-              MapPtr, IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, L), Int32Ty));
-        else
-#endif
-          MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, L));
-
-        /* Update bitmap */
-        LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
-        Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
-        Value *Incr = IRB.CreateAdd(Counter, One);
-
-#if LLVM_VERSION_MAJOR < 9
-        if (neverZero_counters_str !=
-            NULL)  // with llvm 9 we make this the default as the bug in llvm is
-                   // then fixed
-#else
-        if (!skip_nozero)
-#endif
-        {
-
-          /* hexcoder: Realize a counter that skips zero during overflow.
-           * Once this counter reaches its maximum value, it next increments to
-           * 1
-           *
-           * Instead of
-           * Counter + 1 -> Counter
-           * we inject now this
-           * Counter + 1 -> {Counter, OverflowFlag}
-           * Counter + OverflowFlag -> Counter
-           */
-          auto cf = IRB.CreateICmpEQ(Incr, Zero);
-          auto carry = IRB.CreateZExt(cf, Int8Ty);
-          Incr = IRB.CreateAdd(Incr, carry);
-
-        }
-
-        IRB.CreateStore(Incr, MapPtrIdx)
-            ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
-        if (caller_str && has_calls) {
-
-          // in CALLER mode we have to restore the original context for the
-          // caller - she might be calling other functions which need the
-          // correct CALLER
-          Instruction *Inst = BB.getTerminator();
-          if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
-
-            IRBuilder<> Post_IRB(Inst);
-            StoreInst * RestoreCtx =
-                Post_IRB.CreateStore(PrevCaller, AFLContext);
-            RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
-                                    MDNode::get(C, None));
-
-          }
-
-        }
-
-        total_instr++;
-
-      }
-
-    }
-
-    if (!be_quiet) {
-
-      char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
-               getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
-               getenv("AFL_USE_ASAN") ? ", ASAN" : "",
-               getenv("AFL_USE_MSAN") ? ", MSAN" : "",
-               getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
-               getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
-
-      OKF("Instrumented %d locations (%llu, %llu) (%s mode)\n", total_instr,
-          total_rs, total_hs, modeline);
-
-    }
-
-    return false;
-
-  }
-
-};  // end of struct InsTrim
-
-}  // end of anonymous namespace
-
-char InsTrim::ID = 0;
-
-static void registerAFLPass(const PassManagerBuilder &,
-                            legacy::PassManagerBase &PM) {
-
-  PM.add(new InsTrim());
-
-}
-
-static RegisterStandardPasses RegisterAFLPass(
-    PassManagerBuilder::EP_OptimizerLast, registerAFLPass);
-
-static RegisterStandardPasses RegisterAFLPass0(
-    PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);
-
diff --git a/instrumentation/MarkNodes.cc b/instrumentation/MarkNodes.cc
deleted file mode 100644
index b77466d9..00000000
--- a/instrumentation/MarkNodes.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-#include <algorithm>
-#include <map>
-#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"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-DenseMap<BasicBlock *, uint32_t>    LMap;
-std::vector<BasicBlock *>           Blocks;
-std::set<uint32_t>                  Marked, Markabove;
-std::vector<std::vector<uint32_t> > Succs, Preds;
-
-void reset() {
-
-  LMap.clear();
-  Blocks.clear();
-  Marked.clear();
-  Markabove.clear();
-
-}
-
-uint32_t start_point;
-
-void labelEachBlock(Function *F) {
-
-  // Fake single endpoint;
-  LMap[NULL] = Blocks.size();
-  Blocks.push_back(NULL);
-
-  // Assign the unique LabelID to each block;
-  for (auto I = F->begin(), E = F->end(); I != E; ++I) {
-
-    BasicBlock *BB = &*I;
-    LMap[BB] = Blocks.size();
-    Blocks.push_back(BB);
-
-  }
-
-  start_point = LMap[&F->getEntryBlock()];
-
-}
-
-void buildCFG(Function *F) {
-
-  Succs.resize(Blocks.size());
-  Preds.resize(Blocks.size());
-  for (size_t i = 0; i < Succs.size(); i++) {
-
-    Succs[i].clear();
-    Preds[i].clear();
-
-  }
-
-  for (auto S = F->begin(), E = F->end(); S != E; ++S) {
-
-    BasicBlock *BB = &*S;
-    uint32_t    MyID = LMap[BB];
-
-    for (auto I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
-
-      Succs[MyID].push_back(LMap[*I]);
-
-    }
-
-  }
-
-}
-
-std::vector<std::vector<uint32_t> > tSuccs;
-std::vector<bool>                   tag, indfs;
-
-void DFStree(size_t now_id) {
-
-  if (tag[now_id]) return;
-  tag[now_id] = true;
-  indfs[now_id] = true;
-  for (auto succ : tSuccs[now_id]) {
-
-    if (tag[succ] and indfs[succ]) {
-
-      Marked.insert(succ);
-      Markabove.insert(succ);
-      continue;
-
-    }
-
-    Succs[now_id].push_back(succ);
-    Preds[succ].push_back(now_id);
-    DFStree(succ);
-
-  }
-
-  indfs[now_id] = false;
-
-}
-
-void turnCFGintoDAG() {
-
-  tSuccs = Succs;
-  tag.resize(Blocks.size());
-  indfs.resize(Blocks.size());
-  for (size_t i = 0; i < Blocks.size(); ++i) {
-
-    Succs[i].clear();
-    tag[i] = false;
-    indfs[i] = false;
-
-  }
-
-  DFStree(start_point);
-  for (size_t i = 0; i < Blocks.size(); ++i)
-    if (Succs[i].empty()) {
-
-      Succs[i].push_back(0);
-      Preds[0].push_back(i);
-
-    }
-
-}
-
-uint32_t timeStamp;
-namespace DominatorTree {
-
-std::vector<std::vector<uint32_t> > cov;
-std::vector<uint32_t>               dfn, nfd, par, sdom, idom, mom, mn;
-
-bool Compare(uint32_t u, uint32_t v) {
-
-  return dfn[u] < dfn[v];
-
-}
-
-uint32_t eval(uint32_t u) {
-
-  if (mom[u] == u) return u;
-  uint32_t res = eval(mom[u]);
-  if (Compare(sdom[mn[mom[u]]], sdom[mn[u]])) { mn[u] = mn[mom[u]]; }
-  return mom[u] = res;
-
-}
-
-void DFS(uint32_t now) {
-
-  timeStamp += 1;
-  dfn[now] = timeStamp;
-  nfd[timeStamp - 1] = now;
-  for (auto succ : Succs[now]) {
-
-    if (dfn[succ] == 0) {
-
-      par[succ] = now;
-      DFS(succ);
-
-    }
-
-  }
-
-}
-
-void DominatorTree() {
-
-  if (Blocks.empty()) return;
-  uint32_t s = start_point;
-
-  // Initialization
-  mn.resize(Blocks.size());
-  cov.resize(Blocks.size());
-  dfn.resize(Blocks.size());
-  nfd.resize(Blocks.size());
-  par.resize(Blocks.size());
-  mom.resize(Blocks.size());
-  sdom.resize(Blocks.size());
-  idom.resize(Blocks.size());
-
-  for (uint32_t i = 0; i < Blocks.size(); i++) {
-
-    dfn[i] = 0;
-    nfd[i] = Blocks.size();
-    cov[i].clear();
-    idom[i] = mom[i] = mn[i] = sdom[i] = i;
-
-  }
-
-  timeStamp = 0;
-  DFS(s);
-
-  for (uint32_t i = Blocks.size() - 1; i >= 1u; i--) {
-
-    uint32_t now = nfd[i];
-    if (now == Blocks.size()) { continue; }
-    for (uint32_t pre : Preds[now]) {
-
-      if (dfn[pre]) {
-
-        eval(pre);
-        if (Compare(sdom[mn[pre]], sdom[now])) { sdom[now] = sdom[mn[pre]]; }
-
-      }
-
-    }
-
-    cov[sdom[now]].push_back(now);
-    mom[now] = par[now];
-    for (uint32_t x : cov[par[now]]) {
-
-      eval(x);
-      if (Compare(sdom[mn[x]], par[now])) {
-
-        idom[x] = mn[x];
-
-      } else {
-
-        idom[x] = par[now];
-
-      }
-
-    }
-
-  }
-
-  for (uint32_t i = 1; i < Blocks.size(); i += 1) {
-
-    uint32_t now = nfd[i];
-    if (now == Blocks.size()) { continue; }
-    if (idom[now] != sdom[now]) idom[now] = idom[idom[now]];
-
-  }
-
-}
-
-}  // namespace DominatorTree
-
-std::vector<uint32_t>               Visited, InStack;
-std::vector<uint32_t>               TopoOrder, InDeg;
-std::vector<std::vector<uint32_t> > t_Succ, t_Pred;
-
-void Go(uint32_t now, uint32_t tt) {
-
-  if (now == tt) return;
-  Visited[now] = InStack[now] = timeStamp;
-
-  for (uint32_t nxt : Succs[now]) {
-
-    if (Visited[nxt] == timeStamp and InStack[nxt] == timeStamp) {
-
-      Marked.insert(nxt);
-
-    }
-
-    t_Succ[now].push_back(nxt);
-    t_Pred[nxt].push_back(now);
-    InDeg[nxt] += 1;
-    if (Visited[nxt] == timeStamp) { continue; }
-    Go(nxt, tt);
-
-  }
-
-  InStack[now] = 0;
-
-}
-
-void TopologicalSort(uint32_t ss, uint32_t tt) {
-
-  timeStamp += 1;
-
-  Go(ss, tt);
-
-  TopoOrder.clear();
-  std::queue<uint32_t> wait;
-  wait.push(ss);
-  while (not wait.empty()) {
-
-    uint32_t now = wait.front();
-    wait.pop();
-    TopoOrder.push_back(now);
-    for (uint32_t nxt : t_Succ[now]) {
-
-      InDeg[nxt] -= 1;
-      if (InDeg[nxt] == 0u) { wait.push(nxt); }
-
-    }
-
-  }
-
-}
-
-std::vector<std::set<uint32_t> > NextMarked;
-bool                             Indistinguish(uint32_t node1, uint32_t node2) {
-
-  if (NextMarked[node1].size() > NextMarked[node2].size()) {
-
-    uint32_t _swap = node1;
-    node1 = node2;
-    node2 = _swap;
-
-  }
-
-  for (uint32_t x : NextMarked[node1]) {
-
-    if (NextMarked[node2].find(x) != NextMarked[node2].end()) { return true; }
-
-  }
-
-  return false;
-
-}
-
-void MakeUniq(uint32_t now) {
-
-  if (Marked.find(now) == Marked.end()) {
-
-    for (uint32_t pred1 : t_Pred[now]) {
-
-      bool StopFlag = false;
-      for (uint32_t pred2 : t_Pred[now]) {
-
-        if (pred1 == pred2) continue;
-        if (Indistinguish(pred1, pred2)) {
-
-          Marked.insert(now);
-          StopFlag = true;
-          break;
-
-        }
-
-      }
-
-      if (StopFlag) { break; }
-
-    }
-
-  }
-
-  if (Marked.find(now) != Marked.end()) {
-
-    NextMarked[now].insert(now);
-
-  } else {
-
-    for (uint32_t pred : t_Pred[now]) {
-
-      for (uint32_t x : NextMarked[pred]) {
-
-        NextMarked[now].insert(x);
-
-      }
-
-    }
-
-  }
-
-}
-
-bool MarkSubGraph(uint32_t ss, uint32_t tt) {
-
-  TopologicalSort(ss, tt);
-  if (TopoOrder.empty()) return false;
-
-  for (uint32_t i : TopoOrder) {
-
-    NextMarked[i].clear();
-
-  }
-
-  NextMarked[TopoOrder[0]].insert(TopoOrder[0]);
-  for (uint32_t i = 1; i < TopoOrder.size(); i += 1) {
-
-    MakeUniq(TopoOrder[i]);
-
-  }
-
-  // Check if there is an empty path.
-  if (NextMarked[tt].count(TopoOrder[0]) > 0) return true;
-  return false;
-
-}
-
-void MarkVertice() {
-
-  uint32_t s = start_point;
-
-  InDeg.resize(Blocks.size());
-  Visited.resize(Blocks.size());
-  InStack.resize(Blocks.size());
-  t_Succ.resize(Blocks.size());
-  t_Pred.resize(Blocks.size());
-  NextMarked.resize(Blocks.size());
-
-  for (uint32_t i = 0; i < Blocks.size(); i += 1) {
-
-    Visited[i] = InStack[i] = InDeg[i] = 0;
-    t_Succ[i].clear();
-    t_Pred[i].clear();
-
-  }
-
-  timeStamp = 0;
-  uint32_t t = 0;
-  bool     emptyPathExists = true;
-
-  while (s != t) {
-
-    emptyPathExists &= MarkSubGraph(DominatorTree::idom[t], t);
-    t = DominatorTree::idom[t];
-
-  }
-
-  if (emptyPathExists) {
-
-    // Mark all exit blocks to catch the empty path.
-    Marked.insert(t_Pred[0].begin(), t_Pred[0].end());
-
-  }
-
-}
-
-// return {marked nodes}
-std::pair<std::vector<BasicBlock *>, std::vector<BasicBlock *> > markNodes(
-    Function *F) {
-
-  assert(F->size() > 0 && "Function can not be empty");
-
-  reset();
-  labelEachBlock(F);
-  buildCFG(F);
-  turnCFGintoDAG();
-  DominatorTree::DominatorTree();
-  MarkVertice();
-
-  std::vector<BasicBlock *> Result, ResultAbove;
-  for (uint32_t x : Markabove) {
-
-    auto it = Marked.find(x);
-    if (it != Marked.end()) Marked.erase(it);
-    if (x) ResultAbove.push_back(Blocks[x]);
-
-  }
-
-  for (uint32_t x : Marked) {
-
-    if (x == 0) {
-
-      continue;
-
-    } else {
-
-      Result.push_back(Blocks[x]);
-
-    }
-
-  }
-
-  return {Result, ResultAbove};
-
-}
-
diff --git a/instrumentation/MarkNodes.h b/instrumentation/MarkNodes.h
deleted file mode 100644
index 8ddc978d..00000000
--- a/instrumentation/MarkNodes.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __MARK_NODES__
-#define __MARK_NODES__
-
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/Function.h"
-#include <vector>
-
-std::pair<std::vector<llvm::BasicBlock *>, std::vector<llvm::BasicBlock *>>
-markNodes(llvm::Function *F);
-
-#endif
-
diff --git a/instrumentation/README.instrim.md b/instrumentation/README.instrim.md
deleted file mode 100644
index 99f6477a..00000000
--- a/instrumentation/README.instrim.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# InsTrim
-
-InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing
-
-## Introduction
-
-InsTrim is the work of Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao and Shih-Kun Huang.
-
-It uses a CFG (call flow graph) and markers to instrument just what
-is necessary in the binary (ie less than llvm_mode). As a result the binary is
-about 10-15% faster compared to normal llvm_mode however with some coverage loss.
-It requires at least llvm version 3.8.0 to build.
-If you have LLVM 7+ we recommend PCGUARD instead.
-
-## Usage
-
-Set the environment variable `AFL_LLVM_INSTRUMENT=CFG` or `AFL_LLVM_INSTRIM=1`
-during compilation of the target.
-
-There is also special mode which instruments loops in a way so that
-afl-fuzz can see which loop path has been selected but not being able to
-see how often the loop has been rerun.
-This again is a tradeoff for speed for less path information.
-To enable this mode set `AFL_LLVM_INSTRIM_LOOPHEAD=1`.
-
-## Background
-
-The paper from Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao and Shih-Kun Huang:
-[InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing]
-(https://www.ndss-symposium.org/wp-content/uploads/2018/07/bar2018_14_Hsu_paper.pdf)
diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md
index 2705ce0d..8ce5afb9 100644
--- a/instrumentation/README.llvm.md
+++ b/instrumentation/README.llvm.md
@@ -2,11 +2,11 @@
 
   (See [../README.md](../README.md) for the general instruction manual.)
 
-  (See [README.gcc_plugon.md](../README.gcc_plugin.md) for the GCC-based instrumentation.)
+  (See [README.gcc_plugin.md](../README.gcc_plugin.md) for the GCC-based instrumentation.)
 
 ## 1) Introduction
 
-! llvm_mode works with llvm versions 3.4 up to 12 !
+! llvm_mode works with llvm versions 6.0 up to 12 !
 
 The code in this directory allows you to instrument programs for AFL using
 true compiler-level instrumentation, instead of the more crude
@@ -101,8 +101,7 @@ instrumentation by either setting `AFL_CC_COMPILER=LLVM` or pass the parameter
 The tool honors roughly the same environmental variables as afl-gcc (see
 [docs/env_variables.md](../docs/env_variables.md)). This includes AFL_USE_ASAN,
 AFL_HARDEN, and AFL_DONT_OPTIMIZE. However AFL_INST_RATIO is not honored
-as it does not serve a good purpose with the more effective PCGUARD, LTO and
- instrim CFG analysis.
+as it does not serve a good purpose with the more effective PCGUARD analysis.
 
 ## 3) Options
 
@@ -116,26 +115,20 @@ For splitting memcmp, strncmp, etc. please see [README.laf-intel.md](README.laf-
 
 Then there are different ways of instrumenting the target:
 
-1. There is an optimized instrumentation strategy that uses CFGs and
-markers to just instrument what is needed. This increases speed by 10-15%
-without any disadvantages
-If you want to use this, set AFL_LLVM_INSTRUMENT=CFG or AFL_LLVM_INSTRIM=1
-See [README.instrim.md](README.instrim.md)
-
-2. An even better instrumentation strategy uses LTO and link time
+1. An better instrumentation strategy uses LTO and link time
 instrumentation. Note that not all targets can compile in this mode, however
 if it works it is the best option you can use.
 Simply use afl-clang-lto/afl-clang-lto++ to use this option.
 See [README.lto.md](README.lto.md)
 
-3. Alternativly you can choose a completely different coverage method:
+2. Alternativly you can choose a completely different coverage method:
 
-3a. N-GRAM coverage - which combines the previous visited edges with the
+2a. N-GRAM coverage - which combines the previous visited edges with the
 current one. This explodes the map but on the other hand has proven to be
 effective for fuzzing.
 See [README.ngram.md](README.ngram.md)
 
-3b. Context sensitive coverage - which combines the visited edges with an
+2b. Context sensitive coverage - which combines the visited edges with an
 individual caller ID (the function that called the current one)
 [README.ctx.md](README.ctx.md)
 
@@ -151,6 +144,11 @@ is not optimal and was only fixed in llvm 9.
 You can set this with AFL_LLVM_NOT_ZERO=1
 See [README.neverzero.md](README.neverzero.md)
 
+Support for thread safe counters has been added for all modes.
+Activate it with `AFL_LLVM_THREADSAFE_INST=1`. The tradeoff is better precision
+in multi threaded apps for a slightly higher instrumentation overhead.
+This also disables the nozero counter default for performance reasons.
+
 ## 4) Snapshot feature
 
 To speed up fuzzing you can use a linux loadable kernel module which enables
diff --git a/instrumentation/README.neverzero.md b/instrumentation/README.neverzero.md
index 49104e00..9bcae324 100644
--- a/instrumentation/README.neverzero.md
+++ b/instrumentation/README.neverzero.md
@@ -16,11 +16,12 @@ at a very little cost (one instruction per edge).
 (The alternative of saturated counters has been tested also and proved to be
 inferior in terms of path discovery.)
 
-This is implemented in afl-gcc and afl-gcc-fast, however for llvm_mode this is optional if
-the llvm version is below 9 - as there is a perfomance bug that is only fixed
-in version 9 and onwards.
+This is implemented in afl-gcc and afl-gcc-fast, however for llvm_mode this is
+optional if multithread safe counters are selected or the llvm version is below
+9 - as there are severe performance costs in these cases.
 
-If you want to enable this for llvm versions below 9 then set
+If you want to enable this for llvm versions below 9 or thread safe counters
+then set
 
 ```
 export AFL_LLVM_NOT_ZERO=1
@@ -33,3 +34,8 @@ AFL_LLVM_SKIP_NEVERZERO=1
 ```
 If the target does not have extensive loops or functions that are called
 a lot then this can give a small performance boost.
+
+Please note that the default counter implementations are not thread safe!
+
+Support for thread safe counters in mode LLVM CLASSIC can be activated with setting
+`AFL_LLVM_THREADSAFE_INST=1`.
\ No newline at end of file
diff --git a/instrumentation/README.snapshot.md b/instrumentation/README.snapshot.md
index c40a956a..c794c2fd 100644
--- a/instrumentation/README.snapshot.md
+++ b/instrumentation/README.snapshot.md
@@ -1,5 +1,7 @@
 # AFL++ snapshot feature
 
+**NOTE:** the snapshot lkm is currently not supported and needs a maintainer :-)
+
 Snapshotting is a feature that makes a snapshot from a process and then
 restores its state, which is faster then forking it again.
 
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 6dd390e6..20f1856e 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -60,15 +60,14 @@ using namespace llvm;
 
 #define DEBUG_TYPE "sancov"
 
-static const char *const SanCovTracePCIndirName =
-    "__sanitizer_cov_trace_pc_indir";
-static const char *const SanCovTracePCName = "__sanitizer_cov_trace_pc";
-// static const char *const SanCovTracePCGuardName =
+const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir";
+const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc";
+// const char SanCovTracePCGuardName =
 //    "__sanitizer_cov_trace_pc_guard";
-static const char *const SanCovGuardsSectionName = "sancov_guards";
-static const char *const SanCovCountersSectionName = "sancov_cntrs";
-static const char *const SanCovBoolFlagSectionName = "sancov_bools";
-static const char *const SanCovPCsSectionName = "sancov_pcs";
+const char SanCovGuardsSectionName[] = "sancov_guards";
+const char SanCovCountersSectionName[] = "sancov_cntrs";
+const char SanCovBoolFlagSectionName[] = "sancov_bools";
+const char SanCovPCsSectionName[] = "sancov_pcs";
 
 static cl::opt<int> ClCoverageLevel(
     "lto-coverage-level",
@@ -237,7 +236,8 @@ class ModuleSanitizerCoverage {
   uint32_t                         inst = 0;
   uint32_t                         afl_global_id = 0;
   uint64_t                         map_addr = 0;
-  char *                           skip_nozero = NULL;
+  const char *                     skip_nozero = NULL;
+  const char *                     use_threadsafe_counters = nullptr;
   std::vector<BasicBlock *>        BlockList;
   DenseMap<Value *, std::string *> valueMap;
   std::vector<std::string>         dictionary;
@@ -438,6 +438,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
     be_quiet = 1;
 
   skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
+  use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
 
   if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL)
     if ((afl_global_id = atoi(ptr)) < 0)
@@ -1209,7 +1210,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
     return;  // Should not instrument sanitizer init functions.
   if (F.getName().startswith("__sanitizer_"))
     return;  // Don't instrument __sanitizer_* callbacks.
-  // Don't touch available_externally functions, their actual body is elewhere.
+  // Don't touch available_externally functions, their actual body is elsewhere.
   if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return;
   // Don't instrument MSVC CRT configuration helpers. They may run before normal
   // initialization.
@@ -1496,22 +1497,31 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     }
 
     /* Update bitmap */
+    if (use_threadsafe_counters) {                                /* Atomic */
 
-    LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
-    Counter->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
+      IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
+                          llvm::AtomicOrdering::Monotonic);
 
-    Value *Incr = IRB.CreateAdd(Counter, One);
+    } else {
 
-    if (skip_nozero == NULL) {
+      LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+      Counter->setMetadata(Mo->getMDKindID("nosanitize"),
+                           MDNode::get(*Ct, None));
 
-      auto cf = IRB.CreateICmpEQ(Incr, Zero);
-      auto carry = IRB.CreateZExt(cf, Int8Tyi);
-      Incr = IRB.CreateAdd(Incr, carry);
+      Value *Incr = IRB.CreateAdd(Counter, One);
 
-    }
+      if (skip_nozero == NULL) {
 
-    IRB.CreateStore(Incr, MapPtrIdx)
-        ->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
+        auto cf = IRB.CreateICmpEQ(Incr, Zero);
+        auto carry = IRB.CreateZExt(cf, Int8Tyi);
+        Incr = IRB.CreateAdd(Incr, carry);
+
+      }
+
+      IRB.CreateStore(Incr, MapPtrIdx)
+          ->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
+
+    }
 
     // done :)
 
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 09cda9e2..4a8c9e28 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -52,51 +52,42 @@ using namespace llvm;
 
 #define DEBUG_TYPE "sancov"
 
-static const char *const SanCovTracePCIndirName =
-    "__sanitizer_cov_trace_pc_indir";
-static const char *const SanCovTracePCName = "__sanitizer_cov_trace_pc";
-static const char *const SanCovTraceCmp1 = "__sanitizer_cov_trace_cmp1";
-static const char *const SanCovTraceCmp2 = "__sanitizer_cov_trace_cmp2";
-static const char *const SanCovTraceCmp4 = "__sanitizer_cov_trace_cmp4";
-static const char *const SanCovTraceCmp8 = "__sanitizer_cov_trace_cmp8";
-static const char *const SanCovTraceConstCmp1 =
-    "__sanitizer_cov_trace_const_cmp1";
-static const char *const SanCovTraceConstCmp2 =
-    "__sanitizer_cov_trace_const_cmp2";
-static const char *const SanCovTraceConstCmp4 =
-    "__sanitizer_cov_trace_const_cmp4";
-static const char *const SanCovTraceConstCmp8 =
-    "__sanitizer_cov_trace_const_cmp8";
-static const char *const SanCovTraceDiv4 = "__sanitizer_cov_trace_div4";
-static const char *const SanCovTraceDiv8 = "__sanitizer_cov_trace_div8";
-static const char *const SanCovTraceGep = "__sanitizer_cov_trace_gep";
-static const char *const SanCovTraceSwitchName = "__sanitizer_cov_trace_switch";
-static const char *const SanCovModuleCtorTracePcGuardName =
+const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir";
+const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc";
+const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1";
+const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2";
+const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4";
+const char SanCovTraceCmp8[] = "__sanitizer_cov_trace_cmp8";
+const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1";
+const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2";
+const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4";
+const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8";
+const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4";
+const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8";
+const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep";
+const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch";
+const char SanCovModuleCtorTracePcGuardName[] =
     "sancov.module_ctor_trace_pc_guard";
-static const char *const SanCovModuleCtor8bitCountersName =
+const char SanCovModuleCtor8bitCountersName[] =
     "sancov.module_ctor_8bit_counters";
-static const char *const SanCovModuleCtorBoolFlagName =
-    "sancov.module_ctor_bool_flag";
+const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag";
 static const uint64_t SanCtorAndDtorPriority = 2;
 
-static const char *const SanCovTracePCGuardName =
-    "__sanitizer_cov_trace_pc_guard";
-static const char *const SanCovTracePCGuardInitName =
-    "__sanitizer_cov_trace_pc_guard_init";
-static const char *const SanCov8bitCountersInitName =
-    "__sanitizer_cov_8bit_counters_init";
-static const char *const SanCovBoolFlagInitName =
-    "__sanitizer_cov_bool_flag_init";
-static const char *const SanCovPCsInitName = "__sanitizer_cov_pcs_init";
+const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard";
+const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init";
+const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init";
+const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init";
+const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init";
 
-static const char *const SanCovGuardsSectionName = "sancov_guards";
-static const char *const SanCovCountersSectionName = "sancov_cntrs";
-static const char *const SanCovBoolFlagSectionName = "sancov_bools";
-static const char *const SanCovPCsSectionName = "sancov_pcs";
+const char SanCovGuardsSectionName[] = "sancov_guards";
+const char SanCovCountersSectionName[] = "sancov_cntrs";
+const char SanCovBoolFlagSectionName[] = "sancov_bools";
+const char SanCovPCsSectionName[] = "sancov_pcs";
 
-static const char *const SanCovLowestStackName = "__sancov_lowest_stack";
+const char SanCovLowestStackName[] = "__sancov_lowest_stack";
 
-static char *skip_nozero;
+static const char *skip_nozero;
+static const char *use_threadsafe_counters;
 
 namespace {
 
@@ -320,12 +311,12 @@ std::pair<Value *, Value *> ModuleSanitizerCoverage::CreateSecStartEnd(
     Module &M, const char *Section, Type *Ty) {
 
   GlobalVariable *SecStart = new GlobalVariable(
-      M, Ty->getPointerElementType(), false, GlobalVariable::ExternalLinkage,
-      nullptr, getSectionStart(Section));
+      M, Ty->getPointerElementType(), false,
+      GlobalVariable::ExternalWeakLinkage, nullptr, getSectionStart(Section));
   SecStart->setVisibility(GlobalValue::HiddenVisibility);
   GlobalVariable *SecEnd = new GlobalVariable(
-      M, Ty->getPointerElementType(), false, GlobalVariable::ExternalLinkage,
-      nullptr, getSectionEnd(Section));
+      M, Ty->getPointerElementType(), false,
+      GlobalVariable::ExternalWeakLinkage, nullptr, getSectionEnd(Section));
   SecEnd->setVisibility(GlobalValue::HiddenVisibility);
   IRBuilder<> IRB(M.getContext());
   if (!TargetTriple.isOSBinFormatCOFF())
@@ -396,6 +387,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
     be_quiet = 1;
 
   skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
+  use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
 
   initInstrumentList();
   scanForDangerousFunctions(&M);
@@ -573,7 +565,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
 }
 
 // True if block has successors and it dominates all of them.
-static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) {
+bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) {
 
   if (succ_begin(BB) == succ_end(BB)) return false;
 
@@ -588,8 +580,7 @@ static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) {
 }
 
 // True if block has predecessors and it postdominates all of them.
-static bool isFullPostDominator(const BasicBlock *       BB,
-                                const PostDominatorTree *PDT) {
+bool isFullPostDominator(const BasicBlock *BB, const PostDominatorTree *PDT) {
 
   if (pred_begin(BB) == pred_end(BB)) return false;
 
@@ -603,10 +594,10 @@ static bool isFullPostDominator(const BasicBlock *       BB,
 
 }
 
-static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
-                                  const DominatorTree *           DT,
-                                  const PostDominatorTree *       PDT,
-                                  const SanitizerCoverageOptions &Options) {
+bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
+                           const DominatorTree *           DT,
+                           const PostDominatorTree *       PDT,
+                           const SanitizerCoverageOptions &Options) {
 
   // Don't insert coverage for blocks containing nothing but unreachable: we
   // will never call __sanitizer_cov() for them, so counting them in
@@ -636,8 +627,7 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
 // A twist here is that we treat From->To as a backedge if
 //   * To dominates From or
 //   * To->UniqueSuccessor dominates From
-static bool IsBackEdge(BasicBlock *From, BasicBlock *To,
-                       const DominatorTree *DT) {
+bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) {
 
   if (DT->dominates(To, From)) return true;
   if (auto Next = To->getUniqueSuccessor())
@@ -651,8 +641,8 @@ static bool IsBackEdge(BasicBlock *From, BasicBlock *To,
 //
 // Note that Cmp pruning is controlled by the same flag as the
 // BB pruning.
-static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
-                             const SanitizerCoverageOptions &Options) {
+bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
+                      const SanitizerCoverageOptions &Options) {
 
   if (!Options.NoPrune)
     if (CMP->hasOneUse())
@@ -1046,7 +1036,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
 
   if (IsEntryBB) {
 
-    // Keep static allocas and llvm.localescape calls in the entry block.  Even
+    // Keep allocas and llvm.localescape calls in the entry block.  Even
     // if we aren't splitting the block, it's nice for allocas to be before
     // calls.
     IP = PrepareToSplitEntryBlock(BB, IP);
@@ -1079,22 +1069,31 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
 
     /* Load counter for CurLoc */
 
-    Value *   MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
-    LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+    Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
 
-    /* Update bitmap */
+    if (use_threadsafe_counters) {
 
-    Value *Incr = IRB.CreateAdd(Counter, One);
+      IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
+                          llvm::AtomicOrdering::Monotonic);
 
-    if (skip_nozero == NULL) {
+    } else {
 
-      auto cf = IRB.CreateICmpEQ(Incr, Zero);
-      auto carry = IRB.CreateZExt(cf, Int8Ty);
-      Incr = IRB.CreateAdd(Incr, carry);
+      LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+      /* Update bitmap */
 
-    }
+      Value *Incr = IRB.CreateAdd(Counter, One);
+
+      if (skip_nozero == NULL) {
+
+        auto cf = IRB.CreateICmpEQ(Incr, Zero);
+        auto carry = IRB.CreateZExt(cf, Int8Ty);
+        Incr = IRB.CreateAdd(Incr, carry);
 
-    IRB.CreateStore(Incr, MapPtrIdx);
+      }
+
+      IRB.CreateStore(Incr, MapPtrIdx);
+
+    }
 
     // done :)
 
@@ -1221,17 +1220,17 @@ ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
 
 }
 
-static void registerPCGUARDPass(const PassManagerBuilder &,
-                                legacy::PassManagerBase &PM) {
+void registerPCGUARDPass(const PassManagerBuilder &,
+                         legacy::PassManagerBase &PM) {
 
   auto p = new ModuleSanitizerCoverageLegacyPass();
   PM.add(p);
 
 }
 
-static RegisterStandardPasses RegisterCompTransPass(
+RegisterStandardPasses RegisterCompTransPass(
     PassManagerBuilder::EP_OptimizerLast, registerPCGUARDPass);
 
-static RegisterStandardPasses RegisterCompTransPass0(
+RegisterStandardPasses RegisterCompTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerPCGUARDPass);
 
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index f241447a..2089ce78 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -34,8 +34,10 @@
 #include <errno.h>
 
 #include <sys/mman.h>
-#include <sys/syscall.h>
 #ifndef __HAIKU__
+  #include <sys/syscall.h>
+#endif
+#ifndef USEMMAP
   #include <sys/shm.h>
 #endif
 #include <sys/wait.h>
@@ -76,6 +78,11 @@
   #define MAP_INITIAL_SIZE MAP_SIZE
 #endif
 
+#if defined(__HAIKU__)
+extern ssize_t _kern_write(int fd, off_t pos, const void *buffer,
+                           size_t bufferSize);
+#endif  // HAIKU
+
 u8   __afl_area_initial[MAP_INITIAL_SIZE];
 u8 * __afl_area_ptr_dummy = __afl_area_initial;
 u8 * __afl_area_ptr = __afl_area_initial;
@@ -99,12 +106,10 @@ int __afl_selective_coverage_temp = 1;
 PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
 PREV_LOC_T __afl_prev_caller[CTX_MAX_K];
 u32        __afl_prev_ctx;
-u32        __afl_cmp_counter;
 #else
 __thread PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
 __thread PREV_LOC_T __afl_prev_caller[CTX_MAX_K];
 __thread u32        __afl_prev_ctx;
-__thread u32        __afl_cmp_counter;
 #endif
 
 int __afl_sharedmem_fuzzing __attribute__((weak));
@@ -1140,6 +1145,18 @@ void __afl_manual_init(void) {
 
 __attribute__((constructor())) void __afl_auto_init(void) {
 
+#ifdef __ANDROID__
+  // Disable handlers in linker/debuggerd, check include/debuggerd/handler.h
+  signal(SIGABRT, SIG_DFL);
+  signal(SIGBUS, SIG_DFL);
+  signal(SIGFPE, SIG_DFL);
+  signal(SIGILL, SIG_DFL);
+  signal(SIGSEGV, SIG_DFL);
+  signal(SIGSTKFLT, SIG_DFL);
+  signal(SIGSYS, SIG_DFL);
+  signal(SIGTRAP, SIG_DFL);
+#endif
+
   if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
 
   if (getenv(DEFER_ENV_VAR)) return;
@@ -1738,7 +1755,11 @@ static int area_is_valid(void *ptr, size_t len) {
 
   if (unlikely(!ptr || __asan_region_is_poisoned(ptr, len))) { return 0; }
 
+#ifndef __HAIKU__
   long r = syscall(SYS_write, __afl_dummy_fd[1], ptr, len);
+#else
+  long r = _kern_write(__afl_dummy_fd[1], -1, ptr, len);
+#endif  // HAIKU
 
   if (r <= 0 || r > len) return 0;
 
diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc
index 41bb5152..3b7eb878 100644
--- a/instrumentation/afl-gcc-pass.so.cc
+++ b/instrumentation/afl-gcc-pass.so.cc
@@ -177,7 +177,7 @@ int plugin_is_GPL_compatible = 1;
 
 namespace {
 
-static const struct pass_data afl_pass_data = {
+static constexpr struct pass_data afl_pass_data = {
 
     .type = GIMPLE_PASS,
     .name = "afl",
@@ -503,7 +503,7 @@ struct afl_pass : gimple_opt_pass {
     // Starting from "LLVMFuzzer" these are functions used in libfuzzer based
     // fuzzing campaign installations, e.g. oss-fuzz
 
-    static const char *ignoreList[] = {
+    static constexpr const char *ignoreList[] = {
 
         "asan.",
         "llvm.",
diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc
index 74943fb2..af32e2f9 100644
--- a/instrumentation/afl-llvm-common.cc
+++ b/instrumentation/afl-llvm-common.cc
@@ -55,7 +55,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
   // Starting from "LLVMFuzzer" these are functions used in libfuzzer based
   // fuzzing campaign installations, e.g. oss-fuzz
 
-  static const char *ignoreList[] = {
+  static constexpr const char *ignoreList[] = {
 
       "asan.",
       "llvm.",
@@ -94,7 +94,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
 
   }
 
-  static const char *ignoreSubstringList[] = {
+  static constexpr const char *ignoreSubstringList[] = {
 
       "__asan",       "__msan",     "__ubsan", "__lsan",
       "__san",        "__sanitize", "__cxx",   "_GLOBAL__",
@@ -104,7 +104,8 @@ bool isIgnoreFunction(const llvm::Function *F) {
 
   for (auto const &ignoreListFunc : ignoreSubstringList) {
 
-    if (F->getName().contains(ignoreListFunc)) { return true; }
+    // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
+    if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
 
   }
 
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index c954054b..e2b44b21 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -426,7 +426,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
               ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
               if (ilen) {
 
-                uint64_t literalLength = Str2.size();
+                uint64_t literalLength = Str2.length();
                 uint64_t optLength = ilen->getZExtValue();
                 if (literalLength + 1 == optLength) {
 
@@ -434,6 +434,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
                 }
 
+                if (optLength > Str2.length()) { optLength = Str2.length(); }
+
               }
 
               valueMap[Str1P] = new std::string(Str2);
@@ -532,6 +534,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
               uint64_t literalLength = optLen;
               optLen = ilen->getZExtValue();
+              if (optLen > thestring.length()) { optLen = thestring.length(); }
               if (optLen < 2) { continue; }
               if (literalLength + 1 == optLen) {  // add null byte
                 thestring.append("\0", 1);
diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc
index 50306224..fe43fbe5 100644
--- a/instrumentation/afl-llvm-lto-instrumentation.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc
@@ -89,11 +89,12 @@ class AFLLTOPass : public ModulePass {
   bool runOnModule(Module &M) override;
 
  protected:
-  uint32_t afl_global_id = 1, autodictionary = 1;
-  uint32_t function_minimum_size = 1;
-  uint32_t inst_blocks = 0, inst_funcs = 0, total_instr = 0;
-  uint64_t map_addr = 0x10000;
-  char *   skip_nozero = NULL;
+  uint32_t               afl_global_id = 1, autodictionary = 1;
+  uint32_t               function_minimum_size = 1;
+  uint32_t               inst_blocks = 0, inst_funcs = 0, total_instr = 0;
+  unsigned long long int map_addr = 0x10000;
+  const char *           skip_nozero = NULL;
+  const char *           use_threadsafe_counters = nullptr;
 
 };
 
@@ -131,6 +132,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
     be_quiet = 1;
 
+  use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
+
   if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
 
     if ((documentFile = fopen(ptr, "a")) == NULL)
@@ -176,7 +179,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
   }
 
-  if (debug) { fprintf(stderr, "map address is 0x%lx\n", map_addr); }
+  if (debug) { fprintf(stderr, "map address is 0x%llx\n", map_addr); }
 
   /* Get/set the globals for the SHM region. */
 
@@ -839,22 +842,32 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
           /* Update bitmap */
 
-          LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
-          Counter->setMetadata(M.getMDKindID("nosanitize"),
-                               MDNode::get(C, None));
+          if (use_threadsafe_counters) {
+
+            IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
+                                llvm::AtomicOrdering::Monotonic);
 
-          Value *Incr = IRB.CreateAdd(Counter, One);
+          } else {
 
-          if (skip_nozero == NULL) {
+            LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+            Counter->setMetadata(M.getMDKindID("nosanitize"),
+                                 MDNode::get(C, None));
 
-            auto cf = IRB.CreateICmpEQ(Incr, Zero);
-            auto carry = IRB.CreateZExt(cf, Int8Ty);
-            Incr = IRB.CreateAdd(Incr, carry);
+            Value *Incr = IRB.CreateAdd(Counter, One);
 
-          }
+            if (skip_nozero == NULL) {
 
-          IRB.CreateStore(Incr, MapPtrIdx)
-              ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+              auto cf = IRB.CreateICmpEQ(Incr, Zero);
+              auto carry = IRB.CreateZExt(cf, Int8Ty);
+              Incr = IRB.CreateAdd(Incr, carry);
+
+            }
+
+            IRB.CreateStore(Incr, MapPtrIdx)
+                ->setMetadata(M.getMDKindID("nosanitize"),
+                              MDNode::get(C, None));
+
+          }
 
           // done :)
 
diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc
index 0f773aba..a8f1baff 100644
--- a/instrumentation/afl-llvm-pass.so.cc
+++ b/instrumentation/afl-llvm-pass.so.cc
@@ -81,11 +81,12 @@ class AFLCoverage : public ModulePass {
   bool runOnModule(Module &M) override;
 
  protected:
-  uint32_t ngram_size = 0;
-  uint32_t ctx_k = 0;
-  uint32_t map_size = MAP_SIZE;
-  uint32_t function_minimum_size = 1;
-  char *   ctx_str = NULL, *caller_str = NULL, *skip_nozero = NULL;
+  uint32_t    ngram_size = 0;
+  uint32_t    ctx_k = 0;
+  uint32_t    map_size = MAP_SIZE;
+  uint32_t    function_minimum_size = 1;
+  const char *ctx_str = NULL, *caller_str = NULL, *skip_nozero = NULL;
+  const char *use_threadsafe_counters = nullptr;
 
 };
 
@@ -182,6 +183,38 @@ bool AFLCoverage::runOnModule(Module &M) {
   char *neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO");
 #endif
   skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
+  use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
+
+  if ((isatty(2) && !getenv("AFL_QUIET")) || !!getenv("AFL_DEBUG")) {
+
+    if (use_threadsafe_counters) {
+
+      // disabled unless there is support for other modules as well
+      // (increases documentation complexity)
+      /*      if (!getenv("AFL_LLVM_NOT_ZERO")) { */
+
+      skip_nozero = "1";
+      SAYF(cCYA "afl-llvm-pass" VERSION cRST " using thread safe counters\n");
+
+      /*
+
+            } else {
+
+              SAYF(cCYA "afl-llvm-pass" VERSION cRST
+                        " using thread safe not-zero-counters\n");
+
+            }
+
+      */
+
+    } else {
+
+      SAYF(cCYA "afl-llvm-pass" VERSION cRST
+                " using non-thread safe instrumentation\n");
+
+    }
+
+  }
 
   unsigned PrevLocSize = 0;
   unsigned PrevCallerSize = 0;
@@ -388,7 +421,6 @@ bool AFLCoverage::runOnModule(Module &M) {
 #endif
 
   // other constants we need
-  ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
   ConstantInt *One = ConstantInt::get(Int8Ty, 1);
 
   Value *   PrevCtx = NULL;     // CTX sensitive coverage
@@ -410,6 +442,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
     if (F.size() < function_minimum_size) continue;
 
+    std::list<Value *> todo;
     for (auto &BB : F) {
 
       BasicBlock::iterator IP = BB.getFirstInsertionPt();
@@ -628,37 +661,68 @@ bool AFLCoverage::runOnModule(Module &M) {
 
       /* Update bitmap */
 
-      LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
-      Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+      if (use_threadsafe_counters) {                              /* Atomic */
+                                     /*
+                                     #if LLVM_VERSION_MAJOR < 9
+                                             if (neverZero_counters_str !=
+                                                 NULL) {  // with llvm 9 we make this the default as the bug
+                                     in llvm
+                                                          // is then fixed
+                                     #else
+                                             if (!skip_nozero) {
+                             
+                                     #endif
+                                               // register MapPtrIdx in a todo list
+                                               todo.push_back(MapPtrIdx);
+                             
+                                             } else {
+
+                                     */
+        IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
+                            llvm::AtomicOrdering::Monotonic);
+        /*
+
+                }
+
+        */
 
-      Value *Incr = IRB.CreateAdd(Counter, One);
+      } else {
+
+        LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+        Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+
+        Value *Incr = IRB.CreateAdd(Counter, One);
 
 #if LLVM_VERSION_MAJOR < 9
-      if (neverZero_counters_str !=
-          NULL) {  // with llvm 9 we make this the default as the bug in llvm is
-                   // then fixed
+        if (neverZero_counters_str !=
+            NULL) {  // with llvm 9 we make this the default as the bug in llvm
+                     // is then fixed
 #else
-      if (!skip_nozero) {
+        if (!skip_nozero) {
 
 #endif
-        /* hexcoder: Realize a counter that skips zero during overflow.
-         * Once this counter reaches its maximum value, it next increments to 1
-         *
-         * Instead of
-         * Counter + 1 -> Counter
-         * we inject now this
-         * Counter + 1 -> {Counter, OverflowFlag}
-         * Counter + OverflowFlag -> Counter
-         */
+          /* hexcoder: Realize a counter that skips zero during overflow.
+           * Once this counter reaches its maximum value, it next increments to
+           * 1
+           *
+           * Instead of
+           * Counter + 1 -> Counter
+           * we inject now this
+           * Counter + 1 -> {Counter, OverflowFlag}
+           * Counter + OverflowFlag -> Counter
+           */
+
+          ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
+          auto         cf = IRB.CreateICmpEQ(Incr, Zero);
+          auto         carry = IRB.CreateZExt(cf, Int8Ty);
+          Incr = IRB.CreateAdd(Incr, carry);
 
-        auto cf = IRB.CreateICmpEQ(Incr, Zero);
-        auto carry = IRB.CreateZExt(cf, Int8Ty);
-        Incr = IRB.CreateAdd(Incr, carry);
+        }
 
-      }
+        IRB.CreateStore(Incr, MapPtrIdx)
+            ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
 
-      IRB.CreateStore(Incr, MapPtrIdx)
-          ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+      }                                                  /* non atomic case */
 
       /* Update prev_loc history vector (by placing cur_loc at the head of the
          vector and shuffle the other elements back by one) */
@@ -715,6 +779,120 @@ bool AFLCoverage::runOnModule(Module &M) {
 
     }
 
+#if 0
+    if (use_threadsafe_counters) {                       /*Atomic NeverZero */
+      // handle the list of registered blocks to instrument
+      for (auto val : todo) {
+
+        /* hexcoder: Realize a thread-safe counter that skips zero during
+         * overflow. Once this counter reaches its maximum value, it next
+         * increments to 1
+         *
+         * Instead of
+         * Counter + 1 -> Counter
+         * we inject now this
+         * Counter + 1 -> {Counter, OverflowFlag}
+         * Counter + OverflowFlag -> Counter
+         */
+
+        /* equivalent c code looks like this
+         * Thanks to
+         https://preshing.com/20150402/you-can-do-any-kind-of-atomic-read-modify-write-operation/
+
+            int old = atomic_load_explicit(&Counter, memory_order_relaxed);
+            int new;
+            do {
+
+                 if (old == 255) {
+
+                   new = 1;
+
+                 } else {
+
+                   new = old + 1;
+
+                 }
+
+            } while (!atomic_compare_exchange_weak_explicit(&Counter, &old, new,
+
+         memory_order_relaxed, memory_order_relaxed));
+
+         */
+
+        Value *              MapPtrIdx = val;
+        Instruction *        MapPtrIdxInst = cast<Instruction>(val);
+        BasicBlock::iterator it0(&(*MapPtrIdxInst));
+        ++it0;
+        IRBuilder<> IRB(&(*it0));
+
+        // load the old counter value atomically
+        LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+        Counter->setAlignment(llvm::Align());
+        Counter->setAtomic(llvm::AtomicOrdering::Monotonic);
+        Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+
+        BasicBlock *BB = IRB.GetInsertBlock();
+        // insert a basic block with the corpus of a do while loop
+        // the calculation may need to repeat, if atomic compare_exchange is not
+        // successful
+
+        BasicBlock::iterator it(*Counter);
+        it++;  // split after load counter
+        BasicBlock *end_bb = BB->splitBasicBlock(it);
+        end_bb->setName("injected");
+
+        // insert the block before the second half of the split
+        BasicBlock *do_while_bb =
+            BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
+
+        // set terminator of BB from target end_bb to target do_while_bb
+        auto term = BB->getTerminator();
+        BranchInst::Create(do_while_bb, BB);
+        term->eraseFromParent();
+
+        // continue to fill instructions into the do_while loop
+        IRB.SetInsertPoint(do_while_bb, do_while_bb->getFirstInsertionPt());
+
+        PHINode *PN = IRB.CreatePHI(Int8Ty, 2);
+
+        // compare with maximum value 0xff
+        auto *Cmp = IRB.CreateICmpEQ(Counter, ConstantInt::get(Int8Ty, -1));
+
+        // increment the counter
+        Value *Incr = IRB.CreateAdd(Counter, One);
+
+        // select the counter value or 1
+        auto *Select = IRB.CreateSelect(Cmp, One, Incr);
+
+        // try to save back the new counter value
+        auto *CmpXchg = IRB.CreateAtomicCmpXchg(
+            MapPtrIdx, PN, Select, llvm::AtomicOrdering::Monotonic,
+            llvm::AtomicOrdering::Monotonic);
+        CmpXchg->setAlignment(llvm::Align());
+        CmpXchg->setWeak(true);
+        CmpXchg->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+
+        // get the result of trying to update the Counter
+        Value *Success =
+            IRB.CreateExtractValue(CmpXchg, ArrayRef<unsigned>({1}));
+        // get the (possibly updated) value of Counter
+        Value *OldVal =
+            IRB.CreateExtractValue(CmpXchg, ArrayRef<unsigned>({0}));
+
+        // initially we use Counter
+        PN->addIncoming(Counter, BB);
+        // on retry, we use the updated value
+        PN->addIncoming(OldVal, do_while_bb);
+
+        // if the cmpXchg was not successful, retry
+        IRB.CreateCondBr(Success, end_bb, do_while_bb);
+
+      }
+
+    }
+
+#endif
+
   }
 
   /*
diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc
index 97ab04a4..82f198aa 100644
--- a/instrumentation/split-switches-pass.so.cc
+++ b/instrumentation/split-switches-pass.so.cc
@@ -89,7 +89,7 @@ class SplitSwitchesTransform : public ModulePass {
 
   };
 
-  typedef std::vector<CaseExpr> CaseVector;
+  using CaseVector = std::vector<CaseExpr>;
 
  private:
   bool        splitSwitches(Module &M);