aboutsummaryrefslogtreecommitdiff
path: root/instrumentation
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-01-21 12:03:21 +0100
committerGitHub <noreply@github.com>2021-01-21 12:03:21 +0100
commitfc3f06caec887b807e13eeb8be4c9899ec04036a (patch)
tree1884eab7e5e1db9d4c9a00439fdb1589f15bc410 /instrumentation
parentb39b87b2f720926645ac5ae23fd49dec7e94c7e9 (diff)
parent0d472adef0cbe68cec128b7b15e508f0bb05455d (diff)
downloadAFLplusplus-fc3f06caec887b807e13eeb8be4c9899ec04036a.tar.gz
Merge pull request #689 from AFLplusplus/cmplog_merge
cmplog merge
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;