aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2017-09-21 01:11:30 +0000
committerVedant Kumar <vsk@apple.com>2017-09-21 01:11:30 +0000
commit3d39fc262434a48c12f5e9c06d7b144a0b19767d (patch)
tree9b8ed36d28da4b1a3e71accf1b9006c5b57851d8
parentec61af4bcc20ba5dccff7c354b761232febbcb13 (diff)
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313853 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMapping.h23
-rw-r--r--lib/ProfileData/Coverage/CoverageMapping.cpp5
-rw-r--r--test/tools/llvm-cov/cov-comdat.test5
-rw-r--r--tools/llvm-cov/CodeCoverage.cpp16
4 files changed, 43 insertions, 6 deletions
diff --git a/include/llvm/ProfileData/Coverage/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 13a9093bd84..22286f6d468 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -508,7 +508,8 @@ public:
class CoverageMapping {
StringSet<> FunctionNames;
std::vector<FunctionRecord> Functions;
- unsigned MismatchedFunctionCount = 0;
+ std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
+ std::vector<std::pair<std::string, uint64_t>> 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<std::pair<std::string, uint64_t>> 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<std::pair<std::string, uint64_t>> getCounterMismatches() const {
+ return FuncCounterMismatches;
+ }
/// Returns a lexicographically sorted, unique list of files that are
/// covered.
diff --git a/lib/ProfileData/Coverage/CoverageMapping.cpp b/lib/ProfileData/Coverage/CoverageMapping.cpp
index 4c257cf38e5..52f9447aa3e 100644
--- a/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/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<InstrProfError>(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/test/tools/llvm-cov/cov-comdat.test b/test/tools/llvm-cov/cov-comdat.test
index 1545f9921e9..9d227163699 100644
--- a/test/tools/llvm-cov/cov-comdat.test
+++ b/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/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp
index 09ee82a491e..981c93a2d95 100644
--- a/tools/llvm-cov/CodeCoverage.cpp
+++ b/tools/llvm-cov/CodeCoverage.cpp
@@ -350,9 +350,23 @@ std::unique_ptr<CoverageMapping> 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())