mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-19 13:03:44 +00:00
@ -58,6 +58,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
MacOS shared memory
|
||||
- updated the grammar custom mutator to the newest version
|
||||
- add -d (add dead fuzzer stats) to afl-whatsup
|
||||
- add thread safe counters for LLVM CLASSIC (set AFL_LLVM_THREADSAFE_INST)
|
||||
- added AFL_PRINT_FILENAMES to afl-showmap/cmin to print the
|
||||
current filename
|
||||
- afl-showmap/cmin will now process queue items in alphabetical order
|
||||
|
@ -231,6 +231,11 @@ Then there are a few specific features that are only available in instrumentatio
|
||||
|
||||
See [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) for more information.
|
||||
|
||||
### Thread safe instrumentation counters (in mode LLVM CLASSIC)
|
||||
- Setting `AFL_LLVM_THREADSAFE_INST` will inject code that implements thread safe counters.
|
||||
The overhead is a bit higher compared to the older non-thread safe case.
|
||||
`AFL_LLVM_NOT_ZERO` and `AFL_LLVM_SKIP_NEVERZERO` are supported (see below).
|
||||
|
||||
### NOT_ZERO
|
||||
|
||||
- Setting `AFL_LLVM_NOT_ZERO=1` during compilation will use counters
|
||||
|
@ -126,6 +126,7 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_NGRAM_SIZE",
|
||||
"AFL_LLVM_NOT_ZERO",
|
||||
"AFL_LLVM_INSTRUMENT_FILE",
|
||||
"AFL_LLVM_THREADSAFE_INST",
|
||||
"AFL_LLVM_SKIP_NEVERZERO",
|
||||
"AFL_NO_AFFINITY",
|
||||
"AFL_TRY_AFFINITY",
|
||||
|
@ -144,6 +144,10 @@ is not optimal and was only fixed in llvm 9.
|
||||
You can set this with AFL_LLVM_NOT_ZERO=1
|
||||
See [README.neverzero.md](README.neverzero.md)
|
||||
|
||||
Support for thread safe counters has been added for mode LLVM CLASSIC.
|
||||
Activate it with `AFL_LLVM_THREADSAFE_INST=1`. The tradeoff is better precision in
|
||||
multi threaded apps for a slightly higher instrumentation overhead.
|
||||
|
||||
## 4) Snapshot feature
|
||||
|
||||
To speed up fuzzing you can use a linux loadable kernel module which enables
|
||||
|
@ -16,11 +16,12 @@ at a very little cost (one instruction per edge).
|
||||
(The alternative of saturated counters has been tested also and proved to be
|
||||
inferior in terms of path discovery.)
|
||||
|
||||
This is implemented in afl-gcc and afl-gcc-fast, however for llvm_mode this is optional if
|
||||
the llvm version is below 9 - as there is a perfomance bug that is only fixed
|
||||
in version 9 and onwards.
|
||||
This is implemented in afl-gcc and afl-gcc-fast, however for llvm_mode this is
|
||||
optional if multithread safe counters are selected or the llvm version is below
|
||||
9 - as there are severe performance costs in these cases.
|
||||
|
||||
If you want to enable this for llvm versions below 9 then set
|
||||
If you want to enable this for llvm versions below 9 or thread safe counters
|
||||
then set
|
||||
|
||||
```
|
||||
export AFL_LLVM_NOT_ZERO=1
|
||||
@ -33,3 +34,8 @@ AFL_LLVM_SKIP_NEVERZERO=1
|
||||
```
|
||||
If the target does not have extensive loops or functions that are called
|
||||
a lot then this can give a small performance boost.
|
||||
|
||||
Please note that the default counter implementations are not thread safe!
|
||||
|
||||
Support for thread safe counters in mode LLVM CLASSIC can be activated with setting
|
||||
`AFL_LLVM_THREADSAFE_INST=1`.
|
@ -236,7 +236,8 @@ class ModuleSanitizerCoverage {
|
||||
uint32_t inst = 0;
|
||||
uint32_t afl_global_id = 0;
|
||||
uint64_t map_addr = 0;
|
||||
char * skip_nozero = NULL;
|
||||
const char * skip_nozero = NULL;
|
||||
const char * use_threadsafe_counters = nullptr;
|
||||
std::vector<BasicBlock *> BlockList;
|
||||
DenseMap<Value *, std::string *> valueMap;
|
||||
std::vector<std::string> dictionary;
|
||||
@ -437,6 +438,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
be_quiet = 1;
|
||||
|
||||
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
|
||||
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
|
||||
|
||||
if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL)
|
||||
if ((afl_global_id = atoi(ptr)) < 0)
|
||||
@ -1208,7 +1210,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
||||
return; // Should not instrument sanitizer init functions.
|
||||
if (F.getName().startswith("__sanitizer_"))
|
||||
return; // Don't instrument __sanitizer_* callbacks.
|
||||
// Don't touch available_externally functions, their actual body is elewhere.
|
||||
// Don't touch available_externally functions, their actual body is elsewhere.
|
||||
if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return;
|
||||
// Don't instrument MSVC CRT configuration helpers. They may run before normal
|
||||
// initialization.
|
||||
@ -1495,23 +1497,33 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
}
|
||||
|
||||
/* Update bitmap */
|
||||
if (use_threadsafe_counters) { /* Atomic */
|
||||
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
if (skip_nozero == NULL) {
|
||||
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Tyi);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx)
|
||||
->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(Mo->getMDKindID("nosanitize"),
|
||||
MDNode::get(*Ct, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
if (skip_nozero == NULL) {
|
||||
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Tyi);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
|
||||
}
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx)
|
||||
->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
|
||||
|
||||
}
|
||||
// done :)
|
||||
|
||||
inst++;
|
||||
|
@ -86,7 +86,8 @@ const char SanCovPCsSectionName[] = "sancov_pcs";
|
||||
|
||||
const char SanCovLowestStackName[] = "__sancov_lowest_stack";
|
||||
|
||||
static char *skip_nozero;
|
||||
static const char *skip_nozero;
|
||||
static const char *use_threadsafe_counters;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -386,6 +387,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
be_quiet = 1;
|
||||
|
||||
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
|
||||
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
|
||||
|
||||
initInstrumentList();
|
||||
scanForDangerousFunctions(&M);
|
||||
@ -1068,21 +1070,32 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
/* Load counter for CurLoc */
|
||||
|
||||
Value * MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
|
||||
/* Update bitmap */
|
||||
if (use_threadsafe_counters) {
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
if (skip_nozero == NULL) {
|
||||
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx);
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
/* Update bitmap */
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
if (skip_nozero == NULL) {
|
||||
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
|
||||
}
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx);
|
||||
|
||||
}
|
||||
|
||||
// done :)
|
||||
|
||||
|
@ -93,7 +93,8 @@ class AFLLTOPass : public ModulePass {
|
||||
uint32_t function_minimum_size = 1;
|
||||
uint32_t inst_blocks = 0, inst_funcs = 0, total_instr = 0;
|
||||
unsigned long long int map_addr = 0x10000;
|
||||
char * skip_nozero = NULL;
|
||||
const char *skip_nozero = NULL;
|
||||
const char *use_threadsafe_counters = nullptr;
|
||||
|
||||
};
|
||||
|
||||
@ -131,6 +132,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
|
||||
|
||||
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
||||
|
||||
if ((documentFile = fopen(ptr, "a")) == NULL)
|
||||
@ -839,23 +842,28 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
|
||||
/* Update bitmap */
|
||||
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
if (use_threadsafe_counters) {
|
||||
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
} else {
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
if (skip_nozero == NULL) {
|
||||
if (skip_nozero == NULL) {
|
||||
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
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));
|
||||
}
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx)
|
||||
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
// done :)
|
||||
|
||||
inst_blocks++;
|
||||
|
@ -85,7 +85,8 @@ class AFLCoverage : public ModulePass {
|
||||
uint32_t ctx_k = 0;
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
uint32_t function_minimum_size = 1;
|
||||
char * ctx_str = NULL, *caller_str = NULL, *skip_nozero = NULL;
|
||||
const char * ctx_str = NULL, *caller_str = NULL, *skip_nozero = NULL;
|
||||
const char * use_threadsafe_counters = nullptr;
|
||||
|
||||
};
|
||||
|
||||
@ -182,6 +183,26 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
char *neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO");
|
||||
#endif
|
||||
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
|
||||
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
|
||||
|
||||
if ((isatty(2) && !getenv("AFL_QUIET")) || !!getenv("AFL_DEBUG")) {
|
||||
|
||||
if (use_threadsafe_counters) {
|
||||
if (!getenv("AFL_LLVM_NOT_ZERO")) {
|
||||
skip_nozero = "1";
|
||||
SAYF(cCYA "afl-llvm-pass" VERSION cRST " using thread safe counters\n");
|
||||
}
|
||||
else {
|
||||
SAYF(cCYA "afl-llvm-pass" VERSION cRST
|
||||
" using thread safe not-zero-counters\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SAYF(cCYA "afl-llvm-pass" VERSION cRST " using non-thread safe instrumentation\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsigned PrevLocSize = 0;
|
||||
unsigned PrevCallerSize = 0;
|
||||
@ -388,7 +409,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
#endif
|
||||
|
||||
// other constants we need
|
||||
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
|
||||
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
|
||||
|
||||
Value * PrevCtx = NULL; // CTX sensitive coverage
|
||||
@ -410,6 +430,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
if (F.size() < function_minimum_size) continue;
|
||||
|
||||
std::list<Value *> todo;
|
||||
for (auto &BB : F) {
|
||||
|
||||
BasicBlock::iterator IP = BB.getFirstInsertionPt();
|
||||
@ -628,37 +649,63 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
/* Update bitmap */
|
||||
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
if (use_threadsafe_counters) {/* 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 (!skip_nozero) {
|
||||
#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 (!skip_nozero) {
|
||||
|
||||
#endif
|
||||
/* hexcoder: Realize a counter that skips zero during overflow.
|
||||
* Once this counter reaches its maximum value, it next increments to 1
|
||||
*
|
||||
* Instead of
|
||||
* Counter + 1 -> Counter
|
||||
* we inject now this
|
||||
* Counter + 1 -> {Counter, OverflowFlag}
|
||||
* Counter + OverflowFlag -> Counter
|
||||
*/
|
||||
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
#endif
|
||||
// register MapPtrIdx in a todo list
|
||||
todo.push_back(MapPtrIdx);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx)
|
||||
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
#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 (!skip_nozero) {
|
||||
|
||||
#endif
|
||||
/* hexcoder: Realize a counter that skips zero during overflow.
|
||||
* Once this counter reaches its maximum value, it next increments to 1
|
||||
*
|
||||
* Instead of
|
||||
* Counter + 1 -> Counter
|
||||
* we inject now this
|
||||
* Counter + 1 -> {Counter, OverflowFlag}
|
||||
* Counter + OverflowFlag -> Counter
|
||||
*/
|
||||
|
||||
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
|
||||
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 */
|
||||
|
||||
/* Update prev_loc history vector (by placing cur_loc at the head of the
|
||||
vector and shuffle the other elements back by one) */
|
||||
@ -715,6 +762,105 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
if (use_threadsafe_counters) { /*Atomic NeverZero */
|
||||
// handle the list of registered blocks to instrument
|
||||
for (auto val : todo) {
|
||||
/* hexcoder: Realize a thread-safe counter that skips zero during overflow. Once this counter reaches its maximum value, it next increments to 1
|
||||
*
|
||||
* Instead of
|
||||
* Counter + 1 -> Counter
|
||||
* we inject now this
|
||||
* Counter + 1 -> {Counter, OverflowFlag}
|
||||
* Counter + OverflowFlag -> Counter
|
||||
*/
|
||||
|
||||
/* equivalent c code looks like this
|
||||
* Thanks to
|
||||
https://preshing.com/20150402/you-can-do-any-kind-of-atomic-read-modify-write-operation/
|
||||
|
||||
int old = atomic_load_explicit(&Counter, memory_order_relaxed);
|
||||
int new;
|
||||
do {
|
||||
if (old == 255) {
|
||||
new = 1;
|
||||
} else {
|
||||
new = old + 1;
|
||||
}
|
||||
} while (!atomic_compare_exchange_weak_explicit(&Counter, &old, new,
|
||||
memory_order_relaxed, memory_order_relaxed));
|
||||
|
||||
*/
|
||||
|
||||
Value * MapPtrIdx = val;
|
||||
Instruction * MapPtrIdxInst = cast<Instruction>(val);
|
||||
BasicBlock::iterator it0(&(*MapPtrIdxInst));
|
||||
++it0;
|
||||
IRBuilder<> IRB(&(*it0));
|
||||
|
||||
// load the old counter value atomically
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setAlignment(llvm::Align());
|
||||
Counter->setAtomic(llvm::AtomicOrdering::Monotonic);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
BasicBlock *BB = IRB.GetInsertBlock();
|
||||
// insert a basic block with the corpus of a do while loop
|
||||
// the calculation may need to repeat, if atomic compare_exchange is not successful
|
||||
|
||||
BasicBlock::iterator it(*Counter);
|
||||
it++; // split after load counter
|
||||
BasicBlock *end_bb = BB->splitBasicBlock(it);
|
||||
end_bb->setName("injected");
|
||||
|
||||
// insert the block before the second half of the split
|
||||
BasicBlock *do_while_bb =
|
||||
BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
|
||||
|
||||
// set terminator of BB from target end_bb to target do_while_bb
|
||||
auto term = BB->getTerminator();
|
||||
BranchInst::Create(do_while_bb, BB);
|
||||
term->eraseFromParent();
|
||||
|
||||
// continue to fill instructions into the do_while loop
|
||||
IRB.SetInsertPoint(do_while_bb, do_while_bb->getFirstInsertionPt());
|
||||
|
||||
PHINode *PN = IRB.CreatePHI(Int8Ty, 2);
|
||||
|
||||
// compare with maximum value 0xff
|
||||
auto *Cmp = IRB.CreateICmpEQ(Counter, ConstantInt::get(Int8Ty, -1));
|
||||
|
||||
// increment the counter
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
// select the counter value or 1
|
||||
auto *Select = IRB.CreateSelect(Cmp, One, Incr);
|
||||
|
||||
// try to save back the new counter value
|
||||
auto *CmpXchg = IRB.CreateAtomicCmpXchg(
|
||||
MapPtrIdx, PN, Select, llvm::AtomicOrdering::Monotonic,
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
CmpXchg->setAlignment(llvm::Align());
|
||||
CmpXchg->setWeak(true);
|
||||
CmpXchg->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
// get the result of trying to update the Counter
|
||||
Value *Success =
|
||||
IRB.CreateExtractValue(CmpXchg, ArrayRef<unsigned>({1}));
|
||||
// get the (possibly updated) value of Counter
|
||||
Value *OldVal =
|
||||
IRB.CreateExtractValue(CmpXchg, ArrayRef<unsigned>({0}));
|
||||
|
||||
// initially we use Counter
|
||||
PN->addIncoming(Counter, BB);
|
||||
// on retry, we use the updated value
|
||||
PN->addIncoming(OldVal, do_while_bb);
|
||||
|
||||
// if the cmpXchg was not successful, retry
|
||||
IRB.CreateCondBr(Success, end_bb, do_while_bb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1777,6 +1777,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
SAYF(
|
||||
"\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
|
||||
"variables:\n"
|
||||
" AFL_LLVM_THREADSAFE_INST: instrument with thread safe counters\n"
|
||||
|
||||
COUNTER_BEHAVIOUR
|
||||
|
||||
|
@ -43,6 +43,36 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
$ECHO "$RED[!] llvm_mode failed"
|
||||
CODE=1
|
||||
}
|
||||
AFL_LLVM_INSTRUMENT=CLASSIC AFL_LLVM_THREADSAFE_INST=1 ../afl-clang-fast -o test-instr.ts ../test-instr.c > /dev/null 2>&1
|
||||
test -e test-instr.ts && {
|
||||
$ECHO "$GREEN[+] llvm_mode threadsafe compilation succeeded"
|
||||
echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.ts.0 -r -- ./test-instr.ts > /dev/null 2>&1
|
||||
AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.ts.1 -r -- ./test-instr.ts < /dev/null > /dev/null 2>&1
|
||||
test -e test-instr.ts.0 -a -e test-instr.ts.1 && {
|
||||
diff test-instr.ts.0 test-instr.ts.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] llvm_mode threadsafe instrumentation should be different on different input but is not"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] llvm_mode threadsafe instrumentation present and working correctly"
|
||||
TUPLES=`echo 0|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.ts 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 2 -a "$TUPLES" -lt 8 && {
|
||||
$ECHO "$GREEN[+] llvm_mode run reported $TUPLES threadsafe instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode threadsafe instrumentation produces weird numbers: $TUPLES"
|
||||
CODE=1
|
||||
}
|
||||
test "$TUPLES" -lt 3 && SKIP=1
|
||||
true
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode threadsafe instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-instr.ts.0 test-instr.ts.1
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode (threadsafe) failed"
|
||||
CODE=1
|
||||
}
|
||||
../afl-clang-fast -DTEST_SHARED_OBJECT=1 -z defs -fPIC -shared -o test-instr.so ../test-instr.c > /dev/null 2>&1
|
||||
test -e test-instr.so && {
|
||||
$ECHO "$GREEN[+] llvm_mode shared object with -z defs compilation succeeded"
|
||||
|
Reference in New Issue
Block a user