C(pp) formatting & autotokens fix (#614)
* fix * a * format * .clang-format
This commit is contained in:
parent
b0dd25ee95
commit
6b76e53bfa
148
.clang-format
Normal file
148
.clang-format
Normal 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
|
||||
...
|
||||
|
@ -2,8 +2,6 @@
|
||||
//! They may be inserted as part of mutations during fuzzing.
|
||||
#[cfg(feature = "std")]
|
||||
use crate::mutators::str_decode;
|
||||
#[cfg(target_os = "linux")]
|
||||
use alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
#[cfg(target_os = "linux")]
|
||||
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> {
|
||||
let mut ret = Self::default();
|
||||
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!(
|
||||
"Tried to create tokens from illegal section: stop < start ({:?} < {:?})",
|
||||
token_stop, token_start
|
||||
|
@ -72,15 +72,35 @@ typedef uint32_t prev_loc_t;
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false), 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> NotZero("not_zero", cl::desc("Never hit 0 again in the hitcount"), cl::init(true), 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);
|
||||
static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false),
|
||||
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> NotZero("not_zero",
|
||||
cl::desc("Never hit 0 again in the hitcount"),
|
||||
cl::init(true), 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 {
|
||||
|
||||
@ -96,7 +116,6 @@ class AFLCoverage : public ModulePass {
|
||||
#endif
|
||||
|
||||
// initInstrumentList();
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_NEW_PM
|
||||
@ -106,11 +125,10 @@ class AFLCoverage : public ModulePass {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
uint32_t function_minimum_size = 1;
|
||||
DenseMap<BasicBlock *, int32_t> bb_to_cur_loc;
|
||||
DenseMap<StringRef, BasicBlock *> entry_bb;
|
||||
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
uint32_t function_minimum_size = 1;
|
||||
DenseMap<BasicBlock *, int32_t> bb_to_cur_loc;
|
||||
DenseMap<StringRef, BasicBlock *> entry_bb;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -118,33 +136,30 @@ class AFLCoverage : public ModulePass {
|
||||
#ifdef USE_NEW_PM
|
||||
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
|
||||
llvmGetPassPluginInfo() {
|
||||
return {
|
||||
LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1",
|
||||
/* lambda to insert our pass into the pass pipeline. */
|
||||
[](PassBuilder &PB) {
|
||||
#if 1
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
MPM.addPass(AFLCoverage());
|
||||
}
|
||||
);
|
||||
/* TODO LTO registration */
|
||||
#else
|
||||
using PipelineElement = typename PassBuilder::PipelineElement;
|
||||
PB.registerPipelineParsingCallback(
|
||||
[](StringRef Name, ModulePassManager &MPM, ArrayRef<PipelineElement>) {
|
||||
if ( Name == "AFLCoverage" ) {
|
||||
MPM.addPass(AFLCoverage());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1",
|
||||
/* lambda to insert our pass into the pass pipeline. */
|
||||
[](PassBuilder &PB) {
|
||||
#if 1
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
MPM.addPass(AFLCoverage());
|
||||
});
|
||||
/* TODO LTO registration */
|
||||
#else
|
||||
using PipelineElement = typename PassBuilder::PipelineElement;
|
||||
PB.registerPipelineParsingCallback([](StringRef Name,
|
||||
ModulePassManager &MPM,
|
||||
ArrayRef<PipelineElement>) {
|
||||
if (Name == "AFLCoverage") {
|
||||
MPM.addPass(AFLCoverage());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}};
|
||||
}
|
||||
#else
|
||||
|
||||
@ -156,7 +171,10 @@ PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) {
|
||||
#else
|
||||
bool AFLCoverage::runOnModule(Module &M) {
|
||||
#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();
|
||||
|
||||
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
|
||||
@ -165,7 +183,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
IntegerType *IntLocTy =
|
||||
IntegerType::getIntNTy(C, sizeof(prev_loc_t) * CHAR_BIT);
|
||||
#endif
|
||||
uint32_t rand_seed;
|
||||
uint32_t rand_seed;
|
||||
unsigned int cur_loc = 0;
|
||||
|
||||
#ifdef USE_NEW_PM
|
||||
@ -205,10 +223,10 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
VectorType *PrevLocTy = NULL;
|
||||
|
||||
if (Ngram && (Ngram < 2 || Ngram > NGRAM_SIZE_MAX))
|
||||
FATAL(
|
||||
"Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX "
|
||||
"(%u))",
|
||||
NGRAM_SIZE_MAX);
|
||||
FATAL(
|
||||
"Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX "
|
||||
"(%u))",
|
||||
NGRAM_SIZE_MAX);
|
||||
|
||||
if (Ngram)
|
||||
PrevLocSize = Ngram - 1;
|
||||
@ -219,22 +237,20 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
VectorType *PrevCallerTy = NULL;
|
||||
|
||||
if (CtxK > CTX_MAX_K)
|
||||
FATAL("Bad value of K for K-context sensitivity (must be between 1 and CTX_MAX_K (%u))",
|
||||
CTX_MAX_K);
|
||||
FATAL(
|
||||
"Bad value of K for K-context sensitivity (must be between 1 and "
|
||||
"CTX_MAX_K (%u))",
|
||||
CTX_MAX_K);
|
||||
|
||||
if (CtxK == 1) {
|
||||
|
||||
CtxK = 0;
|
||||
instrument_ctx = true;
|
||||
instrument_caller = true; // Enable CALLER instead
|
||||
|
||||
}
|
||||
|
||||
if (CtxK) {
|
||||
|
||||
PrevCallerSize = CtxK;
|
||||
instrument_ctx = true;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
@ -371,11 +387,10 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
|
||||
|
||||
Constant * PrevCallerShuffleMask = NULL;
|
||||
Constant *PrevCallerShuffleMask = NULL;
|
||||
SmallVector<Constant *, 32> PrevCallerShuffle = {UndefValue::get(Int32Ty)};
|
||||
|
||||
if (CtxK) {
|
||||
|
||||
for (unsigned I = 0; I < PrevCallerSize - 1; ++I)
|
||||
PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, I));
|
||||
|
||||
@ -383,7 +398,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, PrevCallerSize));
|
||||
|
||||
PrevCallerShuffleMask = ConstantVector::get(PrevCallerShuffle);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -391,7 +405,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// other constants we need
|
||||
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
|
||||
|
||||
Value * PrevCtx = NULL; // CTX sensitive coverage
|
||||
Value *PrevCtx = NULL; // CTX sensitive coverage
|
||||
LoadInst *PrevCaller = NULL; // K-CTX coverage
|
||||
|
||||
/* Instrument all the things! */
|
||||
@ -400,7 +414,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// scanForDangerousFunctions(&M);
|
||||
|
||||
for (auto &F : M) {
|
||||
|
||||
int has_calls = 0;
|
||||
if (Debug)
|
||||
fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(),
|
||||
@ -413,16 +426,13 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
std::list<Value *> todo;
|
||||
for (auto &BB : F) {
|
||||
|
||||
BasicBlock::iterator IP = BB.getFirstInsertionPt();
|
||||
IRBuilder<> IRB(&(*IP));
|
||||
|
||||
// Context sensitive coverage
|
||||
if (instrument_ctx && &BB == &F.getEntryBlock()) {
|
||||
|
||||
#ifdef HAVE_VECTOR_INTRINSICS
|
||||
if (CtxK) {
|
||||
|
||||
PrevCaller = IRB.CreateLoad(AFLPrevCaller);
|
||||
PrevCaller->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
@ -430,7 +440,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
IRB.CreateZExt(IRB.CreateXorReduce(PrevCaller), IRB.getInt32Ty());
|
||||
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
|
||||
@ -440,42 +449,31 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
PrevCtxLoad->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
PrevCtx = PrevCtxLoad;
|
||||
|
||||
}
|
||||
|
||||
// does the function have calls? and is any of the calls larger than one
|
||||
// basic block?
|
||||
for (auto &BB_2 : F) {
|
||||
|
||||
if (has_calls) break;
|
||||
for (auto &IN : BB_2) {
|
||||
|
||||
CallInst *callInst = nullptr;
|
||||
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||
|
||||
Function *Callee = callInst->getCalledFunction();
|
||||
if (!Callee || Callee->size() < function_minimum_size)
|
||||
continue;
|
||||
else {
|
||||
|
||||
has_calls = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if yes we store a context ID for this function in the global var
|
||||
if (has_calls) {
|
||||
|
||||
Value *NewCtx = ConstantInt::get(Int32Ty, RandBelow(map_size));
|
||||
#ifdef HAVE_VECTOR_INTRINSICS
|
||||
if (CtxK) {
|
||||
|
||||
Value *ShuffledPrevCaller = IRB.CreateShuffleVector(
|
||||
PrevCaller, UndefValue::get(PrevCallerTy),
|
||||
PrevCallerShuffleMask);
|
||||
@ -488,7 +486,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
MDNode::get(C, None));
|
||||
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
|
||||
@ -496,11 +493,8 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
StoreInst *StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
|
||||
StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (RandBelow(100) >= InstRatio) continue;
|
||||
@ -523,7 +517,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// fprintf(stderr, "BB %u: ", cur_loc);
|
||||
for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); PI != E;
|
||||
++PI) {
|
||||
|
||||
BasicBlock *Pred = *PI;
|
||||
|
||||
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;
|
||||
++SI) {
|
||||
|
||||
BasicBlock *Succ = *SI;
|
||||
|
||||
// if (count > 0)
|
||||
// fprintf(stderr, "|");
|
||||
if (Succ != NULL) count++;
|
||||
// fprintf(stderr, "%p", Succ);
|
||||
|
||||
}
|
||||
|
||||
if (count > 1) more_than_one = 1;
|
||||
|
||||
}
|
||||
|
||||
// fprintf(stderr, " == %d\n", more_than_one);
|
||||
if (F.size() > 1 && more_than_one != 1) {
|
||||
|
||||
// in CTX mode we have to restore the original context for the caller -
|
||||
// she might be calling other functions which need the correct CTX
|
||||
if (instrument_ctx && has_calls) {
|
||||
|
||||
Instruction *Inst = BB.getTerminator();
|
||||
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
|
||||
|
||||
IRBuilder<> Post_IRB(Inst);
|
||||
|
||||
StoreInst *RestoreCtx;
|
||||
@ -567,13 +554,10 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext);
|
||||
RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -630,23 +614,23 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
/* Update bitmap */
|
||||
|
||||
if (ThreadSafe) { /* Atomic */
|
||||
/*
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
if (neverZero_counters_str !=
|
||||
NULL) { // with llvm 9 we make this the default as the bug
|
||||
in llvm
|
||||
// is then fixed
|
||||
#else
|
||||
if (NotZero) {
|
||||
|
||||
#endif
|
||||
// register MapPtrIdx in a todo list
|
||||
todo.push_back(MapPtrIdx);
|
||||
|
||||
} else {
|
||||
|
||||
*/
|
||||
if (ThreadSafe) { /* Atomic */
|
||||
/*
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
if (neverZero_counters_str !=
|
||||
NULL) { // with llvm 9 we make this the default as the bug
|
||||
in llvm
|
||||
// is then fixed
|
||||
#else
|
||||
if (NotZero) {
|
||||
|
||||
#endif
|
||||
// register MapPtrIdx in a todo list
|
||||
todo.push_back(MapPtrIdx);
|
||||
|
||||
} else {
|
||||
|
||||
*/
|
||||
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
|
||||
#if LLVM_VERSION_MAJOR >= 13
|
||||
llvm::MaybeAlign(1),
|
||||
@ -659,7 +643,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
*/
|
||||
|
||||
} else {
|
||||
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
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 carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
|
||||
}
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx)
|
||||
->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
|
||||
vector and shuffle the other elements back by one) */
|
||||
@ -703,7 +685,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
#ifdef HAVE_VECTOR_INTRINSICS
|
||||
if (Ngram) {
|
||||
|
||||
Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
|
||||
PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask);
|
||||
Value *UpdatedPrevLoc = IRB.CreateInsertElement(
|
||||
@ -713,24 +694,20 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
|
||||
Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1),
|
||||
AFLPrevLoc);
|
||||
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
}
|
||||
|
||||
// in CTX mode we have to restore the original context for the caller -
|
||||
// she might be calling other functions which need the correct CTX.
|
||||
// Currently this is only needed for the Ubuntu clang-6.0 bug
|
||||
if (instrument_ctx && has_calls) {
|
||||
|
||||
Instruction *Inst = BB.getTerminator();
|
||||
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
|
||||
|
||||
IRBuilder<> Post_IRB(Inst);
|
||||
|
||||
StoreInst *RestoreCtx;
|
||||
@ -742,39 +719,37 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext);
|
||||
RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inst_blocks++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (DumpCFG) {
|
||||
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.");
|
||||
std::string cfg = "";
|
||||
for (auto record = entry_bb.begin(); record != entry_bb.end(); record++) {
|
||||
// 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
|
||||
auto current_bb = record->getFirst();
|
||||
Function* calling_func = current_bb->getParent();
|
||||
auto current_bb = record->getFirst();
|
||||
Function *calling_func = current_bb->getParent();
|
||||
if (calling_func) {
|
||||
auto function_name = calling_func->getName().str();
|
||||
cfg += formatv("%%{0}", function_name);
|
||||
}
|
||||
else
|
||||
} else
|
||||
cfg += "%%__";
|
||||
auto current_cur_loc = record->getSecond();
|
||||
cfg += formatv("+{0}\n", current_cur_loc);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -804,14 +779,13 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
if (Debug) {
|
||||
|
||||
if (Debug) {
|
||||
if (!inst_blocks)
|
||||
fprintf(stderr, "No instrumentation targets found.\n");
|
||||
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
|
||||
@ -819,15 +793,12 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifndef USE_NEW_PM
|
||||
static void registerAFLPass(const PassManagerBuilder &,
|
||||
legacy::PassManagerBase &PM) {
|
||||
|
||||
PM.add(new AFLCoverage());
|
||||
|
||||
}
|
||||
|
||||
static RegisterStandardPasses RegisterAFLPass(
|
||||
|
@ -64,12 +64,11 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define FATAL(x...) \
|
||||
do { \
|
||||
\
|
||||
fprintf(stderr, "FATAL: " x); \
|
||||
exit(1); \
|
||||
\
|
||||
#define FATAL(x...) \
|
||||
do { \
|
||||
fprintf(stderr, "FATAL: " x); \
|
||||
exit(1); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
using namespace llvm;
|
||||
@ -79,7 +78,6 @@ namespace {
|
||||
/* Function that we never instrument or analyze */
|
||||
/* Note: this ignore check is also called in isInInstrumentList() */
|
||||
bool isIgnoreFunction(const llvm::Function *F) {
|
||||
|
||||
// Starting from "LLVMFuzzer" these are functions used in libfuzzer based
|
||||
// fuzzing campaign installations, e.g. oss-fuzz
|
||||
|
||||
@ -117,9 +115,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
||||
};
|
||||
|
||||
for (auto const &ignoreListFunc : ignoreList) {
|
||||
|
||||
if (F->getName().startswith(ignoreListFunc)) { return true; }
|
||||
|
||||
}
|
||||
|
||||
static constexpr const char *ignoreSubstringList[] = {
|
||||
@ -131,67 +127,51 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
||||
};
|
||||
|
||||
for (auto const &ignoreListFunc : ignoreSubstringList) {
|
||||
|
||||
// hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
|
||||
if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
class AutoTokensPass : public ModulePass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
AutoTokensPass() : ModulePass(ID) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool runOnModule(Module &M) override;
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
std::vector<std::string> dictionary;
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::vector<std::string> dictionary;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
char AutoTokensPass::ID = 0;
|
||||
|
||||
|
||||
void dict2file(int fd, uint8_t *mem, uint32_t len) {
|
||||
uint32_t i, j, binary = 0;
|
||||
char line[MAX_AUTO_EXTRA * 8], tmp[8];
|
||||
uint32_t i, j, binary = 0;
|
||||
char line[MAX_AUTO_EXTRA * 8], tmp[8];
|
||||
|
||||
strcpy(line, "\"");
|
||||
j = 1;
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') {
|
||||
|
||||
line[j++] = mem[i];
|
||||
|
||||
} else {
|
||||
|
||||
if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) {
|
||||
|
||||
line[j] = 0;
|
||||
sprintf(tmp, "\\x%02x", (uint8_t)mem[i]);
|
||||
strcat(line, tmp);
|
||||
j = strlen(line);
|
||||
|
||||
}
|
||||
|
||||
binary = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
line[j] = 0;
|
||||
@ -199,15 +179,13 @@ void dict2file(int fd, uint8_t *mem, uint32_t len) {
|
||||
if (write(fd, line, strlen(line)) <= 0)
|
||||
FATAL("Could not write to dictionary file");
|
||||
fsync(fd);
|
||||
|
||||
}
|
||||
|
||||
bool AutoTokensPass::runOnModule(Module &M) {
|
||||
|
||||
DenseMap<Value *, std::string *> valueMap;
|
||||
char * ptr;
|
||||
char *ptr;
|
||||
int fd, found = 0;
|
||||
bool use_file = true;
|
||||
bool use_file = true;
|
||||
|
||||
/* Show a banner */
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
@ -215,22 +193,21 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
ptr = getenv("AFL_LLVM_DICT2FILE");
|
||||
|
||||
if (!ptr || *ptr != '/') {
|
||||
// fprintf(stderr, "AFL_LLVM_DICT2FILE is not set to an absolute path: %s\n", ptr);
|
||||
// fprintf(stderr, "Writing tokens into libafl_tokens section\n");
|
||||
// fprintf(stderr, "AFL_LLVM_DICT2FILE is not set to an absolute path:
|
||||
// %s\n", ptr); fprintf(stderr, "Writing tokens into libafl_tokens
|
||||
// section\n");
|
||||
|
||||
use_file = false;
|
||||
}
|
||||
|
||||
if(use_file) {
|
||||
if (use_file) {
|
||||
if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0)
|
||||
FATAL("Could not open/create %s.", ptr);
|
||||
}
|
||||
|
||||
|
||||
/* Instrument all the things! */
|
||||
|
||||
for (auto &F : M) {
|
||||
|
||||
if (isIgnoreFunction(&F)) continue;
|
||||
|
||||
/* Some implementation notes.
|
||||
@ -262,15 +239,12 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
*/
|
||||
|
||||
for (auto &BB : F) {
|
||||
|
||||
for (auto &IN : BB) {
|
||||
|
||||
CallInst *callInst = nullptr;
|
||||
CmpInst * cmpInst = nullptr;
|
||||
CmpInst *cmpInst = nullptr;
|
||||
|
||||
if ((cmpInst = dyn_cast<CmpInst>(&IN))) {
|
||||
|
||||
Value * op = cmpInst->getOperand(1);
|
||||
Value *op = cmpInst->getOperand(1);
|
||||
ConstantInt *ilen = dyn_cast<ConstantInt>(op);
|
||||
|
||||
/* 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) */
|
||||
|
||||
if (ilen && ilen->uge(0xffffffffffffffff) == false) {
|
||||
|
||||
uint64_t val2 = 0, val = ilen->getZExtValue();
|
||||
uint32_t len = 0;
|
||||
if (val > 0x10000 && val < 0xffffffff) len = 4;
|
||||
if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
|
||||
|
||||
if (len) {
|
||||
|
||||
auto c = cmpInst->getPredicate();
|
||||
|
||||
switch (c) {
|
||||
|
||||
case CmpInst::FCMP_OGT: // fall through
|
||||
case CmpInst::FCMP_OLE: // 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
|
||||
if ((len == 4 && (val & 80000000)) ||
|
||||
(len == 8 && (val & 8000000000000000))) {
|
||||
|
||||
if ((val & 0xffff) != 1) val2 = val - 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// fall through
|
||||
@ -321,10 +290,8 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
// signed comparison and it is a negative constant
|
||||
if ((len == 4 && (val & 80000000)) ||
|
||||
(len == 8 && (val & 8000000000000000))) {
|
||||
|
||||
if ((val & 0xffff) != 1) val2 = val - 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// fall through
|
||||
@ -338,37 +305,28 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
|
||||
default:
|
||||
val2 = 0;
|
||||
|
||||
}
|
||||
|
||||
if(use_file) {
|
||||
if (use_file) {
|
||||
dict2file(fd, (uint8_t *)&val, len);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
dictionary.push_back(std::string((char *)&val, len));
|
||||
}
|
||||
|
||||
found++;
|
||||
if (val2) {
|
||||
|
||||
if(use_file) {
|
||||
if (use_file) {
|
||||
dict2file(fd, (uint8_t *)&val2, len);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
dictionary.push_back(std::string((char *)&val2, len));
|
||||
}
|
||||
found++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||
|
||||
bool isStrcmp = true;
|
||||
bool isMemcmp = true;
|
||||
bool isStrncmp = true;
|
||||
@ -448,138 +406,96 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
getConstantStringInfo(Str1P, TmpStr);
|
||||
|
||||
if (TmpStr.empty()) {
|
||||
|
||||
HasStr1 = false;
|
||||
|
||||
} else {
|
||||
|
||||
HasStr1 = true;
|
||||
Str1 = TmpStr.str();
|
||||
|
||||
}
|
||||
|
||||
bool HasStr2;
|
||||
getConstantStringInfo(Str2P, TmpStr);
|
||||
if (TmpStr.empty()) {
|
||||
|
||||
HasStr2 = false;
|
||||
|
||||
} else {
|
||||
|
||||
HasStr2 = true;
|
||||
Str2 = TmpStr.str();
|
||||
|
||||
}
|
||||
|
||||
// we handle the 2nd parameter first because of llvm memcpy
|
||||
if (!HasStr2) {
|
||||
|
||||
auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
|
||||
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
|
||||
|
||||
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
|
||||
|
||||
if (Var->hasInitializer()) {
|
||||
|
||||
if (auto *Array =
|
||||
dyn_cast<ConstantDataArray>(Var->getInitializer())) {
|
||||
|
||||
HasStr2 = true;
|
||||
Str2 = Array->getRawDataValues().str();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// for the internal memcpy routine we only care for the second
|
||||
// parameter and are not reporting anything.
|
||||
if (isIntMemcpy == true) {
|
||||
|
||||
if (HasStr2 == true) {
|
||||
|
||||
Value * op2 = callInst->getArgOperand(2);
|
||||
Value *op2 = callInst->getArgOperand(2);
|
||||
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
|
||||
if (ilen) {
|
||||
|
||||
uint64_t literalLength = Str2.length();
|
||||
uint64_t optLength = ilen->getZExtValue();
|
||||
if (literalLength + 1 == optLength) {
|
||||
|
||||
Str2.append("\0", 1); // add null byte
|
||||
|
||||
}
|
||||
|
||||
if (optLength > Str2.length()) { optLength = Str2.length(); }
|
||||
|
||||
}
|
||||
|
||||
valueMap[Str1P] = new std::string(Str2);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// Neither a literal nor a global variable?
|
||||
// maybe it is a local variable that we saved
|
||||
if (!HasStr2) {
|
||||
|
||||
std::string *strng = valueMap[Str2P];
|
||||
if (strng && !strng->empty()) {
|
||||
|
||||
Str2 = *strng;
|
||||
HasStr2 = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!HasStr1) {
|
||||
|
||||
auto Ptr = dyn_cast<ConstantExpr>(Str1P);
|
||||
|
||||
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
|
||||
|
||||
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
|
||||
|
||||
if (Var->hasInitializer()) {
|
||||
|
||||
if (auto *Array =
|
||||
dyn_cast<ConstantDataArray>(Var->getInitializer())) {
|
||||
|
||||
HasStr1 = true;
|
||||
Str1 = Array->getRawDataValues().str();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Neither a literal nor a global variable?
|
||||
// maybe it is a local variable that we saved
|
||||
if (!HasStr1) {
|
||||
|
||||
std::string *strng = valueMap[Str1P];
|
||||
if (strng && !strng->empty()) {
|
||||
|
||||
Str1 = *strng;
|
||||
HasStr1 = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 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 (isMemcmp || isStrncmp || isStrncasecmp) {
|
||||
|
||||
Value * op2 = callInst->getArgOperand(2);
|
||||
Value *op2 = callInst->getArgOperand(2);
|
||||
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
|
||||
|
||||
if (ilen) {
|
||||
|
||||
uint64_t literalLength = optLen;
|
||||
optLen = ilen->getZExtValue();
|
||||
if (optLen > thestring.length()) { optLen = thestring.length(); }
|
||||
@ -610,33 +524,24 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
if (literalLength + 1 == optLen) { // add null byte
|
||||
thestring.append("\0", 1);
|
||||
addedNull = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add null byte if this is a string compare function and a null
|
||||
// was not already added
|
||||
if (!isMemcmp) {
|
||||
|
||||
if (addedNull == false && thestring[optLen - 1] != '\0') {
|
||||
|
||||
thestring.append("\0", 1); // add null byte
|
||||
optLen++;
|
||||
|
||||
}
|
||||
|
||||
if (!isStdString) {
|
||||
|
||||
// ensure we do not have garbage
|
||||
size_t offset = thestring.find('\0', 0);
|
||||
if (offset + 1 < optLen) optLen = offset + 1;
|
||||
thestring = thestring.substr(0, optLen);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
if(use_file){
|
||||
if (use_file) {
|
||||
dict2file(fd, (uint8_t *)ptr, optLen);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
dictionary.push_back(thestring.substr(0, optLen));
|
||||
}
|
||||
found++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(use_file){
|
||||
if (use_file) {
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
std::sort(dictionary.begin(), dictionary.end());
|
||||
auto last = std::unique(dictionary.begin(), dictionary.end());
|
||||
dictionary.erase(last, dictionary.end());
|
||||
for (auto token : dictionary) {
|
||||
memlen += token.length();
|
||||
count++;
|
||||
}
|
||||
|
||||
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++;
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static void registerAutoTokensPass(const PassManagerBuilder &,
|
||||
legacy::PassManagerBase &PM) {
|
||||
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(new AutoTokensPass());
|
||||
|
||||
}
|
||||
|
||||
static RegisterPass<AutoTokensPass> X("autotokens",
|
||||
"autotokens instrumentation pass",
|
||||
false, false);
|
||||
"autotokens instrumentation pass", false,
|
||||
false);
|
||||
|
||||
static RegisterStandardPasses RegisterAutoTokensPass(
|
||||
PassManagerBuilder::EP_OptimizerLast, registerAutoTokensPass);
|
||||
|
@ -55,7 +55,6 @@ namespace {
|
||||
/* Function that we never instrument or analyze */
|
||||
/* Note: this ignore check is also called in isInInstrumentList() */
|
||||
bool isIgnoreFunction(const llvm::Function *F) {
|
||||
|
||||
// Starting from "LLVMFuzzer" these are functions used in libfuzzer based
|
||||
// fuzzing campaign installations, e.g. oss-fuzz
|
||||
|
||||
@ -93,9 +92,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
||||
};
|
||||
|
||||
for (auto const &ignoreListFunc : ignoreList) {
|
||||
|
||||
if (F->getName().startswith(ignoreListFunc)) { return true; }
|
||||
|
||||
}
|
||||
|
||||
static constexpr const char *ignoreSubstringList[] = {
|
||||
@ -107,38 +104,32 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
||||
};
|
||||
|
||||
for (auto const &ignoreListFunc : ignoreSubstringList) {
|
||||
|
||||
// hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
|
||||
if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
class CmpLogRoutines : public ModulePass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
CmpLogRoutines() : ModulePass(ID) {}
|
||||
CmpLogRoutines() : ModulePass(ID) {
|
||||
}
|
||||
|
||||
bool runOnModule(Module &M) override;
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 4
|
||||
const char *getPassName() const override {
|
||||
|
||||
#else
|
||||
StringRef getPassName() const override {
|
||||
|
||||
#endif
|
||||
return "cmplog routines";
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
bool hookRtns(Module &M);
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -146,9 +137,8 @@ class CmpLogRoutines : public ModulePass {
|
||||
char CmpLogRoutines::ID = 0;
|
||||
|
||||
bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
|
||||
std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC;
|
||||
LLVMContext & C = M.getContext();
|
||||
LLVMContext &C = M.getContext();
|
||||
|
||||
Type *VoidTy = Type::getVoidTy(C);
|
||||
// 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 */
|
||||
for (auto &F : M) {
|
||||
|
||||
if (isIgnoreFunction(&F)) continue;
|
||||
|
||||
for (auto &BB : F) {
|
||||
|
||||
for (auto &IN : BB) {
|
||||
|
||||
CallInst *callInst = nullptr;
|
||||
|
||||
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||
|
||||
Function *Callee = callInst->getCalledFunction();
|
||||
if (!Callee) continue;
|
||||
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
|
||||
@ -316,9 +302,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
|
||||
if (isGccStdStringCString || isGccStdStringStdString ||
|
||||
isLlvmStdStringStdString || isLlvmStdStringCString) {
|
||||
|
||||
isPtrRtn = false;
|
||||
|
||||
}
|
||||
|
||||
if (isPtrRtn) { calls.push_back(callInst); }
|
||||
@ -326,13 +310,9 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
if (isGccStdStringCString) { gccStdC.push_back(callInst); }
|
||||
if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); }
|
||||
if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!calls.size() && !gccStdStd.size() && !gccStdC.size() &&
|
||||
@ -340,119 +320,104 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
return false;
|
||||
|
||||
for (auto &callInst : calls) {
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
||||
IRBuilder<> IRB(callInst->getParent());
|
||||
IRB.SetInsertPoint(callInst);
|
||||
|
||||
std::vector<Value *> args;
|
||||
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
|
||||
IRB.CreateCall(cmplogHookFn, args);
|
||||
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
|
||||
}
|
||||
|
||||
for (auto &callInst : gccStdStd) {
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
||||
IRBuilder<> IRB(callInst->getParent());
|
||||
IRB.SetInsertPoint(callInst);
|
||||
|
||||
std::vector<Value *> args;
|
||||
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
|
||||
IRB.CreateCall(cmplogGccStdStd, args);
|
||||
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
|
||||
}
|
||||
|
||||
for (auto &callInst : gccStdC) {
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
||||
IRBuilder<> IRB(callInst->getParent());
|
||||
IRB.SetInsertPoint(callInst);
|
||||
|
||||
std::vector<Value *> args;
|
||||
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
|
||||
IRB.CreateCall(cmplogGccStdC, args);
|
||||
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
|
||||
}
|
||||
|
||||
for (auto &callInst : llvmStdStd) {
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
||||
IRBuilder<> IRB(callInst->getParent());
|
||||
IRB.SetInsertPoint(callInst);
|
||||
|
||||
std::vector<Value *> args;
|
||||
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
|
||||
IRB.CreateCall(cmplogLlvmStdStd, args);
|
||||
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
|
||||
}
|
||||
|
||||
for (auto &callInst : llvmStdC) {
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
||||
IRBuilder<> IRB(callInst->getParent());
|
||||
IRB.SetInsertPoint(callInst);
|
||||
|
||||
std::vector<Value *> args;
|
||||
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
|
||||
IRB.CreateCall(cmplogLlvmStdC, args);
|
||||
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool CmpLogRoutines::runOnModule(Module &M) {
|
||||
|
||||
hookRtns(M);
|
||||
verifyModule(M);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static void registerCmpLogRoutinesPass(const PassManagerBuilder &,
|
||||
legacy::PassManagerBase &PM) {
|
||||
|
||||
auto p = new CmpLogRoutines();
|
||||
PM.add(p);
|
||||
|
||||
}
|
||||
|
||||
static RegisterStandardPasses RegisterCmpLogRoutinesPass(
|
||||
@ -466,4 +431,3 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO(
|
||||
PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
|
||||
registerCmpLogRoutinesPass);
|
||||
#endif
|
||||
|
||||
|
@ -54,59 +54,52 @@ typedef uint32_t prev_loc_t;
|
||||
|
||||
#define MAP_SIZE LIBAFL_ACCOUNTING_MAP_SIZE
|
||||
|
||||
|
||||
#define SECURITY_SENSITIVE_FUNCS(CF) static CF securitySensitiveFunctions[] = {\
|
||||
CF("memcpy"), \
|
||||
CF("strlen"), \
|
||||
CF("ReadImage"), \
|
||||
CF("memmove"), \
|
||||
CF("free"), \
|
||||
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"), \
|
||||
};
|
||||
|
||||
#define SECURITY_SENSITIVE_FUNCS(CF) \
|
||||
static CF securitySensitiveFunctions[] = { \
|
||||
CF("memcpy"), CF("strlen"), CF("ReadImage"), CF("memmove"), \
|
||||
CF("free"), 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;
|
||||
|
||||
enum AccountingGranularity {
|
||||
BB_GRAN,
|
||||
FUNC_GRAN,
|
||||
// LOOP,
|
||||
UKNOWN_GRAN
|
||||
BB_GRAN,
|
||||
FUNC_GRAN,
|
||||
// LOOP,
|
||||
UKNOWN_GRAN
|
||||
};
|
||||
|
||||
static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false), cl::NotHidden);
|
||||
static cl::opt<std::string> GranularityStr("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);
|
||||
static cl::opt<bool> Debug("debug", cl::desc("Debug prints"), cl::init(false),
|
||||
cl::NotHidden);
|
||||
static cl::opt<std::string> GranularityStr(
|
||||
"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 {
|
||||
|
||||
SECURITY_SENSITIVE_FUNCS(StringRef)
|
||||
|
||||
bool isSecuritySensitiveFunction(Function* F) {
|
||||
if (!F) return 0;
|
||||
auto func_name = F->getName();
|
||||
for (auto name : securitySensitiveFunctions) {
|
||||
if (func_name.contains(name)) {
|
||||
if (Debug)
|
||||
fprintf(stderr, "Counted %s as security sensitive", func_name.str().c_str());
|
||||
return 1;
|
||||
}
|
||||
bool isSecuritySensitiveFunction(Function *F) {
|
||||
if (!F) return 0;
|
||||
auto func_name = F->getName();
|
||||
for (auto name : securitySensitiveFunctions) {
|
||||
if (func_name.contains(name)) {
|
||||
if (Debug)
|
||||
fprintf(stderr, "Counted %s as security sensitive",
|
||||
func_name.str().c_str());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_NEW_PM
|
||||
@ -120,11 +113,10 @@ class AFLCoverage : public ModulePass {
|
||||
AFLCoverage() : ModulePass(ID) {
|
||||
#endif
|
||||
granularity = StringSwitch<AccountingGranularity>(GranularityStr)
|
||||
.Case("BB", BB_GRAN)
|
||||
.Case("FUNC", FUNC_GRAN)
|
||||
.Default(UKNOWN_GRAN);
|
||||
.Case("BB", BB_GRAN)
|
||||
.Case("FUNC", FUNC_GRAN)
|
||||
.Default(UKNOWN_GRAN);
|
||||
// initInstrumentList();
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_NEW_PM
|
||||
@ -134,10 +126,9 @@ class AFLCoverage : public ModulePass {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
uint32_t function_minimum_size = 1;
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
uint32_t function_minimum_size = 1;
|
||||
AccountingGranularity granularity;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -145,33 +136,30 @@ class AFLCoverage : public ModulePass {
|
||||
#ifdef USE_NEW_PM
|
||||
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
|
||||
llvmGetPassPluginInfo() {
|
||||
return {
|
||||
LLVM_PLUGIN_API_VERSION, "AFLCoverageAccounting", "v0.1",
|
||||
/* lambda to insert our pass into the pass pipeline. */
|
||||
[](PassBuilder &PB) {
|
||||
#if 1
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
MPM.addPass(AFLCoverage());
|
||||
}
|
||||
);
|
||||
/* TODO LTO registration */
|
||||
#else
|
||||
using PipelineElement = typename PassBuilder::PipelineElement;
|
||||
PB.registerPipelineParsingCallback(
|
||||
[](StringRef Name, ModulePassManager &MPM, ArrayRef<PipelineElement>) {
|
||||
if ( Name == "AFLCoverageAccounting" ) {
|
||||
MPM.addPass(AFLCoverage());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
return {LLVM_PLUGIN_API_VERSION, "AFLCoverageAccounting", "v0.1",
|
||||
/* lambda to insert our pass into the pass pipeline. */
|
||||
[](PassBuilder &PB) {
|
||||
#if 1
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
MPM.addPass(AFLCoverage());
|
||||
});
|
||||
/* TODO LTO registration */
|
||||
#else
|
||||
using PipelineElement = typename PassBuilder::PipelineElement;
|
||||
PB.registerPipelineParsingCallback([](StringRef Name,
|
||||
ModulePassManager &MPM,
|
||||
ArrayRef<PipelineElement>) {
|
||||
if (Name == "AFLCoverageAccounting") {
|
||||
MPM.addPass(AFLCoverage());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}};
|
||||
}
|
||||
#else
|
||||
|
||||
@ -187,7 +175,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
LLVMContext &C = M.getContext();
|
||||
|
||||
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
|
||||
uint32_t rand_seed;
|
||||
uint32_t rand_seed;
|
||||
unsigned int cur_loc = 0;
|
||||
|
||||
#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
|
||||
__afl_acc_prev_loc is thread-local. */
|
||||
|
||||
GlobalVariable *AFLMemOpPtr =
|
||||
new GlobalVariable(M, PointerType::get(Int32Ty, 0), false,
|
||||
GlobalValue::ExternalLinkage, 0, "__afl_acc_memop_ptr");
|
||||
GlobalVariable *AFLMemOpPtr = new GlobalVariable(
|
||||
M, PointerType::get(Int32Ty, 0), false, GlobalValue::ExternalLinkage, 0,
|
||||
"__afl_acc_memop_ptr");
|
||||
|
||||
GlobalVariable *AFLPrevLoc;
|
||||
|
||||
#if defined(__ANDROID__) || defined(__HAIKU__)
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc");
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc");
|
||||
#else
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc", 0,
|
||||
GlobalVariable::GeneralDynamicTLSModel, 0, false);
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc",
|
||||
0, GlobalVariable::GeneralDynamicTLSModel, 0, false);
|
||||
#endif
|
||||
|
||||
/* Instrument all the things! */
|
||||
@ -227,7 +215,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// scanForDangerousFunctions(&M);
|
||||
|
||||
for (auto &F : M) {
|
||||
|
||||
int has_calls = 0;
|
||||
if (Debug)
|
||||
fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(),
|
||||
@ -239,7 +226,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
std::list<Value *> todo;
|
||||
for (auto &BB : F) {
|
||||
|
||||
BasicBlock::iterator IP = BB.getFirstInsertionPt();
|
||||
IRBuilder<> IRB(&(*IP));
|
||||
|
||||
@ -250,8 +236,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
for (auto &I : BB) {
|
||||
switch (granularity) {
|
||||
case BB_GRAN:
|
||||
if (I.mayReadFromMemory() || I.mayWriteToMemory())
|
||||
++MemCnt;
|
||||
if (I.mayReadFromMemory() || I.mayWriteToMemory()) ++MemCnt;
|
||||
break;
|
||||
case FUNC_GRAN:
|
||||
if (auto *C = dyn_cast<CallInst>(&I)) {
|
||||
@ -275,36 +260,37 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
/* Load SHM pointer */
|
||||
|
||||
LoadInst *MemReadPtr = IRB.CreateLoad(AFLMemOpPtr);
|
||||
MemReadPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
Value *MemReadPtrIdx = IRB.CreateGEP(MemReadPtr, IRB.CreateXor(PrevLoc, CurLoc));
|
||||
MemReadPtr->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
Value *MemReadPtrIdx =
|
||||
IRB.CreateGEP(MemReadPtr, IRB.CreateXor(PrevLoc, CurLoc));
|
||||
|
||||
/* Update bitmap */
|
||||
|
||||
LoadInst *MemReadCount = IRB.CreateLoad(MemReadPtrIdx);
|
||||
MemReadCount->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
Value *MemReadIncr = IRB.CreateAdd(MemReadCount, ConstantInt::get(Int32Ty, MemCnt));
|
||||
MemReadCount->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
Value *MemReadIncr =
|
||||
IRB.CreateAdd(MemReadCount, ConstantInt::get(Int32Ty, MemCnt));
|
||||
IRB.CreateStore(MemReadIncr, MemReadPtrIdx)
|
||||
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
/* Update prev_loc */
|
||||
|
||||
StoreInst * Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1),
|
||||
AFLPrevLoc);
|
||||
StoreInst *Store =
|
||||
IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc);
|
||||
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
inst_blocks++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Debug) {
|
||||
|
||||
if (Debug) {
|
||||
if (!inst_blocks)
|
||||
fprintf(stderr, "No instrumentation targets found.\n");
|
||||
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
|
||||
@ -312,15 +298,12 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifndef USE_NEW_PM
|
||||
static void registerAFLPass(const PassManagerBuilder &,
|
||||
legacy::PassManagerBase &PM) {
|
||||
|
||||
PM.add(new AFLCoverage());
|
||||
|
||||
}
|
||||
|
||||
static RegisterStandardPasses RegisterAFLPass(
|
||||
|
Loading…
x
Reference in New Issue
Block a user