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/GNUmakefile11
-rw-r--r--llvm_mode/README.lto.md54
-rw-r--r--llvm_mode/README.md4
-rw-r--r--llvm_mode/afl-clang-fast.c42
-rw-r--r--llvm_mode/afl-llvm-lto-instrim.so.cc6
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc6
-rw-r--r--llvm_mode/afl-llvm-rt.o.c10
-rw-r--r--llvm_mode/compare-transform-pass.so.cc4
-rw-r--r--llvm_mode/split-compares-pass.so.cc391
9 files changed, 359 insertions, 169 deletions
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile
index b5d026ef..443322d7 100644
--- a/llvm_mode/GNUmakefile
+++ b/llvm_mode/GNUmakefile
@@ -32,15 +32,16 @@ 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.4 up to 11) -> e.g. "pkg_add llvm-7.0.1p9")
+    $(error llvm_mode needs a complete llvm installation (versions 3.4 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
   endif
 else
   LLVM_CONFIG ?= llvm-config
 endif
 
 LLVMVER  = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' )
-LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^1[2-9]' && echo 1 || echo 0 )
+LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^1[3-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_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-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)
 LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
@@ -53,7 +54,7 @@ ifeq "$(LLVMVER)" ""
 endif
 
 ifeq "$(LLVM_UNSUPPORTED)" "1"
-  $(warning llvm_mode only supports llvm versions 3.4 up to 11)
+  $(warning llvm_mode only supports llvm versions 3.4 up to 12)
 endif
 
 ifeq "$(LLVM_MAJOR)" "9"
@@ -65,8 +66,8 @@ ifeq "$(LLVM_NEW_API)" "1"
   LLVM_STDCXX = c++14
 endif
 
-ifeq "$(LLVM_MAJOR)" "11"
-  $(info [+] llvm_mode detected llvm 11, enabling afl-clang-lto LTO implementation)
+ifeq "$(LLVM_HAVE_LTO)" "1"
+  $(info [+] llvm_mode detected llvm 11+, enabling afl-clang-lto LTO implementation)
   LLVM_LTO = 1
   #TEST_MMAP = 1
 endif
diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md
index 4641fa89..d54d4ee0 100644
--- a/llvm_mode/README.lto.md
+++ b/llvm_mode/README.lto.md
@@ -2,7 +2,7 @@
 
 ## TLDR;
 
-This version requires a current llvm 11 compiled from the github master.
+This version requires a current llvm 11+ compiled from the github master.
 
 1. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better
    coverage than anything else that is out there in the AFL world
@@ -10,7 +10,7 @@ This version requires a current llvm 11 compiled from the github master.
 2. You can use it together with llvm_mode: laf-intel and the instrument file listing
    features and can be combined with cmplog/Redqueen
 
-3. It only works with llvm 11 (current github master state)
+3. It only works with llvm 11+
 
 4. AUTODICTIONARY feature! see below
 
@@ -61,9 +61,9 @@ AUTODICTIONARY: 11 strings found
 [+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode).
 ```
 
-## Getting llvm 11
+## Getting llvm 11+
 
-### Installing llvm 11 from the llvm repository
+### Installing llvm from the llvm repository (version 11)
 
 Installing the llvm snapshot builds is easy and mostly painless:
 
@@ -83,7 +83,7 @@ apt-get install -y clang-11 clang-tools-11 libc++1-11 libc++-11-dev \
     libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools
 ```
 
-### Building llvm 11 yourself
+### Building llvm yourself (version 12)
 
 Building llvm from github takes quite some long time and is not painless:
 ```
@@ -125,10 +125,9 @@ NOTE: some targets also need to set the linker, try both `afl-clang-lto` and
 
 ## AUTODICTIONARY feature
 
-Setting `AFL_LLVM_LTO_AUTODICTIONARY` will generate a dictionary in the
-target binary based on string compare and memory compare functions.
-afl-fuzz will automatically get these transmitted when starting to fuzz.
-This improves coverage on a lot of targets.
+While compiling, automatically a dictionary based on string comparisons is
+generated put into the target binary. This dictionary is transfered to afl-fuzz
+on start. This improves coverage statistically by 5-10% :)
 
 ## Fixed memory map
 
@@ -147,6 +146,8 @@ Some targets are difficult because the configure script does unusual stuff that
 is unexpected for afl. See the next chapter `Potential issues` how to solve
 these.
 
+### Example: ffmpeg
+
 An example of a hard to solve target is ffmpeg. Here is how to successfully
 instrument it:
 
@@ -186,6 +187,31 @@ instrument it:
 
 4. Then type make, wait for a long time and you are done :)
 
+### Example: WebKit jsc
+
+Building jsc is difficult as the build script has bugs.
+
+1. checkout Webkit: 
+```
+svn checkout https://svn.webkit.org/repository/webkit/trunk WebKit
+cd WebKit
+```
+
+2. Fix the build environment:
+```
+mkdir -p WebKitBuild/Release
+cd WebKitBuild/Release
+ln -s ../../../../../usr/bin/llvm-ar-12 llvm-ar-12
+ln -s ../../../../../usr/bin/llvm-ranlib-12 llvm-ranlib-12
+cd ../..
+```
+
+3. Build :)
+
+```
+Tools/Scripts/build-jsc --jsc-only --cli --cmakeargs="-DCMAKE_AR='llvm-ar-12' -DCMAKE_RANLIB='llvm-ranlib-12' -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_CC_FLAGS='-O3 -lrt' -DCMAKE_CXX_FLAGS='-O3 -lrt' -DIMPORTED_LOCATION='/lib/x86_64-linux-gnu/' -DCMAKE_CC=afl-clang-lto -DCMAKE_CXX=afl-clang-lto++ -DENABLE_STATIC_JSC=ON"
+```
+
 ## Potential issues
 
 ### compiling libraries fails
@@ -220,17 +246,17 @@ AS=llvm-as  ...
 afl-clang-lto is still work in progress.
 
 Known issues:
-  * Anything that llvm 11 cannot compile, afl-clang-lto can not compile either - obviously
+  * Anything that llvm 11+ cannot compile, afl-clang-lto can not compile either - obviously
   * Anything that does not compile with LTO, afl-clang-lto can not compile either - obviously
 
-Hence if building a target with afl-clang-lto fails try to build it with llvm11
-and LTO enabled (`CC=clang-11` `CXX=clang++-11` `CFLAGS=-flto=full` and
+Hence if building a target with afl-clang-lto fails try to build it with llvm12
+and LTO enabled (`CC=clang-12` `CXX=clang++-12` `CFLAGS=-flto=full` and
 `CXXFLAGS=-flto=full`).
 
 If this succeeeds then there is an issue with afl-clang-lto. Please report at
 [https://github.com/AFLplusplus/AFLplusplus/issues/226](https://github.com/AFLplusplus/AFLplusplus/issues/226)
 
-Even some targets where clang-11 fails can be build if the fail is just in
+Even some targets where clang-12 fails can be build if the fail is just in
 `./configure`, see `Solving difficult targets` above.
 
 ### Target crashes immediately
@@ -270,7 +296,7 @@ Still more problems came up though as this only works without bugs from
 llvm 9 onwards, and with high optimization the link optimization ruins
 the instrumented control flow graph.
 
-This is all now fixed with llvm 11. The llvm's own linker is now able to
+This is all now fixed with llvm 11+. The llvm's own linker is now able to
 load passes and this bypasses all problems we had.
 
 Happy end :)
diff --git a/llvm_mode/README.md b/llvm_mode/README.md
index e2e22751..22088dfd 100644
--- a/llvm_mode/README.md
+++ b/llvm_mode/README.md
@@ -6,7 +6,7 @@
 
 ## 1) Introduction
 
-! llvm_mode works with llvm versions 3.4 up to 11 !
+! llvm_mode works with llvm versions 3.4 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
@@ -183,4 +183,4 @@ AFL_LLVM_INSTRUMENT=PCGUARD  make
 ```
 
 Note that this us currently the default, as it is the best mode.
-If you have llvm 11 and compiled afl-clang-lto - this is the only better mode.
+If you have llvm 11+ and compiled afl-clang-lto - this is the only better mode.
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index f1b03682..4d01e740 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -311,12 +311,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", AFL_REAL_LD);
     cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
-    if (instrument_mode == INSTRUMENT_CFG)
-      cc_params[cc_par_cnt++] =
-          alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.so", obj_path);
-    else
-      cc_params[cc_par_cnt++] = alloc_printf(
-          "-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
+    /*
+        The current LTO instrim mode is not good, so we disable it
+        if (instrument_mode == INSTRUMENT_CFG)
+          cc_params[cc_par_cnt++] =
+              alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.so",
+       obj_path); else
+    */
+    cc_params[cc_par_cnt++] = alloc_printf(
+        "-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
     cc_params[cc_par_cnt++] = lto_flag;
 
   } else {
@@ -379,6 +382,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined"))
       continue;
 
+    if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
+
     cc_params[cc_par_cnt++] = cur;
 
   }
@@ -660,7 +665,7 @@ int main(int argc, char **argv, char **envp) {
       }
 
       if (strncasecmp(ptr, "pc-guard", strlen("pc-guard")) == 0 ||
-          strncasecmp(ptr, "pcguard", strlen("pcgard")) == 0) {
+          strncasecmp(ptr, "pcguard", strlen("pcguard")) == 0) {
 
         if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD)
           instrument_mode = INSTRUMENT_PCGUARD;
@@ -763,9 +768,19 @@ int main(int argc, char **argv, char **envp) {
 #if LLVM_VERSION_MAJOR <= 6
     instrument_mode = INSTRUMENT_AFL;
 #else
-    if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST"))
+    if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) {
+
       instrument_mode = INSTRUMENT_AFL;
-    else
+      WARNF(
+          "switching to classic instrumentation because "
+          "AFL_LLVM_INSTRUMENT_FILE does not work with PCGUARD. Use "
+          "-fsanitize-coverage-allowlist=allowlist.txt if you want to use "
+          "PCGUARD. See "
+          "https://clang.llvm.org/docs/"
+          "SanitizerCoverage.html#partially-disabling-instrumentation");
+
+    } else
+
       instrument_mode = INSTRUMENT_PCGUARD;
 #endif
 
@@ -813,9 +828,12 @@ int main(int argc, char **argv, char **envp) {
 
   if (instrument_mode == INSTRUMENT_PCGUARD &&
       (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")))
-    WARNF(
+    FATAL(
         "Instrumentation type PCGUARD does not support "
-        "AFL_LLVM_INSTRUMENT_FILE!");
+        "AFL_LLVM_INSTRUMENT_FILE! Use "
+        "-fsanitize-coverage-allowlist=allowlist.txt instead, see "
+        "https://clang.llvm.org/docs/"
+        "SanitizerCoverage.html#partially-disabling-instrumentation");
 
   if (argc < 2 || strcmp(argv[1], "-h") == 0) {
 
@@ -939,7 +957,7 @@ int main(int argc, char **argv, char **envp) {
 
     u32 map_size = atoi(ptr2);
     if (map_size != MAP_SIZE)
-      FATAL("AFL_MAP_SIZE is not supported by afl-clang-fast");
+      WARNF("AFL_MAP_SIZE is not supported by afl-clang-fast");
 
   }
 
diff --git a/llvm_mode/afl-llvm-lto-instrim.so.cc b/llvm_mode/afl-llvm-lto-instrim.so.cc
index ca2b5886..880963ac 100644
--- a/llvm_mode/afl-llvm-lto-instrim.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrim.so.cc
@@ -73,7 +73,7 @@ struct InsTrimLTO : public ModulePass {
  protected:
   uint32_t function_minimum_size = 1;
   char *   skip_nozero = NULL;
-  int      afl_global_id = 1, debug = 0, autodictionary = 0;
+  int      afl_global_id = 1, debug = 0, autodictionary = 1;
   uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0;
   uint64_t map_addr = 0x10000;
 
@@ -127,10 +127,6 @@ struct InsTrimLTO : public ModulePass {
 
     /* Process environment variables */
 
-    if (getenv("AFL_LLVM_AUTODICTIONARY") ||
-        getenv("AFL_LLVM_LTO_AUTODICTIONARY"))
-      autodictionary = 1;
-
     if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
 
     if ((ptr = getenv("AFL_LLVM_MAP_ADDR"))) {
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index af2db3ff..3c1d3565 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -86,7 +86,7 @@ class AFLLTOPass : public ModulePass {
   bool runOnModule(Module &M) override;
 
  protected:
-  int      afl_global_id = 1, debug = 0, autodictionary = 0;
+  int      afl_global_id = 1, debug = 0, autodictionary = 1;
   uint32_t function_minimum_size = 1;
   uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0, total_instr = 0;
   uint64_t map_addr = 0x10000;
@@ -120,10 +120,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
 
     be_quiet = 1;
 
-  if (getenv("AFL_LLVM_AUTODICTIONARY") ||
-      getenv("AFL_LLVM_LTO_AUTODICTIONARY"))
-    autodictionary = 1;
-
   if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
 
   if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
index f81d13ee..a509a9f0 100644
--- a/llvm_mode/afl-llvm-rt.o.c
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -53,7 +53,11 @@
 #define CONST_PRIO 5
 
 #ifndef MAP_FIXED_NOREPLACE
-  #define MAP_FIXED_NOREPLACE MAP_FIXED
+  #ifdef MAP_EXCL
+    #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
+  #else
+    #define MAP_FIXED_NOREPLACE MAP_FIXED
+  #endif
 #endif
 
 #include <sys/mman.h>
@@ -510,6 +514,8 @@ static void __afl_start_snapshots(void) {
 
       if (!child_pid) {
 
+        (void)nice(-20);
+
         signal(SIGCHLD, old_sigchld_handler);
 
         close(FORKSRV_FD);
@@ -713,6 +719,8 @@ static void __afl_start_forkserver(void) {
 
       if (!child_pid) {
 
+        (void)nice(-20);
+
         signal(SIGCHLD, old_sigchld_handler);
 
         close(FORKSRV_FD);
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
index 2d1ab1cc..2f165ea6 100644
--- a/llvm_mode/compare-transform-pass.so.cc
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -474,8 +474,8 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
       if (cur_lenchk_bb) {
 
         IRBuilder<> cur_lenchk_IRB(&*(cur_lenchk_bb->getFirstInsertionPt()));
-        Value *     icmp = cur_lenchk_IRB.CreateICmpEQ(sizedValue,
-                                                  ConstantInt::get(Int64Ty, i));
+        Value *     icmp = cur_lenchk_IRB.CreateICmpEQ(
+            sizedValue, ConstantInt::get(sizedValue->getType(), i));
         cur_lenchk_IRB.CreateCondBr(icmp, end_bb, cur_cmp_bb);
         cur_lenchk_bb->getTerminator()->eraseFromParent();
 
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc
index 651fa5b4..55128ca2 100644
--- a/llvm_mode/split-compares-pass.so.cc
+++ b/llvm_mode/split-compares-pass.so.cc
@@ -80,6 +80,7 @@ class SplitComparesTransform : public ModulePass {
   size_t splitIntCompares(Module &M, unsigned bitw);
   size_t splitFPCompares(Module &M);
   bool   simplifyCompares(Module &M);
+  bool   simplifyFPCompares(Module &M);
   bool   simplifyIntSignedness(Module &M);
   size_t nextPowerOfTwo(size_t in);
 
@@ -89,12 +90,11 @@ class SplitComparesTransform : public ModulePass {
 
 char SplitComparesTransform::ID = 0;
 
-/* This function splits ICMP instructions with xGE or xLE predicates into two
- * ICMP instructions with predicate xGT or xLT and EQ */
-bool SplitComparesTransform::simplifyCompares(Module &M) {
+/* This function splits FCMP instructions with xGE or xLE predicates into two
+ * FCMP instructions with predicate xGT or xLT and EQ */
+bool SplitComparesTransform::simplifyFPCompares(Module &M) {
 
   LLVMContext &              C = M.getContext();
-  std::vector<Instruction *> icomps;
   std::vector<Instruction *> fcomps;
   IntegerType *              Int1Ty = IntegerType::getInt1Ty(C);
 
@@ -112,24 +112,6 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
 
         if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
 
-          if (selectcmpInst->getPredicate() == CmpInst::ICMP_UGE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_SGE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_ULE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_SLE) {
-
-            auto op0 = selectcmpInst->getOperand(0);
-            auto op1 = selectcmpInst->getOperand(1);
-
-            IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType());
-            IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType());
-
-            /* this is probably not needed but we do it anyway */
-            if (!intTyOp0 || !intTyOp1) { continue; }
-
-            icomps.push_back(selectcmpInst);
-
-          }
-
           if (enableFPSplit &&
               (selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
                selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
@@ -159,105 +141,159 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
 
   }
 
-  if (!icomps.size() && !fcomps.size()) { return false; }
+  if (!fcomps.size()) { return false; }
 
-  for (auto &IcmpInst : icomps) {
+  /* transform for floating point */
+  for (auto &FcmpInst : fcomps) {
 
-    BasicBlock *bb = IcmpInst->getParent();
+    BasicBlock *bb = FcmpInst->getParent();
 
-    auto op0 = IcmpInst->getOperand(0);
-    auto op1 = IcmpInst->getOperand(1);
+    auto op0 = FcmpInst->getOperand(0);
+    auto op1 = FcmpInst->getOperand(1);
 
     /* find out what the new predicate is going to be */
-    auto               pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate();
+    auto               pred = dyn_cast<CmpInst>(FcmpInst)->getPredicate();
     CmpInst::Predicate new_pred;
     switch (pred) {
 
-      case CmpInst::ICMP_UGE:
-        new_pred = CmpInst::ICMP_UGT;
+      case CmpInst::FCMP_UGE:
+        new_pred = CmpInst::FCMP_UGT;
         break;
-      case CmpInst::ICMP_SGE:
-        new_pred = CmpInst::ICMP_SGT;
+      case CmpInst::FCMP_OGE:
+        new_pred = CmpInst::FCMP_OGT;
         break;
-      case CmpInst::ICMP_ULE:
-        new_pred = CmpInst::ICMP_ULT;
+      case CmpInst::FCMP_ULE:
+        new_pred = CmpInst::FCMP_ULT;
         break;
-      case CmpInst::ICMP_SLE:
-        new_pred = CmpInst::ICMP_SLT;
+      case CmpInst::FCMP_OLE:
+        new_pred = CmpInst::FCMP_OLT;
         break;
       default:  // keep the compiler happy
         continue;
 
     }
 
-    /* split before the icmp instruction */
-    BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
+    /* split before the fcmp instruction */
+    BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(FcmpInst));
 
     /* the old bb now contains a unconditional jump to the new one (end_bb)
      * we need to delete it later */
 
-    /* create the ICMP instruction with new_pred and add it to the old basic
-     * 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);
+    /* create the FCMP instruction with new_pred and add it to the old basic
+     * block bb it is now at the position where the old FcmpInst was */
+    Instruction *fcmp_np;
+    fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1);
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
-                             icmp_np);
+                             fcmp_np);
 
-    /* create a new basic block which holds the new EQ icmp */
-    Instruction *icmp_eq;
+    /* create a new basic block which holds the new EQ fcmp */
+    Instruction *fcmp_eq;
     /* insert middle_bb before end_bb */
     BasicBlock *middle_bb =
         BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
-    icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1);
-    middle_bb->getInstList().push_back(icmp_eq);
+    fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1);
+    middle_bb->getInstList().push_back(fcmp_eq);
     /* add an unconditional branch to the end of middle_bb with destination
      * end_bb */
     BranchInst::Create(end_bb, middle_bb);
 
     /* replace the uncond branch with a conditional one, which depends on the
-     * new_pred icmp. True goes to end, false to the middle (injected) bb */
+     * new_pred fcmp. True goes to end, false to the middle (injected) bb */
     auto term = bb->getTerminator();
-    BranchInst::Create(end_bb, middle_bb, icmp_np, bb);
+    BranchInst::Create(end_bb, middle_bb, fcmp_np, bb);
     term->eraseFromParent();
 
-    /* replace the old IcmpInst (which is the first inst in end_bb) with a PHI
+    /* replace the old FcmpInst (which is the first inst in end_bb) with a PHI
      * inst to wire up the loose ends */
     PHINode *PN = PHINode::Create(Int1Ty, 2, "");
-    /* the first result depends on the outcome of icmp_eq */
-    PN->addIncoming(icmp_eq, middle_bb);
-    /* if the source was the original bb we know that the icmp_np yielded true
+    /* the first result depends on the outcome of fcmp_eq */
+    PN->addIncoming(fcmp_eq, middle_bb);
+    /* if the source was the original bb we know that the fcmp_np yielded true
      * hence we can hardcode this value */
     PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
-    /* replace the old IcmpInst with our new and shiny PHI inst */
-    BasicBlock::iterator ii(IcmpInst);
-    ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+    /* replace the old FcmpInst with our new and shiny PHI inst */
+    BasicBlock::iterator ii(FcmpInst);
+    ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
 
   }
 
-  /* now for floating point */
-  for (auto &FcmpInst : fcomps) {
+  return true;
 
-    BasicBlock *bb = FcmpInst->getParent();
+}
 
-    auto op0 = FcmpInst->getOperand(0);
-    auto op1 = FcmpInst->getOperand(1);
+/* This function splits ICMP instructions with xGE or xLE predicates into two
+ * ICMP instructions with predicate xGT or xLT and EQ */
+bool SplitComparesTransform::simplifyCompares(Module &M) {
+
+  LLVMContext &              C = M.getContext();
+  std::vector<Instruction *> icomps;
+  IntegerType *              Int1Ty = IntegerType::getInt1Ty(C);
+
+  /* iterate over all functions, bbs and instruction and add
+   * all integer comparisons with >= and <= predicates to the icomps vector */
+  for (auto &F : M) {
+
+    if (!isInInstrumentList(&F)) continue;
+
+    for (auto &BB : F) {
+
+      for (auto &IN : BB) {
+
+        CmpInst *selectcmpInst = nullptr;
+
+        if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
+
+          if (selectcmpInst->getPredicate() == CmpInst::ICMP_UGE ||
+              selectcmpInst->getPredicate() == CmpInst::ICMP_SGE ||
+              selectcmpInst->getPredicate() == CmpInst::ICMP_ULE ||
+              selectcmpInst->getPredicate() == CmpInst::ICMP_SLE) {
+
+            auto op0 = selectcmpInst->getOperand(0);
+            auto op1 = selectcmpInst->getOperand(1);
+
+            IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+            IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+
+            /* this is probably not needed but we do it anyway */
+            if (!intTyOp0 || !intTyOp1) { continue; }
+
+            icomps.push_back(selectcmpInst);
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
+
+  if (!icomps.size()) { return false; }
+
+  for (auto &IcmpInst : icomps) {
+
+    BasicBlock *bb = IcmpInst->getParent();
+
+    auto op0 = IcmpInst->getOperand(0);
+    auto op1 = IcmpInst->getOperand(1);
 
     /* find out what the new predicate is going to be */
-    auto               pred = dyn_cast<CmpInst>(FcmpInst)->getPredicate();
+    auto               pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate();
     CmpInst::Predicate new_pred;
     switch (pred) {
 
-      case CmpInst::FCMP_UGE:
-        new_pred = CmpInst::FCMP_UGT;
+      case CmpInst::ICMP_UGE:
+        new_pred = CmpInst::ICMP_UGT;
         break;
-      case CmpInst::FCMP_OGE:
-        new_pred = CmpInst::FCMP_OGT;
+      case CmpInst::ICMP_SGE:
+        new_pred = CmpInst::ICMP_SGT;
         break;
-      case CmpInst::FCMP_ULE:
-        new_pred = CmpInst::FCMP_ULT;
+      case CmpInst::ICMP_ULE:
+        new_pred = CmpInst::ICMP_ULT;
         break;
-      case CmpInst::FCMP_OLE:
-        new_pred = CmpInst::FCMP_OLT;
+      case CmpInst::ICMP_SLE:
+        new_pred = CmpInst::ICMP_SLT;
         break;
       default:  // keep the compiler happy
         continue;
@@ -265,25 +301,25 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
     }
 
     /* split before the icmp instruction */
-    BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(FcmpInst));
+    BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
 
     /* the old bb now contains a unconditional jump to the new one (end_bb)
      * we need to delete it later */
 
     /* create the ICMP instruction with new_pred and add it to the old basic
      * 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);
+    Instruction *icmp_np;
+    icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
-                             fcmp_np);
+                             icmp_np);
 
-    /* create a new basic block which holds the new EQ fcmp */
-    Instruction *fcmp_eq;
+    /* create a new basic block which holds the new EQ icmp */
+    Instruction *icmp_eq;
     /* insert middle_bb before end_bb */
     BasicBlock *middle_bb =
         BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
-    fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1);
-    middle_bb->getInstList().push_back(fcmp_eq);
+    icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1);
+    middle_bb->getInstList().push_back(icmp_eq);
     /* add an unconditional branch to the end of middle_bb with destination
      * end_bb */
     BranchInst::Create(end_bb, middle_bb);
@@ -291,20 +327,20 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
     /* replace the uncond branch with a conditional one, which depends on the
      * new_pred icmp. True goes to end, false to the middle (injected) bb */
     auto term = bb->getTerminator();
-    BranchInst::Create(end_bb, middle_bb, fcmp_np, bb);
+    BranchInst::Create(end_bb, middle_bb, icmp_np, bb);
     term->eraseFromParent();
 
     /* replace the old IcmpInst (which is the first inst in end_bb) with a PHI
      * inst to wire up the loose ends */
     PHINode *PN = PHINode::Create(Int1Ty, 2, "");
     /* the first result depends on the outcome of icmp_eq */
-    PN->addIncoming(fcmp_eq, middle_bb);
+    PN->addIncoming(icmp_eq, middle_bb);
     /* if the source was the original bb we know that the icmp_np yielded true
      * hence we can hardcode this value */
     PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
     /* replace the old IcmpInst with our new and shiny PHI inst */
-    BasicBlock::iterator ii(FcmpInst);
-    ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
+    BasicBlock::iterator ii(IcmpInst);
+    ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
 
   }
 
@@ -640,7 +676,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
     BranchInst::Create(end_bb, signequal_bb);
 
-    /* create a new bb which is executed if exponents are equal */
+    /* create a new bb which is executed if exponents are satisfying the compare
+     */
     BasicBlock *middle_bb =
         BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
 
@@ -695,7 +732,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     }
 
     /* compare the exponents of the operands */
+    Instruction *icmp_exponents_equal;
     Instruction *icmp_exponent_result;
+    BasicBlock * signequal2_bb = signequal_bb;
     switch (FcmpInst->getPredicate()) {
 
       case CmpInst::FCMP_OEQ:
@@ -707,22 +746,60 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         icmp_exponent_result =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, m_e0, m_e1);
         break;
+      /* compare the exponents of the operands (signs are equal)
+       * if exponents are equal -> proceed to mantissa comparison
+       * else get result depending on sign
+       */
       case CmpInst::FCMP_OGT:
       case CmpInst::FCMP_UGT:
         Instruction *icmp_exponent;
+        icmp_exponents_equal =
+            CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
+        signequal_bb->getInstList().insert(
+            BasicBlock::iterator(signequal_bb->getTerminator()),
+            icmp_exponents_equal);
+
+        // shortcut for unequal exponents
+        signequal2_bb = signequal_bb->splitBasicBlock(
+            BasicBlock::iterator(signequal_bb->getTerminator()));
+
+        /* if the exponents are equal goto middle_bb else to signequal2_bb */
+        term = signequal_bb->getTerminator();
+        BranchInst::Create(middle_bb, signequal2_bb, icmp_exponents_equal,
+                           signequal_bb);
+        term->eraseFromParent();
+
         icmp_exponent =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
-        signequal_bb->getInstList().insert(
-            BasicBlock::iterator(signequal_bb->getTerminator()), icmp_exponent);
+        signequal2_bb->getInstList().insert(
+            BasicBlock::iterator(signequal2_bb->getTerminator()),
+            icmp_exponent);
         icmp_exponent_result =
             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
         break;
       case CmpInst::FCMP_OLT:
       case CmpInst::FCMP_ULT:
+        icmp_exponents_equal =
+            CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
+        signequal_bb->getInstList().insert(
+            BasicBlock::iterator(signequal_bb->getTerminator()),
+            icmp_exponents_equal);
+
+        // shortcut for unequal exponents
+        signequal2_bb = signequal_bb->splitBasicBlock(
+            BasicBlock::iterator(signequal_bb->getTerminator()));
+
+        /* if the exponents are equal goto middle_bb else to signequal2_bb */
+        term = signequal_bb->getTerminator();
+        BranchInst::Create(middle_bb, signequal2_bb, icmp_exponents_equal,
+                           signequal_bb);
+        term->eraseFromParent();
+
         icmp_exponent =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
-        signequal_bb->getInstList().insert(
-            BasicBlock::iterator(signequal_bb->getTerminator()), icmp_exponent);
+        signequal2_bb->getInstList().insert(
+            BasicBlock::iterator(signequal2_bb->getTerminator()),
+            icmp_exponent);
         icmp_exponent_result =
             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
         break;
@@ -731,15 +808,40 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
     }
 
-    signequal_bb->getInstList().insert(
-        BasicBlock::iterator(signequal_bb->getTerminator()),
+    signequal2_bb->getInstList().insert(
+        BasicBlock::iterator(signequal2_bb->getTerminator()),
         icmp_exponent_result);
 
     {
 
-      auto term = signequal_bb->getTerminator();
-      /* if the exponents are different do a fraction cmp */
-      BranchInst::Create(middle_bb, end_bb, icmp_exponent_result, signequal_bb);
+      term = signequal2_bb->getTerminator();
+
+      switch (FcmpInst->getPredicate()) {
+
+        case CmpInst::FCMP_OEQ:
+          /* if the exponents are satifying the compare do a fraction cmp in
+           * middle_bb */
+          BranchInst::Create(middle_bb, end_bb, icmp_exponent_result,
+                             signequal2_bb);
+          break;
+        case CmpInst::FCMP_ONE:
+        case CmpInst::FCMP_UNE:
+          /* if the exponents are satifying the compare do a fraction cmp in
+           * middle_bb */
+          BranchInst::Create(end_bb, middle_bb, icmp_exponent_result,
+                             signequal2_bb);
+          break;
+        case CmpInst::FCMP_OGT:
+        case CmpInst::FCMP_UGT:
+        case CmpInst::FCMP_OLT:
+        case CmpInst::FCMP_ULT:
+          BranchInst::Create(end_bb, signequal2_bb);
+          break;
+        default:
+          continue;
+
+      }
+
       term->eraseFromParent();
 
     }
@@ -800,44 +902,82 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
     /* compare the fractions of the operands */
     Instruction *icmp_fraction_result;
+    Instruction *icmp_fraction_result2;
+    BasicBlock * middle2_bb = middle_bb;
+    PHINode *    PN2 = nullptr;
     switch (FcmpInst->getPredicate()) {
 
       case CmpInst::FCMP_OEQ:
         icmp_fraction_result =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1);
+        middle2_bb->getInstList().insert(
+            BasicBlock::iterator(middle2_bb->getTerminator()),
+            icmp_fraction_result);
+
         break;
       case CmpInst::FCMP_UNE:
       case CmpInst::FCMP_ONE:
         icmp_fraction_result =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
+        middle2_bb->getInstList().insert(
+            BasicBlock::iterator(middle2_bb->getTerminator()),
+            icmp_fraction_result);
+
         break;
       case CmpInst::FCMP_OGT:
       case CmpInst::FCMP_UGT:
-        Instruction *icmp_fraction;
-        icmp_fraction =
-            CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
-        middle_bb->getInstList().insert(
-            BasicBlock::iterator(middle_bb->getTerminator()), icmp_fraction);
-        icmp_fraction_result =
-            BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
-        break;
       case CmpInst::FCMP_OLT:
-      case CmpInst::FCMP_ULT:
-        icmp_fraction =
-            CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
-        middle_bb->getInstList().insert(
-            BasicBlock::iterator(middle_bb->getTerminator()), icmp_fraction);
-        icmp_fraction_result =
-            BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
-        break;
+      case CmpInst::FCMP_ULT: {
+
+        middle2_bb = middle_bb->splitBasicBlock(
+            BasicBlock::iterator(middle_bb->getTerminator()));
+
+        BasicBlock *negative_bb = BasicBlock::Create(
+            C, "negative_value", middle2_bb->getParent(), middle2_bb);
+        BasicBlock *positive_bb = BasicBlock::Create(
+            C, "positive_value", negative_bb->getParent(), negative_bb);
+
+        if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
+            FcmpInst->getPredicate() == CmpInst::FCMP_UGT) {
+
+          negative_bb->getInstList().push_back(
+              icmp_fraction_result = CmpInst::Create(
+                  Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1));
+          positive_bb->getInstList().push_back(
+              icmp_fraction_result2 = CmpInst::Create(
+                  Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1));
+
+        } else {
+
+          negative_bb->getInstList().push_back(
+              icmp_fraction_result = CmpInst::Create(
+                  Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1));
+          positive_bb->getInstList().push_back(
+              icmp_fraction_result2 = CmpInst::Create(
+                  Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1));
+
+        }
+
+        BranchInst::Create(middle2_bb, negative_bb);
+        BranchInst::Create(middle2_bb, positive_bb);
+
+        term = middle_bb->getTerminator();
+        BranchInst::Create(negative_bb, positive_bb, t_s0, middle_bb);
+        term->eraseFromParent();
+
+        PN2 = PHINode::Create(Int1Ty, 2, "");
+        PN2->addIncoming(icmp_fraction_result, negative_bb);
+        PN2->addIncoming(icmp_fraction_result2, positive_bb);
+        middle2_bb->getInstList().insert(
+            BasicBlock::iterator(middle2_bb->getTerminator()), PN2);
+
+      } break;
+
       default:
         continue;
 
     }
 
-    middle_bb->getInstList().insert(
-        BasicBlock::iterator(middle_bb->getTerminator()), icmp_fraction_result);
-
     PHINode *PN = PHINode::Create(Int1Ty, 3, "");
 
     switch (FcmpInst->getPredicate()) {
@@ -849,7 +989,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         /* unequal exponents cannot be equal values, too */
         PN->addIncoming(ConstantInt::get(Int1Ty, 0), signequal_bb);
         /* fractions comparison */
-        PN->addIncoming(icmp_fraction_result, middle_bb);
+        PN->addIncoming(icmp_fraction_result, middle2_bb);
         break;
       case CmpInst::FCMP_ONE:
       case CmpInst::FCMP_UNE:
@@ -857,25 +997,25 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         /* goto true branch */
         PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
         /* unequal exponents are unequal values, too */
-        PN->addIncoming(ConstantInt::get(Int1Ty, 1), signequal_bb);
+        PN->addIncoming(icmp_exponent_result, signequal_bb);
         /* fractions comparison */
-        PN->addIncoming(icmp_fraction_result, middle_bb);
+        PN->addIncoming(icmp_fraction_result, middle2_bb);
         break;
       case CmpInst::FCMP_OGT:
       case CmpInst::FCMP_UGT:
         /* if op1 is negative goto true branch,
            else go on comparing */
         PN->addIncoming(t_s1, bb);
-        PN->addIncoming(icmp_exponent_result, signequal_bb);
-        PN->addIncoming(icmp_fraction_result, middle_bb);
+        PN->addIncoming(icmp_exponent_result, signequal2_bb);
+        PN->addIncoming(PN2, middle2_bb);
         break;
       case CmpInst::FCMP_OLT:
       case CmpInst::FCMP_ULT:
         /* if op0 is negative goto true branch,
            else go on comparing */
         PN->addIncoming(t_s0, bb);
-        PN->addIncoming(icmp_exponent_result, signequal_bb);
-        PN->addIncoming(icmp_fraction_result, middle_bb);
+        PN->addIncoming(icmp_exponent_result, signequal2_bb);
+        PN->addIncoming(PN2, middle2_bb);
         break;
       default:
         continue;
@@ -1115,24 +1255,29 @@ bool SplitComparesTransform::runOnModule(Module &M) {
 
   enableFPSplit = getenv("AFL_LLVM_LAF_SPLIT_FLOATS") != NULL;
 
-  simplifyCompares(M);
-
-  simplifyIntSignedness(M);
-
   if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
       getenv("AFL_DEBUG") != NULL) {
 
     errs() << "Split-compare-pass by laf.intel@gmail.com, extended by "
               "heiko@hexco.de\n";
 
-    if (enableFPSplit)
+    if (enableFPSplit) {
+
       errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M)
              << " FP comparisons splitted\n";
 
+    }
+
   } else
 
     be_quiet = 1;
 
+  if (enableFPSplit) simplifyFPCompares(M);
+
+  simplifyCompares(M);
+
+  simplifyIntSignedness(M);
+
   switch (bitw) {
 
     case 64: