C(pp) formatting & autotokens fix (#614)

* fix

* a

* format

* .clang-format
This commit is contained in:
Dongjia Zhang 2022-05-04 03:42:43 +09:00 committed by GitHub
parent b0dd25ee95
commit 6b76e53bfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 408 additions and 454 deletions

148
.clang-format Normal file
View File

@ -0,0 +1,148 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: BeforeHash
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 8
UseTab: Never
...

View File

@ -2,8 +2,6 @@
//! They may be inserted as part of mutations during fuzzing. //! They may be inserted as part of mutations during fuzzing.
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::mutators::str_decode; use crate::mutators::str_decode;
#[cfg(target_os = "linux")]
use alloc::string::ToString;
use alloc::vec::Vec; use alloc::vec::Vec;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use core::slice::from_raw_parts; use core::slice::from_raw_parts;
@ -110,9 +108,9 @@ impl Tokens {
pub unsafe fn from_ptrs(token_start: *const u8, token_stop: *const u8) -> Result<Self, Error> { pub unsafe fn from_ptrs(token_start: *const u8, token_stop: *const u8) -> Result<Self, Error> {
let mut ret = Self::default(); let mut ret = Self::default();
if token_start.is_null() || token_stop.is_null() { if token_start.is_null() || token_stop.is_null() {
return Err(Error::IllegalArgument("token_start or token_stop is null. If you are using autotokens() you likely did not build your target with the \"AutoTokens\"-pass".to_string())); return Ok(Self::new());
} }
if token_stop <= token_start { if token_stop < token_start {
return Err(Error::IllegalArgument(format!( return Err(Error::IllegalArgument(format!(
"Tried to create tokens from illegal section: stop < start ({:?} < {:?})", "Tried to create tokens from illegal section: stop < start ({:?} < {:?})",
token_stop, token_start token_stop, token_start

View File

@ -72,15 +72,35 @@ typedef uint32_t prev_loc_t;
using namespace llvm; using namespace llvm;
static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false), cl::NotHidden); static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false),
static cl::opt<uint32_t> InstRatio("inst_ratio", cl::desc("Instrumentation ratio in percentage"), cl::init(100), cl::NotHidden); cl::NotHidden);
static cl::opt<bool> NotZero("not_zero", cl::desc("Never hit 0 again in the hitcount"), cl::init(true), cl::NotHidden); static cl::opt<uint32_t> InstRatio(
static cl::opt<uint32_t> Ngram("ngram", cl::desc("Size of the Ngram instrumentation (0 to disable)"), cl::init(0), cl::NotHidden); "inst_ratio", cl::desc("Instrumentation ratio in percentage"),
static cl::opt<uint32_t> CtxK("ctx_k", cl::desc("Size of the context for K-Ctx context sensitivity (0 to disable)"), cl::init(0), cl::NotHidden); cl::init(100), cl::NotHidden);
static cl::opt<bool> Ctx("ctx", cl::desc("Enable full context sensitive coverage"), cl::init(false), cl::NotHidden); static cl::opt<bool> NotZero("not_zero",
static cl::opt<bool> ThreadSafe("thread_safe", cl::desc("Use the thread safe instrumentation"), cl::init(false), cl::NotHidden); cl::desc("Never hit 0 again in the hitcount"),
static cl::opt<bool> DumpCFG("dump_afl_cfg", cl::desc("Dump CFG containing AFL-style edge index"), cl::init(false), cl::NotHidden); cl::init(true), cl::NotHidden);
static cl::opt<std::string> DumpCFGPath("dump_afl_cfg_path", cl::desc("Path to dump CFG containing AFL-style edge index"), cl::init(".cfg"), cl::NotHidden); static cl::opt<uint32_t> Ngram(
"ngram", cl::desc("Size of the Ngram instrumentation (0 to disable)"),
cl::init(0), cl::NotHidden);
static cl::opt<uint32_t> CtxK(
"ctx_k",
cl::desc(
"Size of the context for K-Ctx context sensitivity (0 to disable)"),
cl::init(0), cl::NotHidden);
static cl::opt<bool> Ctx("ctx",
cl::desc("Enable full context sensitive coverage"),
cl::init(false), cl::NotHidden);
static cl::opt<bool> ThreadSafe("thread_safe",
cl::desc("Use the thread safe instrumentation"),
cl::init(false), cl::NotHidden);
static cl::opt<bool> DumpCFG(
"dump_afl_cfg", cl::desc("Dump CFG containing AFL-style edge index"),
cl::init(false), cl::NotHidden);
static cl::opt<std::string> DumpCFGPath(
"dump_afl_cfg_path",
cl::desc("Path to dump CFG containing AFL-style edge index"),
cl::init(".cfg"), cl::NotHidden);
namespace { namespace {
@ -96,7 +116,6 @@ class AFLCoverage : public ModulePass {
#endif #endif
// initInstrumentList(); // initInstrumentList();
} }
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -106,11 +125,10 @@ class AFLCoverage : public ModulePass {
#endif #endif
protected: protected:
uint32_t map_size = MAP_SIZE; uint32_t map_size = MAP_SIZE;
uint32_t function_minimum_size = 1; uint32_t function_minimum_size = 1;
DenseMap<BasicBlock *, int32_t> bb_to_cur_loc; DenseMap<BasicBlock *, int32_t> bb_to_cur_loc;
DenseMap<StringRef, BasicBlock *> entry_bb; DenseMap<StringRef, BasicBlock *> entry_bb;
}; };
} // namespace } // namespace
@ -118,33 +136,30 @@ class AFLCoverage : public ModulePass {
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() { llvmGetPassPluginInfo() {
return { return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1",
LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", /* lambda to insert our pass into the pass pipeline. */
/* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) {
[](PassBuilder &PB) { #if 1
#if 1 using OptimizationLevel = typename PassBuilder::OptimizationLevel;
using OptimizationLevel = typename PassBuilder::OptimizationLevel; PB.registerOptimizerLastEPCallback(
PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(AFLCoverage());
MPM.addPass(AFLCoverage()); });
} /* TODO LTO registration */
); #else
/* TODO LTO registration */ using PipelineElement = typename PassBuilder::PipelineElement;
#else PB.registerPipelineParsingCallback([](StringRef Name,
using PipelineElement = typename PassBuilder::PipelineElement; ModulePassManager &MPM,
PB.registerPipelineParsingCallback( ArrayRef<PipelineElement>) {
[](StringRef Name, ModulePassManager &MPM, ArrayRef<PipelineElement>) { if (Name == "AFLCoverage") {
if ( Name == "AFLCoverage" ) { MPM.addPass(AFLCoverage());
MPM.addPass(AFLCoverage()); return true;
return true; } else {
} else { return false;
return false; }
} });
} #endif
); }};
#endif
}
};
} }
#else #else
@ -156,7 +171,10 @@ PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) {
#else #else
bool AFLCoverage::runOnModule(Module &M) { bool AFLCoverage::runOnModule(Module &M) {
#endif #endif
if (Ctx && DumpCFG) FATAL("Does not support dumping CFG with full context sensitive coverage enabled."); if (Ctx && DumpCFG)
FATAL(
"Does not support dumping CFG with full context sensitive coverage "
"enabled.");
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
@ -165,7 +183,7 @@ bool AFLCoverage::runOnModule(Module &M) {
IntegerType *IntLocTy = IntegerType *IntLocTy =
IntegerType::getIntNTy(C, sizeof(prev_loc_t) * CHAR_BIT); IntegerType::getIntNTy(C, sizeof(prev_loc_t) * CHAR_BIT);
#endif #endif
uint32_t rand_seed; uint32_t rand_seed;
unsigned int cur_loc = 0; unsigned int cur_loc = 0;
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -205,10 +223,10 @@ bool AFLCoverage::runOnModule(Module &M) {
VectorType *PrevLocTy = NULL; VectorType *PrevLocTy = NULL;
if (Ngram && (Ngram < 2 || Ngram > NGRAM_SIZE_MAX)) if (Ngram && (Ngram < 2 || Ngram > NGRAM_SIZE_MAX))
FATAL( FATAL(
"Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX " "Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX "
"(%u))", "(%u))",
NGRAM_SIZE_MAX); NGRAM_SIZE_MAX);
if (Ngram) if (Ngram)
PrevLocSize = Ngram - 1; PrevLocSize = Ngram - 1;
@ -219,22 +237,20 @@ bool AFLCoverage::runOnModule(Module &M) {
VectorType *PrevCallerTy = NULL; VectorType *PrevCallerTy = NULL;
if (CtxK > CTX_MAX_K) if (CtxK > CTX_MAX_K)
FATAL("Bad value of K for K-context sensitivity (must be between 1 and CTX_MAX_K (%u))", FATAL(
CTX_MAX_K); "Bad value of K for K-context sensitivity (must be between 1 and "
"CTX_MAX_K (%u))",
CTX_MAX_K);
if (CtxK == 1) { if (CtxK == 1) {
CtxK = 0; CtxK = 0;
instrument_ctx = true; instrument_ctx = true;
instrument_caller = true; // Enable CALLER instead instrument_caller = true; // Enable CALLER instead
} }
if (CtxK) { if (CtxK) {
PrevCallerSize = CtxK; PrevCallerSize = CtxK;
instrument_ctx = true; instrument_ctx = true;
} }
#else #else
@ -371,11 +387,10 @@ bool AFLCoverage::runOnModule(Module &M) {
Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle); Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
Constant * PrevCallerShuffleMask = NULL; Constant *PrevCallerShuffleMask = NULL;
SmallVector<Constant *, 32> PrevCallerShuffle = {UndefValue::get(Int32Ty)}; SmallVector<Constant *, 32> PrevCallerShuffle = {UndefValue::get(Int32Ty)};
if (CtxK) { if (CtxK) {
for (unsigned I = 0; I < PrevCallerSize - 1; ++I) for (unsigned I = 0; I < PrevCallerSize - 1; ++I)
PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, I)); PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, I));
@ -383,7 +398,6 @@ bool AFLCoverage::runOnModule(Module &M) {
PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, PrevCallerSize)); PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, PrevCallerSize));
PrevCallerShuffleMask = ConstantVector::get(PrevCallerShuffle); PrevCallerShuffleMask = ConstantVector::get(PrevCallerShuffle);
} }
#endif #endif
@ -391,7 +405,7 @@ bool AFLCoverage::runOnModule(Module &M) {
// other constants we need // other constants we need
ConstantInt *One = ConstantInt::get(Int8Ty, 1); ConstantInt *One = ConstantInt::get(Int8Ty, 1);
Value * PrevCtx = NULL; // CTX sensitive coverage Value *PrevCtx = NULL; // CTX sensitive coverage
LoadInst *PrevCaller = NULL; // K-CTX coverage LoadInst *PrevCaller = NULL; // K-CTX coverage
/* Instrument all the things! */ /* Instrument all the things! */
@ -400,7 +414,6 @@ bool AFLCoverage::runOnModule(Module &M) {
// scanForDangerousFunctions(&M); // scanForDangerousFunctions(&M);
for (auto &F : M) { for (auto &F : M) {
int has_calls = 0; int has_calls = 0;
if (Debug) if (Debug)
fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(), fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(),
@ -413,16 +426,13 @@ bool AFLCoverage::runOnModule(Module &M) {
std::list<Value *> todo; std::list<Value *> todo;
for (auto &BB : F) { for (auto &BB : F) {
BasicBlock::iterator IP = BB.getFirstInsertionPt(); BasicBlock::iterator IP = BB.getFirstInsertionPt();
IRBuilder<> IRB(&(*IP)); IRBuilder<> IRB(&(*IP));
// Context sensitive coverage // Context sensitive coverage
if (instrument_ctx && &BB == &F.getEntryBlock()) { if (instrument_ctx && &BB == &F.getEntryBlock()) {
#ifdef HAVE_VECTOR_INTRINSICS #ifdef HAVE_VECTOR_INTRINSICS
if (CtxK) { if (CtxK) {
PrevCaller = IRB.CreateLoad(AFLPrevCaller); PrevCaller = IRB.CreateLoad(AFLPrevCaller);
PrevCaller->setMetadata(M.getMDKindID("nosanitize"), PrevCaller->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None)); MDNode::get(C, None));
@ -430,7 +440,6 @@ bool AFLCoverage::runOnModule(Module &M) {
IRB.CreateZExt(IRB.CreateXorReduce(PrevCaller), IRB.getInt32Ty()); IRB.CreateZExt(IRB.CreateXorReduce(PrevCaller), IRB.getInt32Ty());
} else } else
#endif #endif
{ {
@ -440,42 +449,31 @@ bool AFLCoverage::runOnModule(Module &M) {
PrevCtxLoad->setMetadata(M.getMDKindID("nosanitize"), PrevCtxLoad->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None)); MDNode::get(C, None));
PrevCtx = PrevCtxLoad; PrevCtx = PrevCtxLoad;
} }
// does the function have calls? and is any of the calls larger than one // does the function have calls? and is any of the calls larger than one
// basic block? // basic block?
for (auto &BB_2 : F) { for (auto &BB_2 : F) {
if (has_calls) break; if (has_calls) break;
for (auto &IN : BB_2) { for (auto &IN : BB_2) {
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction(); Function *Callee = callInst->getCalledFunction();
if (!Callee || Callee->size() < function_minimum_size) if (!Callee || Callee->size() < function_minimum_size)
continue; continue;
else { else {
has_calls = 1; has_calls = 1;
break; break;
} }
} }
} }
} }
// if yes we store a context ID for this function in the global var // if yes we store a context ID for this function in the global var
if (has_calls) { if (has_calls) {
Value *NewCtx = ConstantInt::get(Int32Ty, RandBelow(map_size)); Value *NewCtx = ConstantInt::get(Int32Ty, RandBelow(map_size));
#ifdef HAVE_VECTOR_INTRINSICS #ifdef HAVE_VECTOR_INTRINSICS
if (CtxK) { if (CtxK) {
Value *ShuffledPrevCaller = IRB.CreateShuffleVector( Value *ShuffledPrevCaller = IRB.CreateShuffleVector(
PrevCaller, UndefValue::get(PrevCallerTy), PrevCaller, UndefValue::get(PrevCallerTy),
PrevCallerShuffleMask); PrevCallerShuffleMask);
@ -488,7 +486,6 @@ bool AFLCoverage::runOnModule(Module &M) {
MDNode::get(C, None)); MDNode::get(C, None));
} else } else
#endif #endif
{ {
@ -496,11 +493,8 @@ bool AFLCoverage::runOnModule(Module &M) {
StoreInst *StoreCtx = IRB.CreateStore(NewCtx, AFLContext); StoreInst *StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
StoreCtx->setMetadata(M.getMDKindID("nosanitize"), StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None)); MDNode::get(C, None));
} }
} }
} }
if (RandBelow(100) >= InstRatio) continue; if (RandBelow(100) >= InstRatio) continue;
@ -523,7 +517,6 @@ bool AFLCoverage::runOnModule(Module &M) {
// fprintf(stderr, "BB %u: ", cur_loc); // fprintf(stderr, "BB %u: ", cur_loc);
for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); PI != E; for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); PI != E;
++PI) { ++PI) {
BasicBlock *Pred = *PI; BasicBlock *Pred = *PI;
int count = 0; int count = 0;
@ -532,30 +525,24 @@ bool AFLCoverage::runOnModule(Module &M) {
for (succ_iterator SI = succ_begin(Pred), E = succ_end(Pred); SI != E; for (succ_iterator SI = succ_begin(Pred), E = succ_end(Pred); SI != E;
++SI) { ++SI) {
BasicBlock *Succ = *SI; BasicBlock *Succ = *SI;
// if (count > 0) // if (count > 0)
// fprintf(stderr, "|"); // fprintf(stderr, "|");
if (Succ != NULL) count++; if (Succ != NULL) count++;
// fprintf(stderr, "%p", Succ); // fprintf(stderr, "%p", Succ);
} }
if (count > 1) more_than_one = 1; if (count > 1) more_than_one = 1;
} }
// fprintf(stderr, " == %d\n", more_than_one); // fprintf(stderr, " == %d\n", more_than_one);
if (F.size() > 1 && more_than_one != 1) { if (F.size() > 1 && more_than_one != 1) {
// in CTX mode we have to restore the original context for the caller - // in CTX mode we have to restore the original context for the caller -
// she might be calling other functions which need the correct CTX // she might be calling other functions which need the correct CTX
if (instrument_ctx && has_calls) { if (instrument_ctx && has_calls) {
Instruction *Inst = BB.getTerminator(); Instruction *Inst = BB.getTerminator();
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) { if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
IRBuilder<> Post_IRB(Inst); IRBuilder<> Post_IRB(Inst);
StoreInst *RestoreCtx; StoreInst *RestoreCtx;
@ -567,13 +554,10 @@ bool AFLCoverage::runOnModule(Module &M) {
RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext);
RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None)); MDNode::get(C, None));
} }
} }
continue; continue;
} }
#endif #endif
@ -630,23 +614,23 @@ bool AFLCoverage::runOnModule(Module &M) {
/* Update bitmap */ /* Update bitmap */
if (ThreadSafe) { /* Atomic */ if (ThreadSafe) { /* Atomic */
/* /*
#if LLVM_VERSION_MAJOR < 9 #if LLVM_VERSION_MAJOR < 9
if (neverZero_counters_str != if (neverZero_counters_str !=
NULL) { // with llvm 9 we make this the default as the bug NULL) { // with llvm 9 we make this the default as the bug
in llvm in llvm
// is then fixed // is then fixed
#else #else
if (NotZero) { if (NotZero) {
#endif #endif
// register MapPtrIdx in a todo list // register MapPtrIdx in a todo list
todo.push_back(MapPtrIdx); todo.push_back(MapPtrIdx);
} else { } else {
*/ */
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
#if LLVM_VERSION_MAJOR >= 13 #if LLVM_VERSION_MAJOR >= 13
llvm::MaybeAlign(1), llvm::MaybeAlign(1),
@ -659,7 +643,6 @@ bool AFLCoverage::runOnModule(Module &M) {
*/ */
} else { } else {
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
@ -688,13 +671,12 @@ bool AFLCoverage::runOnModule(Module &M) {
auto cf = IRB.CreateICmpEQ(Incr, Zero); auto cf = IRB.CreateICmpEQ(Incr, Zero);
auto carry = IRB.CreateZExt(cf, Int8Ty); auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry); Incr = IRB.CreateAdd(Incr, carry);
} }
IRB.CreateStore(Incr, MapPtrIdx) IRB.CreateStore(Incr, MapPtrIdx)
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
} /* non atomic case */ } /* non atomic case */
/* Update prev_loc history vector (by placing cur_loc at the head of the /* Update prev_loc history vector (by placing cur_loc at the head of the
vector and shuffle the other elements back by one) */ vector and shuffle the other elements back by one) */
@ -703,7 +685,6 @@ bool AFLCoverage::runOnModule(Module &M) {
#ifdef HAVE_VECTOR_INTRINSICS #ifdef HAVE_VECTOR_INTRINSICS
if (Ngram) { if (Ngram) {
Value *ShuffledPrevLoc = IRB.CreateShuffleVector( Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask); PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask);
Value *UpdatedPrevLoc = IRB.CreateInsertElement( Value *UpdatedPrevLoc = IRB.CreateInsertElement(
@ -713,24 +694,20 @@ bool AFLCoverage::runOnModule(Module &M) {
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
} else } else
#endif #endif
{ {
Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1),
AFLPrevLoc); AFLPrevLoc);
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
} }
// in CTX mode we have to restore the original context for the caller - // in CTX mode we have to restore the original context for the caller -
// she might be calling other functions which need the correct CTX. // she might be calling other functions which need the correct CTX.
// Currently this is only needed for the Ubuntu clang-6.0 bug // Currently this is only needed for the Ubuntu clang-6.0 bug
if (instrument_ctx && has_calls) { if (instrument_ctx && has_calls) {
Instruction *Inst = BB.getTerminator(); Instruction *Inst = BB.getTerminator();
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) { if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
IRBuilder<> Post_IRB(Inst); IRBuilder<> Post_IRB(Inst);
StoreInst *RestoreCtx; StoreInst *RestoreCtx;
@ -742,39 +719,37 @@ bool AFLCoverage::runOnModule(Module &M) {
RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext);
RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None)); MDNode::get(C, None));
} }
} }
inst_blocks++; inst_blocks++;
} }
} }
if (DumpCFG) { if (DumpCFG) {
int fd; int fd;
if ((fd = open(DumpCFGPath.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644)) < 0) if ((fd = open(DumpCFGPath.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644)) <
0)
FATAL("Could not open/create CFG dump file."); FATAL("Could not open/create CFG dump file.");
std::string cfg = ""; std::string cfg = "";
for (auto record = entry_bb.begin(); record != entry_bb.end(); record++) { for (auto record = entry_bb.begin(); record != entry_bb.end(); record++) {
// Dump function BB entry points // Dump function BB entry points
cfg += formatv("$${0}+{1}\n", record->getFirst(), bb_to_cur_loc[record->getSecond()]); cfg += formatv("$${0}+{1}\n", record->getFirst(),
bb_to_cur_loc[record->getSecond()]);
} }
for (auto record = bb_to_cur_loc.begin(); record != bb_to_cur_loc.end(); record++) { for (auto record = bb_to_cur_loc.begin(); record != bb_to_cur_loc.end();
record++) {
// Dump CFG information // Dump CFG information
auto current_bb = record->getFirst(); auto current_bb = record->getFirst();
Function* calling_func = current_bb->getParent(); Function *calling_func = current_bb->getParent();
if (calling_func) { if (calling_func) {
auto function_name = calling_func->getName().str(); auto function_name = calling_func->getName().str();
cfg += formatv("%%{0}", function_name); cfg += formatv("%%{0}", function_name);
} } else
else
cfg += "%%__"; cfg += "%%__";
auto current_cur_loc = record->getSecond(); auto current_cur_loc = record->getSecond();
cfg += formatv("+{0}\n", current_cur_loc); cfg += formatv("+{0}\n", current_cur_loc);
for (auto bb_successor = succ_begin(current_bb); for (auto bb_successor = succ_begin(current_bb);
bb_successor != succ_end(current_bb); bb_successor++) { bb_successor != succ_end(current_bb); bb_successor++) {
cfg += formatv("->{0}\n", bb_to_cur_loc[*bb_successor]).str(); cfg += formatv("->{0}\n", bb_to_cur_loc[*bb_successor]).str();
} }
} }
@ -804,14 +779,13 @@ bool AFLCoverage::runOnModule(Module &M) {
} }
}*/ }*/
if (Debug) {
if (Debug) {
if (!inst_blocks) if (!inst_blocks)
fprintf(stderr, "No instrumentation targets found.\n"); fprintf(stderr, "No instrumentation targets found.\n");
else else
fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks, (unsigned)InstRatio); fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks,
(unsigned)InstRatio);
} }
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -819,15 +793,12 @@ bool AFLCoverage::runOnModule(Module &M) {
#else #else
return true; return true;
#endif #endif
} }
#ifndef USE_NEW_PM #ifndef USE_NEW_PM
static void registerAFLPass(const PassManagerBuilder &, static void registerAFLPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
PM.add(new AFLCoverage()); PM.add(new AFLCoverage());
} }
static RegisterStandardPasses RegisterAFLPass( static RegisterStandardPasses RegisterAFLPass(

View File

@ -64,12 +64,11 @@
#include <iostream> #include <iostream>
#define FATAL(x...) \ #define FATAL(x...) \
do { \ do { \
\ fprintf(stderr, "FATAL: " x); \
fprintf(stderr, "FATAL: " x); \ exit(1); \
exit(1); \ \
\
} while (0) } while (0)
using namespace llvm; using namespace llvm;
@ -79,7 +78,6 @@ namespace {
/* Function that we never instrument or analyze */ /* Function that we never instrument or analyze */
/* Note: this ignore check is also called in isInInstrumentList() */ /* Note: this ignore check is also called in isInInstrumentList() */
bool isIgnoreFunction(const llvm::Function *F) { bool isIgnoreFunction(const llvm::Function *F) {
// Starting from "LLVMFuzzer" these are functions used in libfuzzer based // Starting from "LLVMFuzzer" these are functions used in libfuzzer based
// fuzzing campaign installations, e.g. oss-fuzz // fuzzing campaign installations, e.g. oss-fuzz
@ -117,9 +115,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
}; };
for (auto const &ignoreListFunc : ignoreList) { for (auto const &ignoreListFunc : ignoreList) {
if (F->getName().startswith(ignoreListFunc)) { return true; } if (F->getName().startswith(ignoreListFunc)) { return true; }
} }
static constexpr const char *ignoreSubstringList[] = { static constexpr const char *ignoreSubstringList[] = {
@ -131,67 +127,51 @@ bool isIgnoreFunction(const llvm::Function *F) {
}; };
for (auto const &ignoreListFunc : ignoreSubstringList) { for (auto const &ignoreListFunc : ignoreSubstringList) {
// hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0 // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; } if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
} }
return false; return false;
} }
class AutoTokensPass : public ModulePass { class AutoTokensPass : public ModulePass {
public: public:
static char ID; static char ID;
AutoTokensPass() : ModulePass(ID) { AutoTokensPass() : ModulePass(ID) {
} }
bool runOnModule(Module &M) override; bool runOnModule(Module &M) override;
protected: protected:
private:
private: std::vector<std::string> dictionary;
std::vector<std::string> dictionary;
}; };
} // namespace } // namespace
char AutoTokensPass::ID = 0; char AutoTokensPass::ID = 0;
void dict2file(int fd, uint8_t *mem, uint32_t len) { void dict2file(int fd, uint8_t *mem, uint32_t len) {
uint32_t i, j, binary = 0; uint32_t i, j, binary = 0;
char line[MAX_AUTO_EXTRA * 8], tmp[8]; char line[MAX_AUTO_EXTRA * 8], tmp[8];
strcpy(line, "\""); strcpy(line, "\"");
j = 1; j = 1;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') { if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') {
line[j++] = mem[i]; line[j++] = mem[i];
} else { } else {
if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) { if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) {
line[j] = 0; line[j] = 0;
sprintf(tmp, "\\x%02x", (uint8_t)mem[i]); sprintf(tmp, "\\x%02x", (uint8_t)mem[i]);
strcat(line, tmp); strcat(line, tmp);
j = strlen(line); j = strlen(line);
} }
binary = 1; binary = 1;
} }
} }
line[j] = 0; line[j] = 0;
@ -199,15 +179,13 @@ void dict2file(int fd, uint8_t *mem, uint32_t len) {
if (write(fd, line, strlen(line)) <= 0) if (write(fd, line, strlen(line)) <= 0)
FATAL("Could not write to dictionary file"); FATAL("Could not write to dictionary file");
fsync(fd); fsync(fd);
} }
bool AutoTokensPass::runOnModule(Module &M) { bool AutoTokensPass::runOnModule(Module &M) {
DenseMap<Value *, std::string *> valueMap; DenseMap<Value *, std::string *> valueMap;
char * ptr; char *ptr;
int fd, found = 0; int fd, found = 0;
bool use_file = true; bool use_file = true;
/* Show a banner */ /* Show a banner */
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
@ -215,22 +193,21 @@ bool AutoTokensPass::runOnModule(Module &M) {
ptr = getenv("AFL_LLVM_DICT2FILE"); ptr = getenv("AFL_LLVM_DICT2FILE");
if (!ptr || *ptr != '/') { if (!ptr || *ptr != '/') {
// fprintf(stderr, "AFL_LLVM_DICT2FILE is not set to an absolute path: %s\n", ptr); // fprintf(stderr, "AFL_LLVM_DICT2FILE is not set to an absolute path:
// fprintf(stderr, "Writing tokens into libafl_tokens section\n"); // %s\n", ptr); fprintf(stderr, "Writing tokens into libafl_tokens
// section\n");
use_file = false; use_file = false;
} }
if(use_file) { if (use_file) {
if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0) if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0)
FATAL("Could not open/create %s.", ptr); FATAL("Could not open/create %s.", ptr);
} }
/* Instrument all the things! */ /* Instrument all the things! */
for (auto &F : M) { for (auto &F : M) {
if (isIgnoreFunction(&F)) continue; if (isIgnoreFunction(&F)) continue;
/* Some implementation notes. /* Some implementation notes.
@ -262,15 +239,12 @@ bool AutoTokensPass::runOnModule(Module &M) {
*/ */
for (auto &BB : F) { for (auto &BB : F) {
for (auto &IN : BB) { for (auto &IN : BB) {
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
CmpInst * cmpInst = nullptr; CmpInst *cmpInst = nullptr;
if ((cmpInst = dyn_cast<CmpInst>(&IN))) { if ((cmpInst = dyn_cast<CmpInst>(&IN))) {
Value *op = cmpInst->getOperand(1);
Value * op = cmpInst->getOperand(1);
ConstantInt *ilen = dyn_cast<ConstantInt>(op); ConstantInt *ilen = dyn_cast<ConstantInt>(op);
/* We skip > 64 bit integers. why? first because their value is /* We skip > 64 bit integers. why? first because their value is
@ -278,18 +252,15 @@ bool AutoTokensPass::runOnModule(Module &M) {
literals > 64 bit (as of llvm 12) */ literals > 64 bit (as of llvm 12) */
if (ilen && ilen->uge(0xffffffffffffffff) == false) { if (ilen && ilen->uge(0xffffffffffffffff) == false) {
uint64_t val2 = 0, val = ilen->getZExtValue(); uint64_t val2 = 0, val = ilen->getZExtValue();
uint32_t len = 0; uint32_t len = 0;
if (val > 0x10000 && val < 0xffffffff) len = 4; if (val > 0x10000 && val < 0xffffffff) len = 4;
if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8; if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
if (len) { if (len) {
auto c = cmpInst->getPredicate(); auto c = cmpInst->getPredicate();
switch (c) { switch (c) {
case CmpInst::FCMP_OGT: // fall through case CmpInst::FCMP_OGT: // fall through
case CmpInst::FCMP_OLE: // fall through case CmpInst::FCMP_OLE: // fall through
case CmpInst::ICMP_SLE: // fall through case CmpInst::ICMP_SLE: // fall through
@ -298,10 +269,8 @@ bool AutoTokensPass::runOnModule(Module &M) {
// signed comparison and it is a negative constant // signed comparison and it is a negative constant
if ((len == 4 && (val & 80000000)) || if ((len == 4 && (val & 80000000)) ||
(len == 8 && (val & 8000000000000000))) { (len == 8 && (val & 8000000000000000))) {
if ((val & 0xffff) != 1) val2 = val - 1; if ((val & 0xffff) != 1) val2 = val - 1;
break; break;
} }
// fall through // fall through
@ -321,10 +290,8 @@ bool AutoTokensPass::runOnModule(Module &M) {
// signed comparison and it is a negative constant // signed comparison and it is a negative constant
if ((len == 4 && (val & 80000000)) || if ((len == 4 && (val & 80000000)) ||
(len == 8 && (val & 8000000000000000))) { (len == 8 && (val & 8000000000000000))) {
if ((val & 0xffff) != 1) val2 = val - 1; if ((val & 0xffff) != 1) val2 = val - 1;
break; break;
} }
// fall through // fall through
@ -338,37 +305,28 @@ bool AutoTokensPass::runOnModule(Module &M) {
default: default:
val2 = 0; val2 = 0;
} }
if(use_file) { if (use_file) {
dict2file(fd, (uint8_t *)&val, len); dict2file(fd, (uint8_t *)&val, len);
} } else {
else{
dictionary.push_back(std::string((char *)&val, len)); dictionary.push_back(std::string((char *)&val, len));
} }
found++; found++;
if (val2) { if (val2) {
if (use_file) {
if(use_file) {
dict2file(fd, (uint8_t *)&val2, len); dict2file(fd, (uint8_t *)&val2, len);
} } else {
else{
dictionary.push_back(std::string((char *)&val2, len)); dictionary.push_back(std::string((char *)&val2, len));
} }
found++; found++;
} }
} }
} }
} }
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
bool isStrcmp = true; bool isStrcmp = true;
bool isMemcmp = true; bool isMemcmp = true;
bool isStrncmp = true; bool isStrncmp = true;
@ -448,138 +406,96 @@ bool AutoTokensPass::runOnModule(Module &M) {
getConstantStringInfo(Str1P, TmpStr); getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) { if (TmpStr.empty()) {
HasStr1 = false; HasStr1 = false;
} else { } else {
HasStr1 = true; HasStr1 = true;
Str1 = TmpStr.str(); Str1 = TmpStr.str();
} }
bool HasStr2; bool HasStr2;
getConstantStringInfo(Str2P, TmpStr); getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) { if (TmpStr.empty()) {
HasStr2 = false; HasStr2 = false;
} else { } else {
HasStr2 = true; HasStr2 = true;
Str2 = TmpStr.str(); Str2 = TmpStr.str();
} }
// we handle the 2nd parameter first because of llvm memcpy // we handle the 2nd parameter first because of llvm memcpy
if (!HasStr2) { if (!HasStr2) {
auto *Ptr = dyn_cast<ConstantExpr>(Str2P); auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) { if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
if (Var->hasInitializer()) { if (Var->hasInitializer()) {
if (auto *Array = if (auto *Array =
dyn_cast<ConstantDataArray>(Var->getInitializer())) { dyn_cast<ConstantDataArray>(Var->getInitializer())) {
HasStr2 = true; HasStr2 = true;
Str2 = Array->getRawDataValues().str(); Str2 = Array->getRawDataValues().str();
} }
} }
} }
} }
} }
// for the internal memcpy routine we only care for the second // for the internal memcpy routine we only care for the second
// parameter and are not reporting anything. // parameter and are not reporting anything.
if (isIntMemcpy == true) { if (isIntMemcpy == true) {
if (HasStr2 == true) { if (HasStr2 == true) {
Value *op2 = callInst->getArgOperand(2);
Value * op2 = callInst->getArgOperand(2);
ConstantInt *ilen = dyn_cast<ConstantInt>(op2); ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
if (ilen) { if (ilen) {
uint64_t literalLength = Str2.length(); uint64_t literalLength = Str2.length();
uint64_t optLength = ilen->getZExtValue(); uint64_t optLength = ilen->getZExtValue();
if (literalLength + 1 == optLength) { if (literalLength + 1 == optLength) {
Str2.append("\0", 1); // add null byte Str2.append("\0", 1); // add null byte
} }
if (optLength > Str2.length()) { optLength = Str2.length(); } if (optLength > Str2.length()) { optLength = Str2.length(); }
} }
valueMap[Str1P] = new std::string(Str2); valueMap[Str1P] = new std::string(Str2);
continue; continue;
} }
continue; continue;
} }
// Neither a literal nor a global variable? // Neither a literal nor a global variable?
// maybe it is a local variable that we saved // maybe it is a local variable that we saved
if (!HasStr2) { if (!HasStr2) {
std::string *strng = valueMap[Str2P]; std::string *strng = valueMap[Str2P];
if (strng && !strng->empty()) { if (strng && !strng->empty()) {
Str2 = *strng; Str2 = *strng;
HasStr2 = true; HasStr2 = true;
} }
} }
if (!HasStr1) { if (!HasStr1) {
auto Ptr = dyn_cast<ConstantExpr>(Str1P); auto Ptr = dyn_cast<ConstantExpr>(Str1P);
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) { if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
if (Var->hasInitializer()) { if (Var->hasInitializer()) {
if (auto *Array = if (auto *Array =
dyn_cast<ConstantDataArray>(Var->getInitializer())) { dyn_cast<ConstantDataArray>(Var->getInitializer())) {
HasStr1 = true; HasStr1 = true;
Str1 = Array->getRawDataValues().str(); Str1 = Array->getRawDataValues().str();
} }
} }
} }
} }
} }
// Neither a literal nor a global variable? // Neither a literal nor a global variable?
// maybe it is a local variable that we saved // maybe it is a local variable that we saved
if (!HasStr1) { if (!HasStr1) {
std::string *strng = valueMap[Str1P]; std::string *strng = valueMap[Str1P];
if (strng && !strng->empty()) { if (strng && !strng->empty()) {
Str1 = *strng; Str1 = *strng;
HasStr1 = true; HasStr1 = true;
} }
} }
/* handle cases of one string is const, one string is variable */ /* handle cases of one string is const, one string is variable */
@ -597,12 +513,10 @@ bool AutoTokensPass::runOnModule(Module &M) {
if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; } if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; }
if (isMemcmp || isStrncmp || isStrncasecmp) { if (isMemcmp || isStrncmp || isStrncasecmp) {
Value *op2 = callInst->getArgOperand(2);
Value * op2 = callInst->getArgOperand(2);
ConstantInt *ilen = dyn_cast<ConstantInt>(op2); ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
if (ilen) { if (ilen) {
uint64_t literalLength = optLen; uint64_t literalLength = optLen;
optLen = ilen->getZExtValue(); optLen = ilen->getZExtValue();
if (optLen > thestring.length()) { optLen = thestring.length(); } if (optLen > thestring.length()) { optLen = thestring.length(); }
@ -610,33 +524,24 @@ bool AutoTokensPass::runOnModule(Module &M) {
if (literalLength + 1 == optLen) { // add null byte if (literalLength + 1 == optLen) { // add null byte
thestring.append("\0", 1); thestring.append("\0", 1);
addedNull = true; addedNull = true;
} }
} }
} }
// add null byte if this is a string compare function and a null // add null byte if this is a string compare function and a null
// was not already added // was not already added
if (!isMemcmp) { if (!isMemcmp) {
if (addedNull == false && thestring[optLen - 1] != '\0') { if (addedNull == false && thestring[optLen - 1] != '\0') {
thestring.append("\0", 1); // add null byte thestring.append("\0", 1); // add null byte
optLen++; optLen++;
} }
if (!isStdString) { if (!isStdString) {
// ensure we do not have garbage // ensure we do not have garbage
size_t offset = thestring.find('\0', 0); size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1; if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen); thestring = thestring.substr(0, optLen);
} }
} }
// we take the longer string, even if the compare was to a // we take the longer string, even if the compare was to a
@ -650,85 +555,70 @@ bool AutoTokensPass::runOnModule(Module &M) {
ptr = (char *)thestring.c_str(); ptr = (char *)thestring.c_str();
if(use_file){ if (use_file) {
dict2file(fd, (uint8_t *)ptr, optLen); dict2file(fd, (uint8_t *)ptr, optLen);
} } else {
else{
dictionary.push_back(thestring.substr(0, optLen)); dictionary.push_back(thestring.substr(0, optLen));
} }
found++; found++;
} }
} }
} }
} }
if(use_file){ if (use_file) {
close(fd); close(fd);
return true; return true;
} }
LLVMContext &Ctx = M.getContext(); LLVMContext &Ctx = M.getContext();
if (dictionary.size()) { size_t memlen = 0, count = 0, offset = 0;
size_t memlen = 0, count = 0, offset = 0; // sort and unique the dictionary
std::sort(dictionary.begin(), dictionary.end());
auto last = std::unique(dictionary.begin(), dictionary.end());
dictionary.erase(last, dictionary.end());
// sort and unique the dictionary for (auto token : dictionary) {
std::sort(dictionary.begin(), dictionary.end()); memlen += token.length();
auto last = std::unique(dictionary.begin(), dictionary.end()); count++;
dictionary.erase(last, dictionary.end()); }
for (auto token : dictionary) { auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
memlen += token.length(); count = 0;
for (auto token : dictionary) {
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
// This lenght is guranteed to be < MAX_AUTO_EXTRA
ptrhld.get()[offset++] = (uint8_t)token.length();
memcpy(ptrhld.get() + offset, token.c_str(), token.length());
offset += token.length();
count++; count++;
}
if (count) {
auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
count = 0;
for (auto token : dictionary) {
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
// This lenght is guranteed to be < MAX_AUTO_EXTRA
ptrhld.get()[offset++] = (uint8_t)token.length();
memcpy(ptrhld.get() + offset, token.c_str(), token.length());
offset += token.length();
count++;
}
}
// Type
ArrayType* arrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
// The actual dict
GlobalVariable *dict = new GlobalVariable(M, arrayTy, true, GlobalVariable::ExternalLinkage, ConstantDataArray::get(Ctx, *(new ArrayRef<char>(ptrhld.get(), offset))), "libafl_dictionary_" + M.getName());
dict->setSection("libafl_token");
} }
} }
// Type
ArrayType *arrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
// The actual dict
GlobalVariable *dict = new GlobalVariable(
M, arrayTy, true, GlobalVariable::ExternalLinkage,
ConstantDataArray::get(Ctx, *(new ArrayRef<char>(ptrhld.get(), offset))),
"libafl_dictionary_" + M.getName());
dict->setSection("libafl_token");
return true; return true;
} }
static void registerAutoTokensPass(const PassManagerBuilder &, static void registerAutoTokensPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
PM.add(new AutoTokensPass()); PM.add(new AutoTokensPass());
} }
static RegisterPass<AutoTokensPass> X("autotokens", static RegisterPass<AutoTokensPass> X("autotokens",
"autotokens instrumentation pass", "autotokens instrumentation pass", false,
false, false); false);
static RegisterStandardPasses RegisterAutoTokensPass( static RegisterStandardPasses RegisterAutoTokensPass(
PassManagerBuilder::EP_OptimizerLast, registerAutoTokensPass); PassManagerBuilder::EP_OptimizerLast, registerAutoTokensPass);

View File

@ -55,7 +55,6 @@ namespace {
/* Function that we never instrument or analyze */ /* Function that we never instrument or analyze */
/* Note: this ignore check is also called in isInInstrumentList() */ /* Note: this ignore check is also called in isInInstrumentList() */
bool isIgnoreFunction(const llvm::Function *F) { bool isIgnoreFunction(const llvm::Function *F) {
// Starting from "LLVMFuzzer" these are functions used in libfuzzer based // Starting from "LLVMFuzzer" these are functions used in libfuzzer based
// fuzzing campaign installations, e.g. oss-fuzz // fuzzing campaign installations, e.g. oss-fuzz
@ -93,9 +92,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
}; };
for (auto const &ignoreListFunc : ignoreList) { for (auto const &ignoreListFunc : ignoreList) {
if (F->getName().startswith(ignoreListFunc)) { return true; } if (F->getName().startswith(ignoreListFunc)) { return true; }
} }
static constexpr const char *ignoreSubstringList[] = { static constexpr const char *ignoreSubstringList[] = {
@ -107,38 +104,32 @@ bool isIgnoreFunction(const llvm::Function *F) {
}; };
for (auto const &ignoreListFunc : ignoreSubstringList) { for (auto const &ignoreListFunc : ignoreSubstringList) {
// hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0 // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; } if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
} }
return false; return false;
} }
class CmpLogRoutines : public ModulePass { class CmpLogRoutines : public ModulePass {
public: public:
static char ID; static char ID;
CmpLogRoutines() : ModulePass(ID) {} CmpLogRoutines() : ModulePass(ID) {
}
bool runOnModule(Module &M) override; bool runOnModule(Module &M) override;
#if LLVM_VERSION_MAJOR < 4 #if LLVM_VERSION_MAJOR < 4
const char *getPassName() const override { const char *getPassName() const override {
#else #else
StringRef getPassName() const override { StringRef getPassName() const override {
#endif #endif
return "cmplog routines"; return "cmplog routines";
} }
private: private:
bool hookRtns(Module &M); bool hookRtns(Module &M);
}; };
} // namespace } // namespace
@ -146,9 +137,8 @@ class CmpLogRoutines : public ModulePass {
char CmpLogRoutines::ID = 0; char CmpLogRoutines::ID = 0;
bool CmpLogRoutines::hookRtns(Module &M) { bool CmpLogRoutines::hookRtns(Module &M) {
std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC; std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC;
LLVMContext & C = M.getContext(); LLVMContext &C = M.getContext();
Type *VoidTy = Type::getVoidTy(C); Type *VoidTy = Type::getVoidTy(C);
// PointerType *VoidPtrTy = PointerType::get(VoidTy, 0); // PointerType *VoidPtrTy = PointerType::get(VoidTy, 0);
@ -246,17 +236,13 @@ bool CmpLogRoutines::hookRtns(Module &M) {
/* iterate over all functions, bbs and instruction and add suitable calls */ /* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) { for (auto &F : M) {
if (isIgnoreFunction(&F)) continue; if (isIgnoreFunction(&F)) continue;
for (auto &BB : F) { for (auto &BB : F) {
for (auto &IN : BB) { for (auto &IN : BB) {
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction(); Function *Callee = callInst->getCalledFunction();
if (!Callee) continue; if (!Callee) continue;
if (callInst->getCallingConv() != llvm::CallingConv::C) continue; if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
@ -316,9 +302,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
if (isGccStdStringCString || isGccStdStringStdString || if (isGccStdStringCString || isGccStdStringStdString ||
isLlvmStdStringStdString || isLlvmStdStringCString) { isLlvmStdStringStdString || isLlvmStdStringCString) {
isPtrRtn = false; isPtrRtn = false;
} }
if (isPtrRtn) { calls.push_back(callInst); } if (isPtrRtn) { calls.push_back(callInst); }
@ -326,13 +310,9 @@ bool CmpLogRoutines::hookRtns(Module &M) {
if (isGccStdStringCString) { gccStdC.push_back(callInst); } if (isGccStdStringCString) { gccStdC.push_back(callInst); }
if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); } if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); }
if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); } if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); }
} }
} }
} }
} }
if (!calls.size() && !gccStdStd.size() && !gccStdC.size() && if (!calls.size() && !gccStdStd.size() && !gccStdC.size() &&
@ -340,119 +320,104 @@ bool CmpLogRoutines::hookRtns(Module &M) {
return false; return false;
for (auto &callInst : calls) { for (auto &callInst : calls) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent()); IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst); IRB.SetInsertPoint(callInst);
std::vector<Value *> args; std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted); args.push_back(v1Pcasted);
args.push_back(v2Pcasted); args.push_back(v2Pcasted);
IRB.CreateCall(cmplogHookFn, args); IRB.CreateCall(cmplogHookFn, args);
// errs() << callInst->getCalledFunction()->getName() << "\n"; // errs() << callInst->getCalledFunction()->getName() << "\n";
} }
for (auto &callInst : gccStdStd) { for (auto &callInst : gccStdStd) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent()); IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst); IRB.SetInsertPoint(callInst);
std::vector<Value *> args; std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted); args.push_back(v1Pcasted);
args.push_back(v2Pcasted); args.push_back(v2Pcasted);
IRB.CreateCall(cmplogGccStdStd, args); IRB.CreateCall(cmplogGccStdStd, args);
// errs() << callInst->getCalledFunction()->getName() << "\n"; // errs() << callInst->getCalledFunction()->getName() << "\n";
} }
for (auto &callInst : gccStdC) { for (auto &callInst : gccStdC) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent()); IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst); IRB.SetInsertPoint(callInst);
std::vector<Value *> args; std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted); args.push_back(v1Pcasted);
args.push_back(v2Pcasted); args.push_back(v2Pcasted);
IRB.CreateCall(cmplogGccStdC, args); IRB.CreateCall(cmplogGccStdC, args);
// errs() << callInst->getCalledFunction()->getName() << "\n"; // errs() << callInst->getCalledFunction()->getName() << "\n";
} }
for (auto &callInst : llvmStdStd) { for (auto &callInst : llvmStdStd) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent()); IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst); IRB.SetInsertPoint(callInst);
std::vector<Value *> args; std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted); args.push_back(v1Pcasted);
args.push_back(v2Pcasted); args.push_back(v2Pcasted);
IRB.CreateCall(cmplogLlvmStdStd, args); IRB.CreateCall(cmplogLlvmStdStd, args);
// errs() << callInst->getCalledFunction()->getName() << "\n"; // errs() << callInst->getCalledFunction()->getName() << "\n";
} }
for (auto &callInst : llvmStdC) { for (auto &callInst : llvmStdC) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent()); IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst); IRB.SetInsertPoint(callInst);
std::vector<Value *> args; std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted); args.push_back(v1Pcasted);
args.push_back(v2Pcasted); args.push_back(v2Pcasted);
IRB.CreateCall(cmplogLlvmStdC, args); IRB.CreateCall(cmplogLlvmStdC, args);
// errs() << callInst->getCalledFunction()->getName() << "\n"; // errs() << callInst->getCalledFunction()->getName() << "\n";
} }
return true; return true;
} }
bool CmpLogRoutines::runOnModule(Module &M) { bool CmpLogRoutines::runOnModule(Module &M) {
hookRtns(M); hookRtns(M);
verifyModule(M); verifyModule(M);
return true; return true;
} }
static void registerCmpLogRoutinesPass(const PassManagerBuilder &, static void registerCmpLogRoutinesPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
auto p = new CmpLogRoutines(); auto p = new CmpLogRoutines();
PM.add(p); PM.add(p);
} }
static RegisterStandardPasses RegisterCmpLogRoutinesPass( static RegisterStandardPasses RegisterCmpLogRoutinesPass(
@ -466,4 +431,3 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO(
PassManagerBuilder::EP_FullLinkTimeOptimizationLast, PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
registerCmpLogRoutinesPass); registerCmpLogRoutinesPass);
#endif #endif

View File

@ -54,59 +54,52 @@ typedef uint32_t prev_loc_t;
#define MAP_SIZE LIBAFL_ACCOUNTING_MAP_SIZE #define MAP_SIZE LIBAFL_ACCOUNTING_MAP_SIZE
#define SECURITY_SENSITIVE_FUNCS(CF) \
#define SECURITY_SENSITIVE_FUNCS(CF) static CF securitySensitiveFunctions[] = {\ static CF securitySensitiveFunctions[] = { \
CF("memcpy"), \ CF("memcpy"), CF("strlen"), CF("ReadImage"), CF("memmove"), \
CF("strlen"), \ CF("free"), CF("memset"), CF("delete"), CF("memcmp"), \
CF("ReadImage"), \ CF("getString"), CF("vsprintf"), CF("GET_COLOR"), CF("read"), \
CF("memmove"), \ CF("load_bmp"), CF("huffcode"), CF("strcmp"), CF("new"), \
CF("free"), \ CF("getName"), CF("strncat"), CF("png_load"), \
CF("memset"), \ };
CF("delete"), \
CF("memcmp"), \
CF("getString"), \
CF("vsprintf"), \
CF("GET_COLOR"), \
CF("read"), \
CF("load_bmp"), \
CF("huffcode"), \
CF("strcmp"), \
CF("new"), \
CF("getName"), \
CF("strncat"), \
CF("png_load"), \
};
using namespace llvm; using namespace llvm;
enum AccountingGranularity { enum AccountingGranularity {
BB_GRAN, BB_GRAN,
FUNC_GRAN, FUNC_GRAN,
// LOOP, // LOOP,
UKNOWN_GRAN UKNOWN_GRAN
}; };
static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false), cl::NotHidden); static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false),
static cl::opt<std::string> GranularityStr("granularity", cl::desc("Granularity of accounting (BB, FUNC)"), cl::init(std::string("BB")), cl::NotHidden); cl::NotHidden);
static cl::opt<uint32_t> InstRatio("inst_ratio", cl::desc("Instrumentation ratio in percentage"), cl::init(100), cl::NotHidden); static cl::opt<std::string> GranularityStr(
static cl::opt<bool> ThreadSafe("thread_safe", cl::desc("Use the thread safe instrumentation"), cl::init(false), cl::NotHidden); "granularity", cl::desc("Granularity of accounting (BB, FUNC)"),
cl::init(std::string("BB")), cl::NotHidden);
static cl::opt<uint32_t> InstRatio(
"inst_ratio", cl::desc("Instrumentation ratio in percentage"),
cl::init(100), cl::NotHidden);
static cl::opt<bool> ThreadSafe("thread_safe",
cl::desc("Use the thread safe instrumentation"),
cl::init(false), cl::NotHidden);
namespace { namespace {
SECURITY_SENSITIVE_FUNCS(StringRef) SECURITY_SENSITIVE_FUNCS(StringRef)
bool isSecuritySensitiveFunction(Function* F) { bool isSecuritySensitiveFunction(Function *F) {
if (!F) return 0; if (!F) return 0;
auto func_name = F->getName(); auto func_name = F->getName();
for (auto name : securitySensitiveFunctions) { for (auto name : securitySensitiveFunctions) {
if (func_name.contains(name)) { if (func_name.contains(name)) {
if (Debug) if (Debug)
fprintf(stderr, "Counted %s as security sensitive", func_name.str().c_str()); fprintf(stderr, "Counted %s as security sensitive",
return 1; func_name.str().c_str());
} return 1;
} }
return 0; }
return 0;
} }
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -120,11 +113,10 @@ class AFLCoverage : public ModulePass {
AFLCoverage() : ModulePass(ID) { AFLCoverage() : ModulePass(ID) {
#endif #endif
granularity = StringSwitch<AccountingGranularity>(GranularityStr) granularity = StringSwitch<AccountingGranularity>(GranularityStr)
.Case("BB", BB_GRAN) .Case("BB", BB_GRAN)
.Case("FUNC", FUNC_GRAN) .Case("FUNC", FUNC_GRAN)
.Default(UKNOWN_GRAN); .Default(UKNOWN_GRAN);
// initInstrumentList(); // initInstrumentList();
} }
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -134,10 +126,9 @@ class AFLCoverage : public ModulePass {
#endif #endif
protected: protected:
uint32_t map_size = MAP_SIZE; uint32_t map_size = MAP_SIZE;
uint32_t function_minimum_size = 1; uint32_t function_minimum_size = 1;
AccountingGranularity granularity; AccountingGranularity granularity;
}; };
} // namespace } // namespace
@ -145,33 +136,30 @@ class AFLCoverage : public ModulePass {
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() { llvmGetPassPluginInfo() {
return { return {LLVM_PLUGIN_API_VERSION, "AFLCoverageAccounting", "v0.1",
LLVM_PLUGIN_API_VERSION, "AFLCoverageAccounting", "v0.1", /* lambda to insert our pass into the pass pipeline. */
/* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) {
[](PassBuilder &PB) { #if 1
#if 1 using OptimizationLevel = typename PassBuilder::OptimizationLevel;
using OptimizationLevel = typename PassBuilder::OptimizationLevel; PB.registerOptimizerLastEPCallback(
PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(AFLCoverage());
MPM.addPass(AFLCoverage()); });
} /* TODO LTO registration */
); #else
/* TODO LTO registration */ using PipelineElement = typename PassBuilder::PipelineElement;
#else PB.registerPipelineParsingCallback([](StringRef Name,
using PipelineElement = typename PassBuilder::PipelineElement; ModulePassManager &MPM,
PB.registerPipelineParsingCallback( ArrayRef<PipelineElement>) {
[](StringRef Name, ModulePassManager &MPM, ArrayRef<PipelineElement>) { if (Name == "AFLCoverageAccounting") {
if ( Name == "AFLCoverageAccounting" ) { MPM.addPass(AFLCoverage());
MPM.addPass(AFLCoverage()); return true;
return true; } else {
} else { return false;
return false; }
} });
} #endif
); }};
#endif
}
};
} }
#else #else
@ -187,7 +175,7 @@ bool AFLCoverage::runOnModule(Module &M) {
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
IntegerType *Int32Ty = IntegerType::getInt32Ty(C); IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
uint32_t rand_seed; uint32_t rand_seed;
unsigned int cur_loc = 0; unsigned int cur_loc = 0;
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -206,19 +194,19 @@ bool AFLCoverage::runOnModule(Module &M) {
/* Get globals for the SHM region and the previous location. Note that /* Get globals for the SHM region and the previous location. Note that
__afl_acc_prev_loc is thread-local. */ __afl_acc_prev_loc is thread-local. */
GlobalVariable *AFLMemOpPtr = GlobalVariable *AFLMemOpPtr = new GlobalVariable(
new GlobalVariable(M, PointerType::get(Int32Ty, 0), false, M, PointerType::get(Int32Ty, 0), false, GlobalValue::ExternalLinkage, 0,
GlobalValue::ExternalLinkage, 0, "__afl_acc_memop_ptr"); "__afl_acc_memop_ptr");
GlobalVariable *AFLPrevLoc; GlobalVariable *AFLPrevLoc;
#if defined(__ANDROID__) || defined(__HAIKU__) #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable( AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc"); M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc");
#else #else
AFLPrevLoc = new GlobalVariable( AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc", 0, M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc",
GlobalVariable::GeneralDynamicTLSModel, 0, false); 0, GlobalVariable::GeneralDynamicTLSModel, 0, false);
#endif #endif
/* Instrument all the things! */ /* Instrument all the things! */
@ -227,7 +215,6 @@ bool AFLCoverage::runOnModule(Module &M) {
// scanForDangerousFunctions(&M); // scanForDangerousFunctions(&M);
for (auto &F : M) { for (auto &F : M) {
int has_calls = 0; int has_calls = 0;
if (Debug) if (Debug)
fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(), fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(),
@ -239,7 +226,6 @@ bool AFLCoverage::runOnModule(Module &M) {
std::list<Value *> todo; std::list<Value *> todo;
for (auto &BB : F) { for (auto &BB : F) {
BasicBlock::iterator IP = BB.getFirstInsertionPt(); BasicBlock::iterator IP = BB.getFirstInsertionPt();
IRBuilder<> IRB(&(*IP)); IRBuilder<> IRB(&(*IP));
@ -250,8 +236,7 @@ bool AFLCoverage::runOnModule(Module &M) {
for (auto &I : BB) { for (auto &I : BB) {
switch (granularity) { switch (granularity) {
case BB_GRAN: case BB_GRAN:
if (I.mayReadFromMemory() || I.mayWriteToMemory()) if (I.mayReadFromMemory() || I.mayWriteToMemory()) ++MemCnt;
++MemCnt;
break; break;
case FUNC_GRAN: case FUNC_GRAN:
if (auto *C = dyn_cast<CallInst>(&I)) { if (auto *C = dyn_cast<CallInst>(&I)) {
@ -275,36 +260,37 @@ bool AFLCoverage::runOnModule(Module &M) {
/* Load SHM pointer */ /* Load SHM pointer */
LoadInst *MemReadPtr = IRB.CreateLoad(AFLMemOpPtr); LoadInst *MemReadPtr = IRB.CreateLoad(AFLMemOpPtr);
MemReadPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); MemReadPtr->setMetadata(M.getMDKindID("nosanitize"),
Value *MemReadPtrIdx = IRB.CreateGEP(MemReadPtr, IRB.CreateXor(PrevLoc, CurLoc)); MDNode::get(C, None));
Value *MemReadPtrIdx =
IRB.CreateGEP(MemReadPtr, IRB.CreateXor(PrevLoc, CurLoc));
/* Update bitmap */ /* Update bitmap */
LoadInst *MemReadCount = IRB.CreateLoad(MemReadPtrIdx); LoadInst *MemReadCount = IRB.CreateLoad(MemReadPtrIdx);
MemReadCount->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); MemReadCount->setMetadata(M.getMDKindID("nosanitize"),
Value *MemReadIncr = IRB.CreateAdd(MemReadCount, ConstantInt::get(Int32Ty, MemCnt)); MDNode::get(C, None));
Value *MemReadIncr =
IRB.CreateAdd(MemReadCount, ConstantInt::get(Int32Ty, MemCnt));
IRB.CreateStore(MemReadIncr, MemReadPtrIdx) IRB.CreateStore(MemReadIncr, MemReadPtrIdx)
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
/* Update prev_loc */ /* Update prev_loc */
StoreInst * Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), StoreInst *Store =
AFLPrevLoc); IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc);
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
inst_blocks++; inst_blocks++;
} }
} }
if (Debug) {
if (Debug) {
if (!inst_blocks) if (!inst_blocks)
fprintf(stderr, "No instrumentation targets found.\n"); fprintf(stderr, "No instrumentation targets found.\n");
else else
fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks, (unsigned)InstRatio); fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks,
(unsigned)InstRatio);
} }
#ifdef USE_NEW_PM #ifdef USE_NEW_PM
@ -312,15 +298,12 @@ bool AFLCoverage::runOnModule(Module &M) {
#else #else
return true; return true;
#endif #endif
} }
#ifndef USE_NEW_PM #ifndef USE_NEW_PM
static void registerAFLPass(const PassManagerBuilder &, static void registerAFLPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
PM.add(new AFLCoverage()); PM.add(new AFLCoverage());
} }
static RegisterStandardPasses RegisterAFLPass( static RegisterStandardPasses RegisterAFLPass(