about summary refs log tree commit diff
path: root/instrumentation
diff options
context:
space:
mode:
Diffstat (limited to 'instrumentation')
-rw-r--r--instrumentation/afl-compiler-rt.o.c281
-rw-r--r--instrumentation/cmplog-instructions-pass.cc590
-rw-r--r--instrumentation/llvm-ngram-coverage.h2
3 files changed, 747 insertions, 126 deletions
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index e31bff16..14da4caa 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -161,7 +161,7 @@ void send_forkserver_error(int error) {
   u32 status;
   if (!error || error > 0xffff) return;
   status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));
-  if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return;
+  if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) { return; }
 
 }
 
@@ -544,11 +544,11 @@ static void __afl_start_snapshots(void) {
   if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT;
   memcpy(tmp, &status, 4);
 
-  if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
+  if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
 
   if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
 
-    if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
+    if (read(FORKSRV_FD, &was_killed, 4) != 4) { _exit(1); }
 
     if (getenv("AFL_DEBUG")) {
 
@@ -1207,22 +1207,33 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
 
 ///// CmpLog instrumentation
 
-void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
+void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) {
 
-  if (unlikely(!__afl_cmp_map)) return;
+  // fprintf(stderr, "hook1 arg0=%02x arg1=%02x attr=%u\n",
+  //         (u8) arg1, (u8) arg2, attr);
+
+  if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
   k &= CMP_MAP_W - 1;
 
-  __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+  u32 hits;
 
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
-  // if (!__afl_cmp_map->headers[k].cnt)
-  //  __afl_cmp_map->headers[k].cnt = __afl_cmp_counter++;
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
 
-  __afl_cmp_map->headers[k].shape = 0;
+    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = 0;
+
+  } else {
+
+    hits = __afl_cmp_map->headers[k].hits++;
+
+  }
+
+  __afl_cmp_map->headers[k].attribute = attr;
 
   hits &= CMP_MAP_H - 1;
   __afl_cmp_map->log[k][hits].v0 = arg1;
@@ -1230,20 +1241,36 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
 
 }
 
-void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
+void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
 
-  if (unlikely(!__afl_cmp_map)) return;
+  if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
   k &= CMP_MAP_W - 1;
 
-  __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+  u32 hits;
+
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
+
+    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = 1;
+
+  } else {
 
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
+    hits = __afl_cmp_map->headers[k].hits++;
 
-  __afl_cmp_map->headers[k].shape = 1;
+    if (!__afl_cmp_map->headers[k].shape) {
+
+      __afl_cmp_map->headers[k].shape = 1;
+
+    }
+
+  }
+
+  __afl_cmp_map->headers[k].attribute = attr;
 
   hits &= CMP_MAP_H - 1;
   __afl_cmp_map->log[k][hits].v0 = arg1;
@@ -1251,20 +1278,38 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
 
 }
 
-void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
+void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
 
-  if (unlikely(!__afl_cmp_map)) return;
+  // fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
+
+  if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
   k &= CMP_MAP_W - 1;
 
-  __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+  u32 hits;
+
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
+
+    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = 3;
+
+  } else {
+
+    hits = __afl_cmp_map->headers[k].hits++;
+
+    if (__afl_cmp_map->headers[k].shape < 3) {
+
+      __afl_cmp_map->headers[k].shape = 3;
 
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
+    }
+
+  }
 
-  __afl_cmp_map->headers[k].shape = 3;
+  __afl_cmp_map->headers[k].attribute = attr;
 
   hits &= CMP_MAP_H - 1;
   __afl_cmp_map->log[k][hits].v0 = arg1;
@@ -1272,20 +1317,38 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
 
 }
 
-void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) {
+void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
 
-  if (unlikely(!__afl_cmp_map)) return;
+  // fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
+
+  if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
   k &= CMP_MAP_W - 1;
 
-  __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+  u32 hits;
+
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
+
+    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = 7;
 
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
+  } else {
+
+    hits = __afl_cmp_map->headers[k].hits++;
+
+    if (__afl_cmp_map->headers[k].shape < 7) {
+
+      __afl_cmp_map->headers[k].shape = 7;
+
+    }
+
+  }
 
-  __afl_cmp_map->headers[k].shape = 7;
+  __afl_cmp_map->headers[k].attribute = attr;
 
   hits &= CMP_MAP_H - 1;
   __afl_cmp_map->log[k][hits].v0 = arg1;
@@ -1293,16 +1356,110 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) {
 
 }
 
+#ifdef WORD_SIZE_64
+// support for u24 to u120 via llvm _ExitInt(). size is in bytes minus 1
+void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
+                        uint8_t size) {
+
+  // fprintf(stderr, "hookN arg0=%llx:%llx arg1=%llx:%llx bytes=%u attr=%u\n",
+  // (u64)(arg1 >> 64), (u64)arg1, (u64)(arg2 >> 64), (u64)arg2, size + 1,
+  // attr);
+
+  if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
+
+  uintptr_t k = (uintptr_t)__builtin_return_address(0);
+  k = (k >> 4) ^ (k << 8);
+  k &= CMP_MAP_W - 1;
+
+  u32 hits;
+
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
+
+    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = size;
+
+  } else {
+
+    hits = __afl_cmp_map->headers[k].hits++;
+
+    if (__afl_cmp_map->headers[k].shape < size) {
+
+      __afl_cmp_map->headers[k].shape = size;
+
+    }
+
+  }
+
+  __afl_cmp_map->headers[k].attribute = attr;
+
+  hits &= CMP_MAP_H - 1;
+  __afl_cmp_map->log[k][hits].v0 = (u64)arg1;
+  __afl_cmp_map->log[k][hits].v1 = (u64)arg2;
+
+  if (size > 7) {
+
+    __afl_cmp_map->log[k][hits].v0_128 = (u64)(arg1 >> 64);
+    __afl_cmp_map->log[k][hits].v1_128 = (u64)(arg2 >> 64);
+
+  }
+
+}
+
+void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
+
+  if (unlikely(!__afl_cmp_map)) return;
+
+  uintptr_t k = (uintptr_t)__builtin_return_address(0);
+  k = (k >> 4) ^ (k << 8);
+  k &= CMP_MAP_W - 1;
+
+  u32 hits;
+
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
+
+    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = 15;
+
+  } else {
+
+    hits = __afl_cmp_map->headers[k].hits++;
+
+    if (__afl_cmp_map->headers[k].shape < 15) {
+
+      __afl_cmp_map->headers[k].shape = 15;
+
+    }
+
+  }
+
+  __afl_cmp_map->headers[k].attribute = attr;
+
+  hits &= CMP_MAP_H - 1;
+  __afl_cmp_map->log[k][hits].v0 = (u64)arg1;
+  __afl_cmp_map->log[k][hits].v1 = (u64)arg2;
+  __afl_cmp_map->log[k][hits].v0_128 = (u64)(arg1 >> 64);
+  __afl_cmp_map->log[k][hits].v1_128 = (u64)(arg2 >> 64);
+
+}
+
+#endif
+
 #if defined(__APPLE__)
   #pragma weak __sanitizer_cov_trace_const_cmp1 = __cmplog_ins_hook1
   #pragma weak __sanitizer_cov_trace_const_cmp2 = __cmplog_ins_hook2
   #pragma weak __sanitizer_cov_trace_const_cmp4 = __cmplog_ins_hook4
   #pragma weak __sanitizer_cov_trace_const_cmp8 = __cmplog_ins_hook8
+  #pragma weak __sanitizer_cov_trace_const_cmp16 = __cmplog_ins_hook16
 
   #pragma weak __sanitizer_cov_trace_cmp1 = __cmplog_ins_hook1
   #pragma weak __sanitizer_cov_trace_cmp2 = __cmplog_ins_hook2
   #pragma weak __sanitizer_cov_trace_cmp4 = __cmplog_ins_hook4
   #pragma weak __sanitizer_cov_trace_cmp8 = __cmplog_ins_hook8
