Skip to content

Commit

Permalink
Inline cmplog (AFLplusplus#996)
Browse files Browse the repository at this point in the history
* inline cmplog check

* better switch support

* add cmplog-switches-pass.cc
  • Loading branch information
vanhauser-thc authored Jun 28, 2021
1 parent 7038e56 commit 046a952
Show file tree
Hide file tree
Showing 5 changed files with 528 additions and 183 deletions.
5 changes: 4 additions & 1 deletion GNUmakefile.llvm
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ ifeq "$(TEST_MMAP)" "1"
endif

PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so
PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so

# If prerequisites are not given, warn, do not build anything, and exit with code 0
ifeq "$(LLVMVER)" ""
Expand Down Expand Up @@ -433,6 +433,9 @@ endif
./cmplog-instructions-pass.so: instrumentation/cmplog-instructions-pass.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o

./cmplog-switches-pass.so: instrumentation/cmplog-switches-pass.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o

afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o

Expand Down
184 changes: 22 additions & 162 deletions instrumentation/cmplog-instructions-pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ Iterator Unique(Iterator first, Iterator last) {
bool CmpLogInstructions::hookInstrs(Module &M) {

std::vector<Instruction *> icomps;
std::vector<SwitchInst *> switches;
LLVMContext & C = M.getContext();

Type * VoidTy = Type::getVoidTy(C);
Expand Down Expand Up @@ -222,6 +221,18 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
FunctionCallee cmplogHookInsN = cN;
#endif

GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map");

if (!AFLCmplogPtr) {

AFLCmplogPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
GlobalValue::ExternalWeakLinkage, 0,
"__afl_cmp_map");

}

Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0));

/* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) {

Expand All @@ -238,164 +249,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) {

}

SwitchInst *switchInst = nullptr;
if ((switchInst = dyn_cast<SwitchInst>(BB.getTerminator()))) {

if (switchInst->getNumCases() > 1) { switches.push_back(switchInst); }

}

}

}

}

// 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 < 16) {

// if (!be_quiet) errs() << "skip trivial switch..\n";
continue;

}

if (max_size % 8) {

max_size = (((max_size / 8) + 1) * 8);
do_cast = 1;

}

IRBuilder<> IRB(SI->getParent());
IRB.SetInsertPoint(SI);

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) {

CompareTo =
IRB.CreateIntCast(CompareTo, IntegerType::get(C, cast_size), false);

}

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) {

new_param =
IRB.CreateIntCast(cint, IntegerType::get(C, cast_size), false);

}

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);

}

#endif
break;
default:
break;

}

}

}

}

}
Expand All @@ -409,8 +262,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) {

for (auto &selectcmpInst : icomps) {

IRBuilder<> IRB(selectcmpInst->getParent());
IRB.SetInsertPoint(selectcmpInst);
IRBuilder<> IRB2(selectcmpInst->getParent());
IRB2.SetInsertPoint(selectcmpInst);
LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm =
SplitBlockAndInsertIfThen(is_not_null, selectcmpInst, false);

IRBuilder<> IRB(ThenTerm);

Value *op0 = selectcmpInst->getOperand(0);
Value *op1 = selectcmpInst->getOperand(1);
Expand Down Expand Up @@ -601,7 +461,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {

}

if (switches.size() || icomps.size())
if (icomps.size())
return true;
else
return false;
Expand Down
67 changes: 57 additions & 10 deletions instrumentation/cmplog-routines-pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ bool CmpLogRoutines::hookRtns(Module &M) {
FunctionCallee cmplogGccStdC = c4;
#endif

GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map");

if (!AFLCmplogPtr) {

AFLCmplogPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
GlobalValue::ExternalWeakLinkage, 0,
"__afl_cmp_map");

}

Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0));

/* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) {

Expand Down Expand Up @@ -289,8 +301,15 @@ bool CmpLogRoutines::hookRtns(Module &M) {

Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);

IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);

LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);

IRBuilder<> IRB(ThenTerm);

std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Expand All @@ -308,8 +327,15 @@ bool CmpLogRoutines::hookRtns(Module &M) {

Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);

IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);

LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);

IRBuilder<> IRB(ThenTerm);

std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Expand All @@ -327,8 +353,15 @@ bool CmpLogRoutines::hookRtns(Module &M) {

Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);

IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);

LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);

IRBuilder<> IRB(ThenTerm);

std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Expand All @@ -346,8 +379,15 @@ bool CmpLogRoutines::hookRtns(Module &M) {

Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);

IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);

LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);

IRBuilder<> IRB(ThenTerm);

std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Expand All @@ -365,8 +405,15 @@ bool CmpLogRoutines::hookRtns(Module &M) {

Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);

IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);

LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);

IRBuilder<> IRB(ThenTerm);

std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Expand Down
Loading

0 comments on commit 046a952

Please sign in to comment.