Skip to content

Commit

Permalink
[sanitizers] trace buffer API to use user-allocated buffer.
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D23185

llvm-svn: 277859
  • Loading branch information
aizatsky-chromium committed Aug 5, 2016
1 parent 04897dc commit b4bbc3b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 27 deletions.
3 changes: 2 additions & 1 deletion llvm/lib/Fuzzer/FuzzerExtFunctions.def
Expand Up @@ -29,7 +29,8 @@ EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t,
EXT_FUNC(__lsan_enable, void, (), false);
EXT_FUNC(__lsan_disable, void, (), false);
EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false);
EXT_FUNC(__sanitizer_get_coverage_pc_buffer, uintptr_t, (uintptr_t**), true);
EXT_FUNC(__sanitizer_set_coverage_pc_buffer, void, (uintptr_t*, uintptr_t), true);
EXT_FUNC(__sanitizer_get_coverage_pc_buffer_pos, uintptr_t, (), true);
EXT_FUNC(__sanitizer_get_number_of_counters, size_t, (), false);
EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int,
(void (*malloc_hook)(const volatile void *, size_t),
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/Fuzzer/FuzzerInternal.h
Expand Up @@ -19,6 +19,7 @@
#include <climits>
#include <cstddef>
#include <cstdlib>
#include <memory>
#include <random>
#include <string.h>
#include <string>
Expand Down Expand Up @@ -334,6 +335,8 @@ class MutationDispatcher {
std::vector<Mutator> DefaultMutators;
};

class CoverageController;

class Fuzzer {
public:

Expand All @@ -346,17 +349,16 @@ class Fuzzer {
CallerCalleeCoverage = 0;
PcMapBits = 0;
CounterBitmapBits = 0;
PcBufferLen = 0;
CounterBitmap.clear();
PCMap.Reset();
PcBufferPos = 0;
}

std::string DebugString() const;

size_t BlockCoverage;
size_t CallerCalleeCoverage;

size_t PcBufferLen;
size_t PcBufferPos;
// Precalculated number of bits in CounterBitmap.
size_t CounterBitmapBits;
std::vector<uint8_t> CounterBitmap;
Expand All @@ -366,6 +368,7 @@ class Fuzzer {
};

Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
~Fuzzer();
void AddToCorpus(const Unit &U) {
Corpus.push_back(U);
UpdateCorpusDistribution();
Expand Down Expand Up @@ -481,6 +484,7 @@ class Fuzzer {

// Maximum recorded coverage.
Coverage MaxCoverage;
std::unique_ptr<CoverageController> CController;

// Need to know our own thread.
static thread_local bool IsMyThread;
Expand Down
67 changes: 44 additions & 23 deletions llvm/lib/Fuzzer/FuzzerLoop.cpp
Expand Up @@ -53,20 +53,33 @@ static void MissingExternalApiFunction(const char *FnName) {
// Only one Fuzzer per process.
static Fuzzer *F;

struct CoverageController {
static void Reset() {
// Only one CoverageController per process should be created.
class CoverageController {
public:
explicit CoverageController(const FuzzingOptions &Options)
: Options(Options) {
if (Options.PrintNewCovPcs) {
PcBufferLen = 1 << 24;
PcBuffer = new uintptr_t[PcBufferLen];
EF->__sanitizer_set_coverage_pc_buffer(PcBuffer, PcBufferLen);
}
}

uintptr_t* pc_buffer() const { return PcBuffer; }

void Reset() {
CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage);
EF->__sanitizer_reset_coverage();
PcMapResetCurrent();
}

static void ResetCounters(const FuzzingOptions &Options) {
void ResetCounters() {
if (Options.UseCounters) {
EF->__sanitizer_update_counter_bitset_and_clear_counters(0);
}
}

static void Prepare(const FuzzingOptions &Options, Fuzzer::Coverage *C) {
void Prepare(Fuzzer::Coverage *C) {
if (Options.UseCounters) {
size_t NumCounters = EF->__sanitizer_get_number_of_counters();
C->CounterBitmap.resize(NumCounters);
Expand All @@ -75,7 +88,7 @@ struct CoverageController {

// Records data to a maximum coverage tracker. Returns true if additional
// coverage was discovered.
static bool RecordMax(const FuzzingOptions &Options, Fuzzer::Coverage *C) {
bool RecordMax(Fuzzer::Coverage *C) {
bool Res = false;

uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage();
Expand Down Expand Up @@ -110,16 +123,23 @@ struct CoverageController {
C->PcMapBits = NewPcMapBits;
}

uintptr_t *CoverageBuf;
uint64_t NewPcBufferLen =
EF->__sanitizer_get_coverage_pc_buffer(&CoverageBuf);
if (NewPcBufferLen > C->PcBufferLen) {
uint64_t NewPcBufferPos = EF->__sanitizer_get_coverage_pc_buffer_pos();
if (NewPcBufferPos > C->PcBufferPos) {
Res = true;
C->PcBufferLen = NewPcBufferLen;
C->PcBufferPos = NewPcBufferPos;
}

if (NewPcBufferPos >= PcBufferLen) {
Printf("ERROR: PC buffer overflow.\n");
}

return Res;
}

private:
const FuzzingOptions Options;
uintptr_t* PcBuffer = nullptr;
size_t PcBufferLen = 0;
};

// Leak detection is expensive, so we first check if there were more mallocs
Expand All @@ -145,7 +165,8 @@ void FreeHook(const volatile void *ptr) {
}

Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
: CB(CB), MD(MD), Options(Options) {
: CB(CB), MD(MD), Options(Options),
CController(new CoverageController(Options)) {
SetDeathCallback();
InitializeTraceState();
assert(!F);
Expand All @@ -156,6 +177,8 @@ Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
}

Fuzzer::~Fuzzer() { }

void Fuzzer::LazyAllocateCurrentUnitData() {
if (CurrentUnitData || Options.MaxLen == 0) return;
CurrentUnitData = new uint8_t[Options.MaxLen];
Expand Down Expand Up @@ -421,15 +444,13 @@ void Fuzzer::ShuffleAndMinimize() {
}

bool Fuzzer::UpdateMaxCoverage() {
uintptr_t PrevBufferLen = MaxCoverage.PcBufferLen;
bool Res = CoverageController::RecordMax(Options, &MaxCoverage);

if (Options.PrintNewCovPcs && PrevBufferLen != MaxCoverage.PcBufferLen) {
uintptr_t *CoverageBuf;
EF->__sanitizer_get_coverage_pc_buffer(&CoverageBuf);
assert(CoverageBuf);
for (size_t I = PrevBufferLen; I < MaxCoverage.PcBufferLen; ++I) {
Printf("%p\n", CoverageBuf[I]);
uintptr_t PrevPcBufferPos = MaxCoverage.PcBufferPos;
bool Res = CController->RecordMax(&MaxCoverage);

if (Options.PrintNewCovPcs && PrevPcBufferPos != MaxCoverage.PcBufferPos) {
uintptr_t* PcBuffer = CController->pc_buffer();
for (size_t I = PrevPcBufferPos; I < MaxCoverage.PcBufferPos; ++I) {
Printf("%p\n", PcBuffer[I]);
}
}

Expand All @@ -440,7 +461,7 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
TotalNumberOfRuns++;

// TODO(aizatsky): this Reset call seems to be not needed.
CoverageController::ResetCounters(Options);
CController->ResetCounters();
ExecuteCallback(Data, Size);
bool Res = UpdateMaxCoverage();

Expand Down Expand Up @@ -693,9 +714,9 @@ size_t Fuzzer::ChooseUnitIdxToMutate() {
}

void Fuzzer::ResetCoverage() {
CoverageController::Reset();
CController->Reset();
MaxCoverage.Reset();
CoverageController::Prepare(Options, &MaxCoverage);
CController->Prepare(&MaxCoverage);
}

// Experimental search heuristic: drilling.
Expand Down

0 comments on commit b4bbc3b

Please sign in to comment.