+  #pragma weak __sanitizer_cov_trace_cmp16 = __cmplog_ins_hook16
 #else
 void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2)
     __attribute__((alias("__cmplog_ins_hook1")));
@@ -1312,6 +1469,10 @@ void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2)
     __attribute__((alias("__cmplog_ins_hook4")));
 void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2)
     __attribute__((alias("__cmplog_ins_hook8")));
+  #ifdef WORD_SIZE_64
+void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2)
+    __attribute__((alias("__cmplog_ins_hook16")));
+  #endif
 
 void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2)
     __attribute__((alias("__cmplog_ins_hook1")));
@@ -1321,6 +1482,10 @@ void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2)
     __attribute__((alias("__cmplog_ins_hook4")));
 void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2)
     __attribute__((alias("__cmplog_ins_hook8")));
+  #ifdef WORD_SIZE_64
+void __sanitizer_cov_trace_cmp16(uint128_t arg1, uint128_t arg2)
+    __attribute__((alias("__cmplog_ins_hook16")));
+  #endif
 #endif                                                /* defined(__APPLE__) */
 
 void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
@@ -1333,12 +1498,28 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
     k = (k >> 4) ^ (k << 8);
     k &= CMP_MAP_W - 1;
 
-    __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+    u32 hits;
 
-    u32 hits = __afl_cmp_map->headers[k].hits;
-    __afl_cmp_map->headers[k].hits = hits + 1;
+    if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
 
-    __afl_cmp_map->headers[k].shape = 7;
+      __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+      hits = 0;
+      __afl_cmp_map->headers[k].hits = 1;
+      __afl_cmp_map->headers[k].shape = 7;
+
+    } else {
+
+      hits = __afl_cmp_map->headers[k].hits++;
+
+      if (__afl_cmp_map->headers[k].shape < 7) {
+
+        __afl_cmp_map->headers[k].shape = 7;
+
+      }
+
+    }
+
+    __afl_cmp_map->headers[k].attribute = 1;
 
     hits &= CMP_MAP_H - 1;
     __afl_cmp_map->log[k][hits].v0 = val;
@@ -1364,6 +1545,18 @@ static int area_is_mapped(void *ptr, size_t len) {
 
 void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
 
+  /*
+    u32 i;
+    if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;
+    fprintf(stderr, "rtn arg0=");
+    for (i = 0; i < 8; i++)
+      fprintf(stderr, "%02x", ptr1[i]);
+    fprintf(stderr, " arg1=");
+    for (i = 0; i < 8; i++)
+      fprintf(stderr, "%02x", ptr2[i]);
+    fprintf(stderr, "\n");
+  */
+
   if (unlikely(!__afl_cmp_map)) return;
 
   if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;
@@ -1372,12 +1565,26 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
   k = (k >> 4) ^ (k << 8);
   k &= CMP_MAP_W - 1;
 
-  __afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
+  u32 hits;
+
+  if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
 
-  u32 hits = __afl_cmp_map->headers[k].hits;
-  __afl_cmp_map->headers[k].hits = hits + 1;
+    __afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
+    hits = 0;
+    __afl_cmp_map->headers[k].hits = 1;
+    __afl_cmp_map->headers[k].shape = 31;
 
-  __afl_cmp_map->headers[k].shape = 31;
+  } else {
+
+    hits = __afl_cmp_map->headers[k].hits++;
+
+    if (__afl_cmp_map->headers[k].shape < 31) {
+
+      __afl_cmp_map->headers[k].shape = 31;
+
+    }
+
+  }
 
   hits &= CMP_MAP_RTN_H - 1;
   __builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0,
diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc
index 3499ccf0..6ce1832f 100644
--- a/instrumentation/cmplog-instructions-pass.cc
+++ b/instrumentation/cmplog-instructions-pass.cc
@@ -85,9 +85,25 @@ class CmpLogInstructions : public ModulePass {
 
 char CmpLogInstructions::ID = 0;
 
+template <class Iterator>
+Iterator Unique(Iterator first, Iterator last) {
+
+  while (first != last) {
+
+    Iterator next(first);
+    last = std::remove(++next, last, *first);
+    first = next;
+
+  }
+
+  return last;
+
+}
+
 bool CmpLogInstructions::hookInstrs(Module &M) {
 
   std::vector<Instruction *> icomps;
+  std::vector<SwitchInst *>  switches;
   LLVMContext &              C = M.getContext();
 
   Type *       VoidTy = Type::getVoidTy(C);
@@ -95,13 +111,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
   IntegerType *Int16Ty = IntegerType::getInt16Ty(C);
   IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
   IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
+  IntegerType *Int128Ty = IntegerType::getInt128Ty(C);
 
 #if LLVM_VERSION_MAJOR < 9
   Constant *
 #else
   FunctionCallee
 #endif
-      c1 = M.getOrInsertFunction("__cmplog_ins_hook1", VoidTy, Int8Ty, Int8Ty
+      c1 = M.getOrInsertFunction("__cmplog_ins_hook1", VoidTy, Int8Ty, Int8Ty,
+                                 Int8Ty
 #if LLVM_VERSION_MAJOR < 5
                                  ,
                                  NULL
@@ -118,7 +136,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 #else
   FunctionCallee
 #endif
-      c2 = M.getOrInsertFunction("__cmplog_ins_hook2", VoidTy, Int16Ty, Int16Ty
+      c2 = M.getOrInsertFunction("__cmplog_ins_hook2", VoidTy, Int16Ty, Int16Ty,
+                                 Int8Ty
 #if LLVM_VERSION_MAJOR < 5
                                  ,
                                  NULL
@@ -135,7 +154,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 #else
   FunctionCallee
 #endif
-      c4 = M.getOrInsertFunction("__cmplog_ins_hook4", VoidTy, Int32Ty, Int32Ty
+      c4 = M.getOrInsertFunction("__cmplog_ins_hook4", VoidTy, Int32Ty, Int32Ty,
+                                 Int8Ty
 #if LLVM_VERSION_MAJOR < 5
                                  ,
                                  NULL
@@ -152,7 +172,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 #else
   FunctionCallee
 #endif
-      c8 = M.getOrInsertFunction("__cmplog_ins_hook8", VoidTy, Int64Ty, Int64Ty
+      c8 = M.getOrInsertFunction("__cmplog_ins_hook8", VoidTy, Int64Ty, Int64Ty,
+                                 Int8Ty
 #if LLVM_VERSION_MAJOR < 5
                                  ,
                                  NULL
@@ -164,6 +185,42 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
   FunctionCallee cmplogHookIns8 = c8;
 #endif
 
+#if LLVM_VERSION_MAJOR < 9
+  Constant *
+#else
+  FunctionCallee
+#endif
+      c16 = M.getOrInsertFunction("__cmplog_ins_hook16", VoidTy, Int128Ty,
+                                  Int128Ty, Int8Ty
+#if LLVM_VERSION_MAJOR < 5
+                                  ,
+                                  NULL
+#endif
+      );
+#if LLVM_VERSION_MAJOR < 9
+  Function *cmplogHookIns16 = cast<Function>(c16);
+#else
+  FunctionCallee cmplogHookIns16 = c16;
+#endif
+
+#if LLVM_VERSION_MAJOR < 9
+  Constant *
+#else
+  FunctionCallee
+#endif
+      cN = M.getOrInsertFunction("__cmplog_ins_hookN", VoidTy, Int128Ty,
+                                 Int128Ty, Int8Ty, Int8Ty
+#if LLVM_VERSION_MAJOR < 5
+                                 ,
+                                 NULL
+#endif
+      );
+#if LLVM_VERSION_MAJOR < 9
+  Function *cmplogHookInsN = cast<Function>(cN);
+#else
+  FunctionCallee cmplogHookInsN = cN;
+#endif
+
   /* iterate over all functions, bbs and instruction and add suitable calls */
   for (auto &F : M) {
 
@@ -174,35 +231,16 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
       for (auto &IN : BB) {
 
         CmpInst *selectcmpInst = nullptr;
-
         if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
 
-          if (selectcmpInst->getPredicate() == CmpInst::ICMP_EQ ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_NE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_UGT ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_SGT ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_ULT ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_SLT ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_UGE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_SGE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_ULE ||
-              selectcmpInst->getPredicate() == CmpInst::ICMP_SLE ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_ULE ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_OLT ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_UEQ ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
-              selectcmpInst->getPredicate() == CmpInst::FCMP_ONE) {
-
-            icomps.push_back(selectcmpInst);
+          icomps.push_back(selectcmpInst);
 
-          }
+        }
+
+        SwitchInst *switchInst = nullptr;
+        if ((switchInst = dyn_cast<SwitchInst>(BB.getTerminator()))) {
+
+          if (switchInst->getNumCases() > 1) { switches.push_back(switchInst); }
 
         }
 
@@ -212,101 +250,477 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
 
   }
 
-  if (!icomps.size()) return false;
-  // if (!be_quiet) errs() << "Hooking " << icomps.size() << " cmp
-  // instructions\n";
+  // unique the collected switches
+  switches.erase(Unique(switches.begin(), switches.end()), switches.end());
+
+  // Instrument switch values for cmplog
+  if (switches.size()) {
+
+    if (!be_quiet)
+      errs() << "Hooking " << switches.size() << " switch instructions\n";
+
+    for (auto &SI : switches) {
+
+      Value *       Val = SI->getCondition();
+      unsigned int  max_size = Val->getType()->getIntegerBitWidth(), cast_size;
+      unsigned char do_cast = 0;
+
+      if (!SI->getNumCases() || max_size <= 8) {
+
+        // if (!be_quiet) errs() << "skip trivial switch..\n";
+        continue;
+
+      }
+
+      IRBuilder<> IRB(SI->getParent());
+      IRB.SetInsertPoint(SI);
+
+      if (max_size % 8) {
+
+        max_size = (((max_size / 8) + 1) * 8);
+        do_cast = 1;
+
+      }
+
+      if (max_size > 128) {
+
+        if (!be_quiet) {
+
+          fprintf(stderr,
+                  "Cannot handle this switch bit size: %u (truncating)\n",
+                  max_size);
+
+        }
+
+        max_size = 128;
+        do_cast = 1;
+
+      }
+
+      // do we need to cast?
+      switch (max_size) {
+
+        case 8:
+        case 16:
+        case 32:
+        case 64:
+        case 128:
+          cast_size = max_size;
+          break;
+        default:
+          cast_size = 128;
+          do_cast = 1;
+
+      }
+
+      Value *CompareTo = Val;
+
+      if (do_cast) {
+
+        ConstantInt *cint = dyn_cast<ConstantInt>(Val);
+        if (cint) {
+
+          uint64_t val = cint->getZExtValue();
+          // fprintf(stderr, "ConstantInt: %lu\n", val);
+          switch (cast_size) {
+
+            case 8:
+              CompareTo = ConstantInt::get(Int8Ty, val);
+              break;
+            case 16:
+              CompareTo = ConstantInt::get(Int16Ty, val);
+              break;
+            case 32:
+              CompareTo = ConstantInt::get(Int32Ty, val);
+              break;
+            case 64:
+              CompareTo = ConstantInt::get(Int64Ty, val);
+              break;
+            case 128:
+              CompareTo = ConstantInt::get(Int128Ty, val);
+              break;
+
+          }
+
+        } else {
+
+          CompareTo = IRB.CreateBitCast(Val, IntegerType::get(C, cast_size));
+
+        }
+
+      }
+
+      for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e;
+           ++i) {
+
+#if LLVM_VERSION_MAJOR < 5
+        ConstantInt *cint = i.getCaseValue();
+#else
+        ConstantInt *cint = i->getCaseValue();
+#endif
+
+        if (cint) {
+
+          std::vector<Value *> args;
+          args.push_back(CompareTo);
+
+          Value *new_param = cint;
 
-  for (auto &selectcmpInst : icomps) {
+          if (do_cast) {
 
-    IRBuilder<> IRB(selectcmpInst->getParent());
-    IRB.SetInsertPoint(selectcmpInst);
+            uint64_t val = cint->getZExtValue();
+            // fprintf(stderr, "ConstantInt: %lu\n", val);
+            switch (cast_size) {
 
-    auto op0 = selectcmpInst->getOperand(0);
-    auto op1 = selectcmpInst->getOperand(1);
+              case 8:
+                new_param = ConstantInt::get(Int8Ty, val);
+                break;
+              case 16:
+                new_param = ConstantInt::get(Int16Ty, val);
+                break;
+              case 32:
+                new_param = ConstantInt::get(Int32Ty, val);
+                break;
+              case 64:
+                new_param = ConstantInt::get(Int64Ty, val);
+                break;
+              case 128:
+                new_param = ConstantInt::get(Int128Ty, val);
+                break;
 
-    IntegerType *        intTyOp0 = NULL;
-    IntegerType *        intTyOp1 = NULL;
-    unsigned             max_size = 0;
-    std::vector<Value *> args;
+            }
 
-    if (selectcmpInst->getOpcode() == Instruction::FCmp) {
+          }
+
+          if (new_param) {
+
+            args.push_back(new_param);
+            ConstantInt *attribute = ConstantInt::get(Int8Ty, 1);
+            args.push_back(attribute);
+            if (cast_size != max_size) {
+
+              ConstantInt *bitsize =
+                  ConstantInt::get(Int8Ty, (max_size / 8) - 1);
+              args.push_back(bitsize);
+
+            }
+
+            switch (cast_size) {
+
+              case 8:
+                IRB.CreateCall(cmplogHookIns1, args);
+                break;
+              case 16:
+                IRB.CreateCall(cmplogHookIns2, args);
+                break;
+              case 32:
+                IRB.CreateCall(cmplogHookIns4, args);
+                break;
+              case 64:
+                IRB.CreateCall(cmplogHookIns8, args);
+                break;
+              case 128:
+#ifdef WORD_SIZE_64
+                if (max_size == 128) {
+
+                  IRB.CreateCall(cmplogHookIns16, args);
+
+                } else {
+
+                  IRB.CreateCall(cmplogHookInsN, args);
+
+                }
 
-      auto ty0 = op0->getType();
-      if (ty0->isHalfTy()
+#endif
+                break;
+              default:
+                break;
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
+
+  if (icomps.size()) {
+
+    // if (!be_quiet) errs() << "Hooking " << icomps.size() <<
+    //                          " cmp instructions\n";
+
+    for (auto &selectcmpInst : icomps) {
+
+      IRBuilder<> IRB(selectcmpInst->getParent());
+      IRB.SetInsertPoint(selectcmpInst);
+
+      Value *op0 = selectcmpInst->getOperand(0);
+      Value *op1 = selectcmpInst->getOperand(1);
+
+      IntegerType *        intTyOp0 = NULL;
+      IntegerType *        intTyOp1 = NULL;
+      unsigned             max_size = 0, cast_size = 0;
+      unsigned char        attr = 0, do_cast = 0;
+      std::vector<Value *> args;
+
+      CmpInst *cmpInst = dyn_cast<CmpInst>(selectcmpInst);
+
+      if (!cmpInst) { continue; }
+
+      switch (cmpInst->getPredicate()) {
+
+        case CmpInst::ICMP_NE:
+        case CmpInst::FCMP_UNE:
+        case CmpInst::FCMP_ONE:
+          break;
+        case CmpInst::ICMP_EQ:
+        case CmpInst::FCMP_UEQ:
+        case CmpInst::FCMP_OEQ:
+          attr += 1;
+          break;
+        case CmpInst::ICMP_UGT:
+        case CmpInst::ICMP_SGT:
+        case CmpInst::FCMP_OGT:
+        case CmpInst::FCMP_UGT:
+          attr += 2;
+          break;
+        case CmpInst::ICMP_UGE:
+        case CmpInst::ICMP_SGE:
+        case CmpInst::FCMP_OGE:
+        case CmpInst::FCMP_UGE:
+          attr += 3;
+          break;
+        case CmpInst::ICMP_ULT:
+        case CmpInst::ICMP_SLT:
+        case CmpInst::FCMP_OLT:
+        case CmpInst::FCMP_ULT:
+          attr += 4;
+          break;
+        case CmpInst::ICMP_ULE:
+        case CmpInst::ICMP_SLE:
+        case CmpInst::FCMP_OLE:
+        case CmpInst::FCMP_ULE:
+          attr += 5;
+          break;
+        default:
+          break;
+
+      }
+
+      if (selectcmpInst->getOpcode() == Instruction::FCmp) {
+
+        auto ty0 = op0->getType();
+        if (ty0->isHalfTy()
 #if LLVM_VERSION_MAJOR >= 11
-          || ty0->isBFloatTy()
+            || ty0->isBFloatTy()
 #endif
-      )
-        max_size = 16;
-      else if (ty0->isFloatTy())
-        max_size = 32;
-      else if (ty0->isDoubleTy())
-        max_size = 64;
+        )
+          max_size = 16;
+        else if (ty0->isFloatTy())
+          max_size = 32;
+        else if (ty0->isDoubleTy())
+          max_size = 64;
+        else if (ty0->isX86_FP80Ty())
+          max_size = 80;
+        else if (ty0->isFP128Ty() || ty0->isPPC_FP128Ty())
+          max_size = 128;
+
+        attr += 8;
+        do_cast = 1;
 
-      if (max_size) {
+      } else {
 
-        Value *V0 = IRB.CreateBitCast(op0, IntegerType::get(C, max_size));
-        intTyOp0 = dyn_cast<IntegerType>(V0->getType());
-        Value *V1 = IRB.CreateBitCast(op1, IntegerType::get(C, max_size));
-        intTyOp1 = dyn_cast<IntegerType>(V1->getType());
+        intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+        intTyOp1 = dyn_cast<IntegerType>(op1->getType());
 
         if (intTyOp0 && intTyOp1) {
 
           max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
                          ? intTyOp0->getBitWidth()
                          : intTyOp1->getBitWidth();
-          args.push_back(V0);
-          args.push_back(V1);
 
-        } else {
+        }
+
+      }
+
+      if (!max_size) { continue; }
+
+      // _ExtInt() with non-8th values
+      if (max_size % 8) {
+
+        max_size = (((max_size / 8) + 1) * 8);
+        do_cast = 1;
+
+      }
+
+      if (max_size > 128) {
 
-          max_size = 0;
+        if (!be_quiet) {
+
+          fprintf(stderr,
+                  "Cannot handle this compare bit size: %u (truncating)\n",
+                  max_size);
 
         }
 
+        max_size = 128;
+        do_cast = 1;
+
       }
 
-    } else {
+      // do we need to cast?
+      switch (max_size) {
+
+        case 8:
+        case 16:
+        case 32:
+        case 64:
+        case 128:
+          cast_size = max_size;
+          break;
+        default:
+          cast_size = 128;
+          do_cast = 1;
 
-      intTyOp0 = dyn_cast<IntegerType>(op0->getType());
-      intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+      }
+
+      if (do_cast) {
+
+        // F*cking LLVM optimized out any kind of bitcasts of ConstantInt values
+        // creating illegal calls. WTF. So we have to work around this.
+
+        ConstantInt *cint = dyn_cast<ConstantInt>(op0);
+        if (cint) {
+
+          uint64_t val = cint->getZExtValue();
+          // fprintf(stderr, "ConstantInt: %lu\n", val);
+          ConstantInt *new_param = NULL;
+          switch (cast_size) {
+
+            case 8:
+              new_param = ConstantInt::get(Int8Ty, val);
+              break;
+            case 16:
+              new_param = ConstantInt::get(Int16Ty, val);
+              break;
+            case 32:
+              new_param = ConstantInt::get(Int32Ty, val);
+              break;
+            case 64:
+              new_param = ConstantInt::get(Int64Ty, val);
+              break;
+            case 128:
+              new_param = ConstantInt::get(Int128Ty, val);
+              break;
 
-      if (intTyOp0 && intTyOp1) {
+          }
+
+          if (!new_param) { continue; }
+          args.push_back(new_param);
+
+        } else {
+
+          Value *V0 = IRB.CreateBitCast(op0, IntegerType::get(C, cast_size));
+          args.push_back(V0);
+
+        }
+
+        cint = dyn_cast<ConstantInt>(op1);
+        if (cint) {
+
+          uint64_t     val = cint->getZExtValue();
+          ConstantInt *new_param = NULL;
+          switch (cast_size) {
+
+            case 8:
+              new_param = ConstantInt::get(Int8Ty, val);
+              break;
+            case 16:
+              new_param = ConstantInt::get(Int16Ty, val);
+              break;
+            case 32:
+              new_param = ConstantInt::get(Int32Ty, val);
+              break;
+            case 64:
+              new_param = ConstantInt::get(Int64Ty, val);
+              break;
+            case 128:
+              new_param = ConstantInt::get(Int128Ty, val);
+              break;
+
+          }
+
+          if (!new_param) { continue; }
+          args.push_back(new_param);
+
+        } else {
+
+          Value *V1 = IRB.CreateBitCast(op1, IntegerType::get(C, cast_size));
+          args.push_back(V1);
+
+        }
+
+      } else {
 
-        max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
-                       ? intTyOp0->getBitWidth()
-                       : intTyOp1->getBitWidth();
         args.push_back(op0);
         args.push_back(op1);
 
       }
 
-    }
+      ConstantInt *attribute = ConstantInt::get(Int8Ty, attr);
+      args.push_back(attribute);
+
+      if (cast_size != max_size) {
+
+        ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1);
+        args.push_back(bitsize);
+
+      }
+
+      // fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast %u\n",
+      //         max_size, cast_size, attr, do_cast);
+
+      switch (cast_size) {
 
-    if (max_size < 8 || max_size > 64 || !intTyOp0 || !intTyOp1) continue;
-
-    switch (max_size) {
-
-      case 8:
-        IRB.CreateCall(cmplogHookIns1, args);
-        break;
-      case 16:
-        IRB.CreateCall(cmplogHookIns2, args);
-        break;
-      case 32:
-        IRB.CreateCall(cmplogHookIns4, args);
-        break;
-      case 64:
-        IRB.CreateCall(cmplogHookIns8, args);
-        break;
-      default:
-        break;
+        case 8:
+          IRB.CreateCall(cmplogHookIns1, args);
+          break;
+        case 16:
+          IRB.CreateCall(cmplogHookIns2, args);
+          break;
+        case 32:
+          IRB.CreateCall(cmplogHookIns4, args);
+          break;
+        case 64:
+          IRB.CreateCall(cmplogHookIns8, args);
+          break;
+        case 128:
+          if (max_size == 128) {
+
+            IRB.CreateCall(cmplogHookIns16, args);
+
+          } else {
+
+            IRB.CreateCall(cmplogHookInsN, args);
+
+          }
+
+          break;
+
+      }
 
     }
 
   }
 
-  return true;
+  if (switches.size() || icomps.size())
+    return true;
+  else
+    return false;
 
 }
 
diff --git a/instrumentation/llvm-ngram-coverage.h b/instrumentation/llvm-ngram-coverage.h
index 12b666e9..666839c8 100644
--- a/instrumentation/llvm-ngram-coverage.h
+++ b/instrumentation/llvm-ngram-coverage.h
@@ -1,7 +1,7 @@
 #ifndef AFL_NGRAM_CONFIG_H
 #define AFL_NGRAM_CONFIG_H
 
-#include "../config.h"
+#include "types.h"
 
 #if (MAP_SIZE_POW2 <= 16)
 typedef u16 PREV_LOC_T;