[libFuzzer] when -print_coverage=1 is given, print more stats (the number of seeds that hit every given function)

llvm-svn: 337501
This commit is contained in:
Kostya Serebryany 2018-07-19 22:00:48 +00:00
parent 1d181bc992
commit 44edc281d9
4 changed files with 23 additions and 16 deletions

View File

@ -184,7 +184,7 @@ void TracePC::UpdateObservedPCs() {
auto Observe = [&](const PCTableEntry &TE) {
if (TE.PCFlags & 1)
if (ObservedFuncs.insert(TE.PC).second && NumPrintNewFuncs)
if (++ObservedFuncs[TE.PC] == 1 && NumPrintNewFuncs)
CoveredFuncs.push_back(TE.PC);
ObservePC(TE.PC);
};
@ -209,7 +209,8 @@ void TracePC::UpdateObservedPCs() {
}
}
for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N; i++) {
for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N;
i++) {
Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size());
PrintPC("%p %F %L", "%p", CoveredFuncs[i] + 1);
Printf("\n");
@ -251,7 +252,7 @@ void TracePC::IterateCoveredFunctions(CallBack CB) {
NextFE++;
} while (NextFE < M.Stop && !(NextFE->PCFlags & 1));
if (ObservedFuncs.count(FE->PC))
CB(FE, NextFE);
CB(FE, NextFE, ObservedFuncs[FE->PC]);
}
}
}
@ -298,28 +299,30 @@ void TracePC::PrintCoverage() {
return;
}
Printf("COVERAGE:\n");
auto CoveredFunctionCallback = [&](const PCTableEntry *First, const PCTableEntry *Last) {
auto CoveredFunctionCallback = [&](const PCTableEntry *First,
const PCTableEntry *Last,
uintptr_t Counter) {
assert(First < Last);
auto VisualizePC = GetNextInstructionPc(First->PC);
std::string FileStr = DescribePC("%s", VisualizePC);
if (!IsInterestingCoverageFile(FileStr)) return;
if (!IsInterestingCoverageFile(FileStr))
return;
std::string FunctionStr = DescribePC("%F", VisualizePC);
if (FunctionStr.find("in ") == 0)
FunctionStr = FunctionStr.substr(3);
std::string LineStr = DescribePC("%l", VisualizePC);
size_t Line = std::stoul(LineStr);
size_t NumEdges = Last - First;
Vector<uintptr_t> UncoveredPCs;
for (auto TE = First; TE < Last; TE++)
if (!ObservedPCs.count(TE->PC))
UncoveredPCs.push_back(TE->PC);
Printf("COVERED_FUNC: ");
UncoveredPCs.empty()
? Printf("all")
: Printf("%zd/%zd", (Last - First) - UncoveredPCs.size(), Last - First);
Printf(" PCs covered %s %s:%zd\n", FunctionStr.c_str(), FileStr.c_str(),
Line);
for (auto PC: UncoveredPCs) {
Printf("COVERED_FUNC: hits: %zd", Counter);
Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges);
Printf(" %s %s:%zd\n", FunctionStr.c_str(), FileStr.c_str(), Line);
for (auto PC: UncoveredPCs)
Printf(" UNCOVERED_PC: %s\n",
DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str());
}
};
IterateCoveredFunctions(CoveredFunctionCallback);

View File

@ -17,6 +17,7 @@
#include "FuzzerValueBitMap.h"
#include <set>
#include <unordered_map>
namespace fuzzer {
@ -176,7 +177,7 @@ private:
uintptr_t *PCs() const;
Set<uintptr_t> ObservedPCs;
Set<uintptr_t> ObservedFuncs;
std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs; // PC => Counter.
template <class Callback>
void IterateInline8bitCounters(Callback CB) const;

View File

@ -12,10 +12,13 @@
const size_t N = 2048;
typedef const uint8_t *IN;
static volatile int one = 1;
extern "C" {
__attribute__((noinline)) void bad() {
fprintf(stderr, "BINGO\n");
abort();
if (one)
abort();
}
__attribute__((noinline)) void f0(IN in) {

View File

@ -5,7 +5,7 @@ RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC %ld_f
RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest
CHECK: COVERAGE:
CHECK: COVERED_FUNC: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13
CHECK: COVERED_FUNC: {{.*}}LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13
RUN: not %run %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s
RUN: %run %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO