From 18dd9e88ed10c380e8d9cc999854c6365f3908c1 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Thu, 21 Sep 2017 01:11:30 +0000 Subject: [PATCH] [llvm-cov] Improve error messaging for function mismatches Passing "-dump" to llvm-cov will now print more detailed information about function hash and counter mismatches. This should make it easier to debug *.profdata files which contain incorrect records, and to debug other scenarios where coverage goes missing due to mismatch issues. llvm-svn: 313853 --- .../ProfileData/Coverage/CoverageMapping.h | 23 +++++++++++++++++-- .../ProfileData/Coverage/CoverageMapping.cpp | 5 ++-- llvm/test/tools/llvm-cov/cov-comdat.test | 5 +++- llvm/tools/llvm-cov/CodeCoverage.cpp | 16 ++++++++++++- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 13a9093bd84f..22286f6d4688 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -508,7 +508,8 @@ public: class CoverageMapping { StringSet<> FunctionNames; std::vector Functions; - unsigned MismatchedFunctionCount = 0; + std::vector> FuncHashMismatches; + std::vector> FuncCounterMismatches; CoverageMapping() = default; @@ -535,7 +536,25 @@ public: /// /// This is a count of functions whose profile is out of date or otherwise /// can't be associated with any coverage information. - unsigned getMismatchedCount() { return MismatchedFunctionCount; } + unsigned getMismatchedCount() const { + return FuncHashMismatches.size() + FuncCounterMismatches.size(); + } + + /// A hash mismatch occurs when a profile record for a symbol does not have + /// the same hash as a coverage mapping record for the same symbol. This + /// returns a list of hash mismatches, where each mismatch is a pair of the + /// symbol name and its coverage mapping hash. + ArrayRef> getHashMismatches() const { + return FuncHashMismatches; + } + + /// A counter mismatch occurs when there is an error when evaluating the + /// counter expressions in a coverage mapping record. This returns a list of + /// counter mismatches, where each mismatch is a pair of the symbol name and + /// the number of valid evaluated counter expressions. + ArrayRef> getCounterMismatches() const { + return FuncCounterMismatches; + } /// Returns a lexicographically sorted, unique list of files that are /// covered. diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 4c257cf38e59..52f9447aa3e7 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -217,7 +217,7 @@ Error CoverageMapping::loadFunctionRecord( Record.FunctionHash, Counts)) { instrprof_error IPE = InstrProfError::take(std::move(E)); if (IPE == instrprof_error::hash_mismatch) { - MismatchedFunctionCount++; + FuncHashMismatches.emplace_back(Record.FunctionName, Record.FunctionHash); return Error::success(); } else if (IPE != instrprof_error::unknown_function) return make_error(IPE); @@ -237,7 +237,8 @@ Error CoverageMapping::loadFunctionRecord( Function.pushRegion(Region, *ExecutionCount); } if (Function.CountedRegions.size() != Record.MappingRegions.size()) { - MismatchedFunctionCount++; + FuncCounterMismatches.emplace_back(Record.FunctionName, + Function.CountedRegions.size()); return Error::success(); } diff --git a/llvm/test/tools/llvm-cov/cov-comdat.test b/llvm/test/tools/llvm-cov/cov-comdat.test index 1545f9921e99..9d2271636994 100644 --- a/llvm/test/tools/llvm-cov/cov-comdat.test +++ b/llvm/test/tools/llvm-cov/cov-comdat.test @@ -7,6 +7,9 @@ REQUIRES: shell # of the same template function are properly merged in show # output. -// RUN: llvm-cov show %S/Inputs/binary-formats.v1.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S/Inputs %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h +// RUN: llvm-cov show %S/Inputs/binary-formats.v1.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S/Inputs %S/Inputs/instrprof-comdat.h -dump 2> %t.err | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h +// RUN: FileCheck --check-prefix=ERROR -input-file %t.err %s +// ERROR: hash-mismatch: No profile record found for 'main' with hash = 0xA + // RUN: llvm-cov show %S/Inputs/binary-formats.v2.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/root/llvm/test/tools,%S/.. %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h // RUN: llvm-cov show %S/Inputs/binary-formats.v2.linux32l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/root/llvm/R/../test/tools,%S/.. %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 09ee82a491e9..981c93a2d95b 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -350,9 +350,23 @@ std::unique_ptr CodeCoverageTool::load() { } auto Coverage = std::move(CoverageOrErr.get()); unsigned Mismatched = Coverage->getMismatchedCount(); - if (Mismatched) + if (Mismatched) { warning(utostr(Mismatched) + " functions have mismatched data"); + if (ViewOpts.Debug) { + for (const auto &HashMismatch : Coverage->getHashMismatches()) + errs() << "hash-mismatch: " + << "No profile record found for '" << HashMismatch.first << "'" + << " with hash = 0x" << utohexstr(HashMismatch.second) << "\n"; + + for (const auto &CounterMismatch : Coverage->getCounterMismatches()) + errs() << "counter-mismatch: " + << "Coverage mapping for " << CounterMismatch.first + << " only has " << CounterMismatch.second + << " valid counter expressions\n"; + } + } + remapPathNames(*Coverage); if (!SourceFiles.empty())