mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-03 09:14:30 +00:00
[sanitizers] trace buffer API to use user-allocated buffer.
Differential Revision: https://reviews.llvm.org/D23185 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277859 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
506c14dc34
commit
4613003000
@ -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),
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
@ -334,6 +335,8 @@ private:
|
||||
std::vector<Mutator> DefaultMutators;
|
||||
};
|
||||
|
||||
class CoverageController;
|
||||
|
||||
class Fuzzer {
|
||||
public:
|
||||
|
||||
@ -346,17 +349,16 @@ public:
|
||||
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;
|
||||
@ -366,6 +368,7 @@ public:
|
||||
};
|
||||
|
||||
Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
|
||||
~Fuzzer();
|
||||
void AddToCorpus(const Unit &U) {
|
||||
Corpus.push_back(U);
|
||||
UpdateCorpusDistribution();
|
||||
@ -481,6 +484,7 @@ private:
|
||||
|
||||
// Maximum recorded coverage.
|
||||
Coverage MaxCoverage;
|
||||
std::unique_ptr<CoverageController> CController;
|
||||
|
||||
// Need to know our own thread.
|
||||
static thread_local bool IsMyThread;
|
||||
|
@ -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);
|
||||
@ -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();
|
||||
@ -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
|
||||
@ -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);
|
||||
@ -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];
|
||||
@ -421,15 +444,13 @@ void Fuzzer::ShuffleAndMinimize() {
|
||||
}
|
||||
|
||||
bool Fuzzer::UpdateMaxCoverage() {
|
||||
uintptr_t PrevBufferLen = MaxCoverage.PcBufferLen;
|
||||
bool Res = CoverageController::RecordMax(Options, &MaxCoverage);
|
||||
uintptr_t PrevPcBufferPos = MaxCoverage.PcBufferPos;
|
||||
bool Res = CController->RecordMax(&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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user