aboutsummaryrefslogtreecommitdiff
path: root/instrumentation
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-01-15 16:56:40 +0100
committervan Hauser <vh@thc.org>2021-01-15 16:56:40 +0100
commita0e884cf8bffe1a0394d106375f6a23edd2b60e6 (patch)
treeff1b4a01977ef9c133ec8dd8cbdd1b9db5a0367f /instrumentation
parentfba8790e322ab933df9851f0cf6ce9ca941f3814 (diff)
downloadAFLplusplus-a0e884cf8bffe1a0394d106375f6a23edd2b60e6.tar.gz
merge cmplog
Diffstat (limited to 'instrumentation')
-rw-r--r--instrumentation/afl-compiler-rt.o.c89
-rw-r--r--instrumentation/cmplog-instructions-pass.cc586
2 files changed, 580 insertions, 95 deletions
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index b735d8df..5d75af78 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,7 +1207,9 @@ 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) {
+
+ // fprintf(stderr, "hook1 arg0=%02x arg1=%02x attr=%u\n", arg1, arg2, attr);
if (unlikely(!__afl_cmp_map)) return;
@@ -1216,6 +1218,7 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+ __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
@@ -1230,7 +1233,7 @@ 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;
@@ -1239,6 +1242,7 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+ __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
@@ -1251,7 +1255,9 @@ 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) {
+
+ // fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
if (unlikely(!__afl_cmp_map)) return;
@@ -1260,6 +1266,7 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+ __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
@@ -1272,7 +1279,9 @@ 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) {
+
+ // fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
if (unlikely(!__afl_cmp_map)) return;
@@ -1281,6 +1290,7 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) {
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+ __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
@@ -1293,16 +1303,77 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) {
}
+// 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)) 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;
+ __afl_cmp_map->headers[k].attribute = attr;
+
+ u32 hits = __afl_cmp_map->headers[k].hits;
+ __afl_cmp_map->headers[k].hits = hits + 1;
+
+ __afl_cmp_map->headers[k].shape = size;
+
+ 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;
+
+ __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+ __afl_cmp_map->headers[k].attribute = attr;
+
+ u32 hits = __afl_cmp_map->headers[k].hits;
+ __afl_cmp_map->headers[k].hits = hits + 1;
+
+ __afl_cmp_map->headers[k].shape = 15;
+
+ 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);
+
+}
+
#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 +1383,8 @@ 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")));
+void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2)
+ __attribute__((alias("__cmplog_ins_hook16")));
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2)
__attribute__((alias("__cmplog_ins_hook1")));
@@ -1321,6 +1394,8 @@ 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")));
+void __sanitizer_cov_trace_cmp16(uint128_t arg1, uint128_t arg2)
+ __attribute__((alias("__cmplog_ins_hook16")));
#endif /* defined(__APPLE__) */
void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc
index 3499ccf0..a74fb6c8 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,473 @@ 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 &selectcmpInst : icomps) {
+ for (auto &SI : switches) {
- IRBuilder<> IRB(selectcmpInst->getParent());
- IRB.SetInsertPoint(selectcmpInst);
+ Value * Val = SI->getCondition();
+ unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size;
+ unsigned char do_cast = 0;
- auto op0 = selectcmpInst->getOperand(0);
- auto op1 = selectcmpInst->getOperand(1);
+ if (!SI->getNumCases() || max_size <= 8) {
- IntegerType * intTyOp0 = NULL;
- IntegerType * intTyOp1 = NULL;
- unsigned max_size = 0;
- std::vector<Value *> args;
+ // if (!be_quiet) errs() << "skip trivial switch..\n";
+ continue;
- if (selectcmpInst->getOpcode() == Instruction::FCmp) {
+ }
+
+ 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;
+
+ }
- auto ty0 = op0->getType();
- if (ty0->isHalfTy()
+ } 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;
+
+ if (do_cast) {
+
+ uint64_t val = cint->getZExtValue();
+ // fprintf(stderr, "ConstantInt: %lu\n", val);
+ 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) {
+
+ 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:
+ if (max_size == 128) {
+
+ IRB.CreateCall(cmplogHookIns16, args);
+
+ } else {
+
+ IRB.CreateCall(cmplogHookInsN, args);
+
+ }
+
+ 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) {
+
+ if (!be_quiet) {
- max_size = 0;
+ fprintf(stderr,
+ "Cannot handle this compare 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;
+
}
- } else {
+ 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 (!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);
- intTyOp0 = dyn_cast<IntegerType>(op0->getType());
- intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+ }
- if (intTyOp0 && intTyOp1) {
+ } 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;
}