[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