[llvm] r310324 - [libFuzzer] simplify the implementation of -print_coverage=1
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 7 17:12:09 PDT 2017
Author: kcc
Date: Mon Aug 7 17:12:09 2017
New Revision: 310324
URL: http://llvm.org/viewvc/llvm-project?rev=310324&view=rev
Log:
[libFuzzer] simplify the implementation of -print_coverage=1
Modified:
llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
llvm/trunk/lib/Fuzzer/test/coverage.test
Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp?rev=310324&r1=310323&r2=310324&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp Mon Aug 7 17:12:09 2017
@@ -174,6 +174,28 @@ void TracePC::UpdateObservedPCs() {
}
}
+inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
+ // TODO: this implementation is x86 only.
+ // see sanitizer_common GetPreviousInstructionPc for full implementation.
+ return PC - 1;
+}
+
+inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) {
+ // TODO: this implementation is x86 only.
+ // see sanitizer_common GetPreviousInstructionPc for full implementation.
+ return PC + 1;
+}
+
+static std::string GetModuleName(uintptr_t PC) {
+ char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++?
+ void *OffsetRaw = nullptr;
+ if (!EF->__sanitizer_get_module_and_offset_for_pc(
+ reinterpret_cast<void *>(PC), ModulePathRaw,
+ sizeof(ModulePathRaw), &OffsetRaw))
+ return "";
+ return ModulePathRaw;
+}
+
void TracePC::PrintCoverage() {
if (!EF->__sanitizer_symbolize_pc ||
!EF->__sanitizer_get_module_and_offset_for_pc) {
@@ -182,107 +204,54 @@ void TracePC::PrintCoverage() {
" not printing coverage\n");
return;
}
- std::map<std::string, std::vector<uintptr_t>> CoveredPCsPerModule;
- std::map<std::string, uintptr_t> ModuleOffsets;
- std::set<std::string> CoveredDirs, CoveredFiles, CoveredFunctions,
- CoveredLines;
Printf("COVERAGE:\n");
- for (size_t i = 1; i < GetNumPCs(); i++) {
- uintptr_t PC = PCs()[i];
- if (!PC) continue;
- std::string FileStr = DescribePC("%s", PC);
- if (!IsInterestingCoverageFile(FileStr)) continue;
- std::string FixedPCStr = DescribePC("%p", PC);
- std::string FunctionStr = DescribePC("%F", PC);
- std::string LineStr = DescribePC("%l", PC);
- char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++?
- void *OffsetRaw = nullptr;
- if (!EF->__sanitizer_get_module_and_offset_for_pc(
- reinterpret_cast<void *>(PC), ModulePathRaw,
- sizeof(ModulePathRaw), &OffsetRaw))
- continue;
- std::string Module = ModulePathRaw;
- uintptr_t FixedPC = std::stoull(FixedPCStr, 0, 16);
- uintptr_t PcOffset = reinterpret_cast<uintptr_t>(OffsetRaw);
- ModuleOffsets[Module] = FixedPC - PcOffset;
- CoveredPCsPerModule[Module].push_back(PcOffset);
- CoveredFunctions.insert(FunctionStr);
- CoveredFiles.insert(FileStr);
- CoveredDirs.insert(DirName(FileStr));
- if (!CoveredLines.insert(FileStr + ":" + LineStr).second)
- continue;
- Printf("COVERED: %s %s:%s\n", FunctionStr.c_str(),
- FileStr.c_str(), LineStr.c_str());
- }
+ std::string LastFunctionName = "";
+ std::string LastFileStr = "";
+ std::set<size_t> UncoveredLines;
+ std::set<size_t> CoveredLines;
- std::string CoveredDirsStr;
- for (auto &Dir : CoveredDirs) {
- if (!CoveredDirsStr.empty())
- CoveredDirsStr += ",";
- CoveredDirsStr += Dir;
- }
- Printf("COVERED_DIRS: %s\n", CoveredDirsStr.c_str());
-
- for (auto &M : CoveredPCsPerModule) {
- std::set<std::string> UncoveredFiles, UncoveredFunctions;
- std::map<std::string, std::set<int> > UncoveredLines; // Func+File => lines
- auto &ModuleName = M.first;
- auto &CoveredOffsets = M.second;
- uintptr_t ModuleOffset = ModuleOffsets[ModuleName];
- std::sort(CoveredOffsets.begin(), CoveredOffsets.end());
- Printf("MODULE_WITH_COVERAGE: %s\n", ModuleName.c_str());
- // sancov does not yet fully support DSOs.
- // std::string Cmd = "sancov -print-coverage-pcs " + ModuleName;
- std::string Cmd = DisassembleCmd(ModuleName) + " | " +
- SearchRegexCmd("call.*__sanitizer_cov_trace_pc_guard");
- std::string SanCovOutput;
- if (!ExecuteCommandAndReadOutput(Cmd, &SanCovOutput)) {
- Printf("INFO: Command failed: %s\n", Cmd.c_str());
- continue;
- }
- std::istringstream ISS(SanCovOutput);
- std::string S;
- while (std::getline(ISS, S, '\n')) {
- size_t PcOffsetEnd = S.find(':');
- if (PcOffsetEnd == std::string::npos)
- continue;
- S.resize(PcOffsetEnd);
- uintptr_t PcOffset = std::stoull(S, 0, 16);
- if (!std::binary_search(CoveredOffsets.begin(), CoveredOffsets.end(),
- PcOffset)) {
- uintptr_t PC = ModuleOffset + PcOffset;
- auto FileStr = DescribePC("%s", PC);
- if (!IsInterestingCoverageFile(FileStr)) continue;
- if (CoveredFiles.count(FileStr) == 0) {
- UncoveredFiles.insert(FileStr);
- continue;
- }
- auto FunctionStr = DescribePC("%F", PC);
- if (CoveredFunctions.count(FunctionStr) == 0) {
- UncoveredFunctions.insert(FunctionStr);
- continue;
+ auto FunctionEndCallback = [&](const std::string &CurrentFunc,
+ const std::string &CurrentFile) {
+ if (LastFunctionName != CurrentFunc) {
+ if (CoveredLines.empty() && !UncoveredLines.empty()) {
+ Printf("UNCOVERED_FUNC: %s\n", LastFunctionName.c_str());
+ } else {
+ for (auto Line : UncoveredLines) {
+ if (!CoveredLines.count(Line))
+ Printf("UNCOVERED_LINE: %s %s:%zd\n", LastFunctionName.c_str(),
+ LastFileStr.c_str(), Line);
}
- std::string LineStr = DescribePC("%l", PC);
- uintptr_t Line = std::stoi(LineStr);
- std::string FileLineStr = FileStr + ":" + LineStr;
- if (CoveredLines.count(FileLineStr) == 0)
- UncoveredLines[FunctionStr + " " + FileStr].insert(Line);
}
+
+ UncoveredLines.clear();
+ CoveredLines.clear();
+ LastFunctionName = CurrentFunc;
+ LastFileStr = CurrentFile;
}
- for (auto &FileLine: UncoveredLines)
- for (int Line : FileLine.second)
- Printf("UNCOVERED_LINE: %s:%d\n", FileLine.first.c_str(), Line);
- for (auto &Func : UncoveredFunctions)
- Printf("UNCOVERED_FUNC: %s\n", Func.c_str());
- for (auto &File : UncoveredFiles)
- Printf("UNCOVERED_FILE: %s\n", File.c_str());
- }
-}
+ };
-inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
- // TODO: this implementation is x86 only.
- // see sanitizer_common GetPreviousInstructionPc for full implementation.
- return PC - 1;
+ for (size_t i = 0; i < NumPCTables; i++) {
+ auto &M = ModulePCTable[i];
+ assert(M.Start < M.Stop);
+ auto ModuleName = GetModuleName(*M.Start);
+ for (auto Ptr = M.Start; Ptr < M.Stop; Ptr++) {
+ auto PC = *Ptr;
+ auto VisualizePC = GetNextInstructionPc(PC);
+ bool IsObserved = ObservedPCs->count(PC);
+ std::string FileStr = DescribePC("%s", VisualizePC);
+ if (!IsInterestingCoverageFile(FileStr)) continue;
+ std::string FunctionStr = DescribePC("%F", VisualizePC);
+ FunctionEndCallback(FunctionStr, FileStr);
+ std::string LineStr = DescribePC("%l", VisualizePC);
+ size_t Line = std::stoul(LineStr);
+ if (IsObserved && CoveredLines.insert(Line).second)
+ Printf("COVERED: %s %s:%zd\n", FunctionStr.c_str(), FileStr.c_str(),
+ Line);
+ else
+ UncoveredLines.insert(Line);
+ }
+ }
+ FunctionEndCallback("", "");
}
void TracePC::DumpCoverage() {
Modified: llvm/trunk/lib/Fuzzer/test/coverage.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/coverage.test?rev=310324&r1=310323&r2=310324&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/coverage.test (original)
+++ llvm/trunk/lib/Fuzzer/test/coverage.test Mon Aug 7 17:12:09 2017
@@ -1,16 +1,14 @@
XFAIL: darwin
-RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
-RUN: %cpp_compiler %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so
-RUN: %cpp_compiler %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so
-RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/NullDerefTest.cpp -o %t-NullDerefTest
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest
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:19
-CHECK: COVERED_DIRS: {{.*}}lib{{[/\\]}}Fuzzer{{[/\\]}}test
RUN: not %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s
RUN: %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
@@ -23,4 +21,3 @@ DSO-DAG: UNCOVERED_LINE:{{.*}}DSO2{{.*}}
DSO-DAG: UNCOVERED_FUNC: in Uncovered1
DSO-DAG: UNCOVERED_FUNC: in Uncovered2
DSO-DAG: UNCOVERED_LINE: in LLVMFuzzerTestOneInput
-DSO-DAG: UNCOVERED_FILE:{{.*}}DSOTestExtra.cpp
More information about the llvm-commits
mailing list