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.
|
//! 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
|
||||||
|
@ -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
|
||||||
@ -110,7 +129,6 @@ class AFLCoverage : public ModulePass {
|
|||||||
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 */
|
||||||
/* TODO LTO registration */
|
#else
|
||||||
#else
|
|
||||||
using PipelineElement = typename PassBuilder::PipelineElement;
|
using PipelineElement = typename PassBuilder::PipelineElement;
|
||||||
PB.registerPipelineParsingCallback(
|
PB.registerPipelineParsingCallback([](StringRef Name,
|
||||||
[](StringRef Name, ModulePassManager &MPM, ArrayRef<PipelineElement>) {
|
ModulePassManager &MPM,
|
||||||
if ( Name == "AFLCoverage" ) {
|
ArrayRef<PipelineElement>) {
|
||||||
|
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);
|
||||||
@ -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(
|
||||||
|
"Bad value of K for K-context sensitivity (must be between 1 and "
|
||||||
|
"CTX_MAX_K (%u))",
|
||||||
CTX_MAX_K);
|
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
|
||||||
@ -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,7 +671,6 @@ 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)
|
||||||
@ -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,34 +719,32 @@ 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);
|
||||||
@ -806,12 +781,11 @@ 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(
|
||||||
|
@ -66,7 +66,6 @@
|
|||||||
|
|
||||||
#define FATAL(x...) \
|
#define FATAL(x...) \
|
||||||
do { \
|
do { \
|
||||||
\
|
|
||||||
fprintf(stderr, "FATAL: " x); \
|
fprintf(stderr, "FATAL: " x); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
\
|
\
|
||||||
@ -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,40 +127,31 @@ 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];
|
||||||
@ -172,26 +159,19 @@ void dict2file(int fd, uint8_t *mem, uint32_t len) {
|
|||||||
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,13 +179,11 @@ 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;
|
||||||
|
|
||||||
@ -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,31 +555,24 @@ 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
|
// sort and unique the dictionary
|
||||||
@ -683,21 +581,16 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
|||||||
dictionary.erase(last, dictionary.end());
|
dictionary.erase(last, dictionary.end());
|
||||||
|
|
||||||
for (auto token : dictionary) {
|
for (auto token : dictionary) {
|
||||||
|
|
||||||
memlen += token.length();
|
memlen += token.length();
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (count) {
|
|
||||||
|
|
||||||
auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
|
auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
for (auto token : dictionary) {
|
for (auto token : dictionary) {
|
||||||
|
|
||||||
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
|
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
|
||||||
|
|
||||||
// This lenght is guranteed to be < MAX_AUTO_EXTRA
|
// This lenght is guranteed to be < MAX_AUTO_EXTRA
|
||||||
ptrhld.get()[offset++] = (uint8_t)token.length();
|
ptrhld.get()[offset++] = (uint8_t)token.length();
|
||||||
memcpy(ptrhld.get() + offset, token.c_str(), token.length());
|
memcpy(ptrhld.get() + offset, token.c_str(), token.length());
|
||||||
@ -707,28 +600,25 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
ArrayType* arrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
|
ArrayType *arrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
|
||||||
|
|
||||||
// The actual dict
|
// 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());
|
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");
|
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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -54,29 +54,14 @@ 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;
|
||||||
|
|
||||||
@ -87,22 +72,30 @@ enum AccountingGranularity {
|
|||||||
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",
|
||||||
|
func_name.str().c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +117,6 @@ class AFLCoverage : public ModulePass {
|
|||||||
.Case("FUNC", FUNC_GRAN)
|
.Case("FUNC", FUNC_GRAN)
|
||||||
.Default(UKNOWN_GRAN);
|
.Default(UKNOWN_GRAN);
|
||||||
// initInstrumentList();
|
// initInstrumentList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_NEW_PM
|
#ifdef USE_NEW_PM
|
||||||
@ -137,7 +129,6 @@ class AFLCoverage : public ModulePass {
|
|||||||
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 */
|
||||||
/* TODO LTO registration */
|
#else
|
||||||
#else
|
|
||||||
using PipelineElement = typename PassBuilder::PipelineElement;
|
using PipelineElement = typename PassBuilder::PipelineElement;
|
||||||
PB.registerPipelineParsingCallback(
|
PB.registerPipelineParsingCallback([](StringRef Name,
|
||||||
[](StringRef Name, ModulePassManager &MPM, ArrayRef<PipelineElement>) {
|
ModulePassManager &MPM,
|
||||||
if ( Name == "AFLCoverageAccounting" ) {
|
ArrayRef<PipelineElement>) {
|
||||||
|
if (Name == "AFLCoverageAccounting") {
|
||||||
MPM.addPass(AFLCoverage());
|
MPM.addPass(AFLCoverage());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
#endif
|
||||||
#endif
|
}};
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -206,9 +194,9 @@ 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;
|
||||||
|
|
||||||
@ -217,8 +205,8 @@ bool AFLCoverage::runOnModule(Module &M) {
|
|||||||
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(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user