forked from OSchip/llvm-project
[libFuzzer] add -print_coverage=1 flag to print coverage directly from libFuzzer
llvm-svn: 281866
This commit is contained in:
parent
f33a6b713b
commit
b706b481ba
|
@ -425,6 +425,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
||||||
!DoPlainRun || Flags.minimize_crash_internal_step;
|
!DoPlainRun || Flags.minimize_crash_internal_step;
|
||||||
Options.PrintNewCovPcs = Flags.print_pcs;
|
Options.PrintNewCovPcs = Flags.print_pcs;
|
||||||
Options.PrintFinalStats = Flags.print_final_stats;
|
Options.PrintFinalStats = Flags.print_final_stats;
|
||||||
|
Options.PrintCoverage = Flags.print_coverage;
|
||||||
Options.TruncateUnits = Flags.truncate_units;
|
Options.TruncateUnits = Flags.truncate_units;
|
||||||
Options.PruneCorpus = Flags.prune_corpus;
|
Options.PruneCorpus = Flags.prune_corpus;
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,8 @@ FUZZER_FLAG_INT(drill, 0, "Experimental: fuzz using a single unit as the seed "
|
||||||
FUZZER_FLAG_INT(output_csv, 0, "Enable pulse output in CSV format.")
|
FUZZER_FLAG_INT(output_csv, 0, "Enable pulse output in CSV format.")
|
||||||
FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.")
|
FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.")
|
||||||
FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.")
|
FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.")
|
||||||
|
FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information at exit."
|
||||||
|
" Experimental, only with trace-pc-guard")
|
||||||
FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
|
FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
|
||||||
FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGSEGV.")
|
FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGSEGV.")
|
||||||
FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.")
|
FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.")
|
||||||
|
|
|
@ -108,6 +108,7 @@ void PrintHexArray(const uint8_t *Data, size_t Size,
|
||||||
void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
|
void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
|
||||||
void PrintASCII(const Unit &U, const char *PrintAfter = "");
|
void PrintASCII(const Unit &U, const char *PrintAfter = "");
|
||||||
void PrintASCII(const Word &W, const char *PrintAfter = "");
|
void PrintASCII(const Word &W, const char *PrintAfter = "");
|
||||||
|
void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC);
|
||||||
std::string Hash(const Unit &U);
|
std::string Hash(const Unit &U);
|
||||||
void SetTimer(int Seconds);
|
void SetTimer(int Seconds);
|
||||||
void SetSigSegvHandler();
|
void SetSigSegvHandler();
|
||||||
|
@ -243,6 +244,7 @@ struct FuzzingOptions {
|
||||||
bool OutputCSV = false;
|
bool OutputCSV = false;
|
||||||
bool PrintNewCovPcs = false;
|
bool PrintNewCovPcs = false;
|
||||||
bool PrintFinalStats = false;
|
bool PrintFinalStats = false;
|
||||||
|
bool PrintCoverage = false;
|
||||||
bool DetectLeaks = true;
|
bool DetectLeaks = true;
|
||||||
bool TruncateUnits = false;
|
bool TruncateUnits = false;
|
||||||
bool PruneCorpus = true;
|
bool PruneCorpus = true;
|
||||||
|
@ -385,6 +387,8 @@ class TracePC {
|
||||||
|
|
||||||
void PrintModuleInfo();
|
void PrintModuleInfo();
|
||||||
|
|
||||||
|
void PrintCoverage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool UseCounters = false;
|
bool UseCounters = false;
|
||||||
size_t TotalCoverage = 0;
|
size_t TotalCoverage = 0;
|
||||||
|
@ -408,6 +412,9 @@ private:
|
||||||
static const size_t kNumCounters = 1 << 14;
|
static const size_t kNumCounters = 1 << 14;
|
||||||
uint8_t Counters[kNumCounters];
|
uint8_t Counters[kNumCounters];
|
||||||
|
|
||||||
|
static const size_t kNumPCs = 1 << 20;
|
||||||
|
uintptr_t PCs[kNumPCs];
|
||||||
|
|
||||||
ValueBitMap CounterMap;
|
ValueBitMap CounterMap;
|
||||||
ValueBitMap TotalCoverageMap;
|
ValueBitMap TotalCoverageMap;
|
||||||
};
|
};
|
||||||
|
|
|
@ -329,6 +329,8 @@ void Fuzzer::PrintStats(const char *Where, const char *End) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::PrintFinalStats() {
|
void Fuzzer::PrintFinalStats() {
|
||||||
|
if (Options.PrintCoverage)
|
||||||
|
TPC.PrintCoverage();
|
||||||
if (!Options.PrintFinalStats) return;
|
if (!Options.PrintFinalStats) return;
|
||||||
size_t ExecPerSec = execPerSec();
|
size_t ExecPerSec = execPerSec();
|
||||||
Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
|
Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
|
||||||
|
@ -560,15 +562,8 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::PrintOneNewPC(uintptr_t PC) {
|
void Fuzzer::PrintOneNewPC(uintptr_t PC) {
|
||||||
if (EF->__sanitizer_symbolize_pc) {
|
PrintPC("\tNEW_PC: %p %F %L\n",
|
||||||
char PcDescr[1024];
|
"\tNEW_PC: %p\n", PC);
|
||||||
EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC),
|
|
||||||
"%p %F %L", PcDescr, sizeof(PcDescr));
|
|
||||||
PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case.
|
|
||||||
Printf("\tNEW_PC: %s\n", PcDescr);
|
|
||||||
} else {
|
|
||||||
Printf("\tNEW_PC: %p\n", PC);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::PrintNewPCs() {
|
void Fuzzer::PrintNewPCs() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace fuzzer {
|
||||||
|
|
||||||
TracePC TPC;
|
TracePC TPC;
|
||||||
const size_t TracePC::kNumCounters;
|
const size_t TracePC::kNumCounters;
|
||||||
|
const size_t TracePC::kNumPCs;
|
||||||
|
|
||||||
void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
|
void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
|
||||||
uintptr_t Idx = *Guard;
|
uintptr_t Idx = *Guard;
|
||||||
|
@ -25,6 +26,7 @@ void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
|
||||||
if (UseCounters) {
|
if (UseCounters) {
|
||||||
uint8_t Counter = Counters[Idx % kNumCounters];
|
uint8_t Counter = Counters[Idx % kNumCounters];
|
||||||
if (Counter == 0) {
|
if (Counter == 0) {
|
||||||
|
PCs[Idx] = PC;
|
||||||
if (TotalCoverageMap.AddValue(Idx)) {
|
if (TotalCoverageMap.AddValue(Idx)) {
|
||||||
TotalCoverage++;
|
TotalCoverage++;
|
||||||
AddNewPC(PC);
|
AddNewPC(PC);
|
||||||
|
@ -38,6 +40,7 @@ void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
|
||||||
*Guard = 0;
|
*Guard = 0;
|
||||||
TotalCoverage++;
|
TotalCoverage++;
|
||||||
AddNewPC(PC);
|
AddNewPC(PC);
|
||||||
|
PCs[Idx] = PC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +103,14 @@ void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
|
||||||
CounterMap.AddValue((Caller & kMask) | ((Callee & kMask) << kBits));
|
CounterMap.AddValue((Caller & kMask) | ((Callee & kMask) << kBits));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TracePC::PrintCoverage() {
|
||||||
|
Printf("COVERAGE:\n");
|
||||||
|
for (size_t i = 0; i < std::min(NumGuards, kNumPCs); i++) {
|
||||||
|
if (PCs[i])
|
||||||
|
PrintPC("COVERED: %p %F %L\n", "COVERED: %p\n", PCs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fuzzer
|
} // namespace fuzzer
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -294,4 +294,16 @@ size_t GetPeakRSSMb() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) {
|
||||||
|
if (EF->__sanitizer_symbolize_pc) {
|
||||||
|
char PcDescr[1024];
|
||||||
|
EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC),
|
||||||
|
SymbolizedFMT, PcDescr, sizeof(PcDescr));
|
||||||
|
PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case.
|
||||||
|
Printf("%s", PcDescr);
|
||||||
|
} else {
|
||||||
|
Printf(FallbackFMT, PC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fuzzer
|
} // namespace fuzzer
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
CHECK: COVERAGE:
|
||||||
|
CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13
|
||||||
|
CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14
|
||||||
|
CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:16
|
||||||
|
CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:18
|
||||||
|
CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:19
|
||||||
|
RUN: not LLVMFuzzer-NullDerefTest-TracePC -print_coverage=1 2>&1 | FileCheck %s
|
|
@ -7,6 +7,7 @@ set(TracePCTests
|
||||||
SimpleTest
|
SimpleTest
|
||||||
CounterTest
|
CounterTest
|
||||||
CallerCalleeTest
|
CallerCalleeTest
|
||||||
|
NullDerefTest
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(Test ${TracePCTests})
|
foreach(Test ${TracePCTests})
|
||||||
|
|
Loading…
Reference in New Issue