Index: test/tools/sancov/stats.test =================================================================== --- /dev/null +++ test/tools/sancov/stats.test @@ -0,0 +1,9 @@ +REQUIRES: x86_64-linux +RUN: sancov -print-coverage-stats %p/Inputs/test-linux_x86_64 %p/Inputs/test-linux_x86_64.0.sancov | FileCheck %s + +CHECK: all-points: 16 +CHECK: cov-points: 7 +CHECK: all-fns: 3 +CHECK: cov-fns: 2 + + Index: tools/sancov/sancov.cc =================================================================== --- tools/sancov/sancov.cc +++ tools/sancov/sancov.cc @@ -63,7 +63,8 @@ PrintCovPointsAction, CoveredFunctionsAction, NotCoveredFunctionsAction, - HtmlReportAction + HtmlReportAction, + StatsAction }; cl::opt Action( @@ -77,6 +78,8 @@ "Print all not covered funcions."), clEnumValN(HtmlReportAction, "html-report", "Print HTML coverage report."), + clEnumValN(StatsAction, "print-coverage-stats", + "Print coverage statistics."), clEnumValEnd)); static cl::list @@ -516,6 +519,23 @@ return Header->Magic == BinCoverageMagic; } +struct CoverageStats { + CoverageStats() : AllPoints(0), CovPoints(0), AllFns(0), CovFns(0) {} + + size_t AllPoints; + size_t CovPoints; + size_t AllFns; + size_t CovFns; +}; + +static raw_ostream &operator<<(raw_ostream &OS, const CoverageStats &Stats) { + OS << "all-points: " << Stats.AllPoints << "\n"; + OS << "cov-points: " << Stats.CovPoints << "\n"; + OS << "all-fns: " << Stats.AllFns << "\n"; + OS << "cov-fns: " << Stats.CovFns << "\n"; + return OS; +} + class CoverageData { public: // Read single file coverage data. @@ -615,9 +635,8 @@ MIXED = 3 }; - SourceCoverageData(std::string ObjectFile, const std::set &Addrs) { - std::set AllCovPoints = getCoveragePoints(ObjectFile); - + SourceCoverageData(std::string ObjectFile, const std::set &Addrs) + : AllCovPoints(getCoveragePoints(ObjectFile)) { if (!std::includes(AllCovPoints.begin(), AllCovPoints.end(), Addrs.begin(), Addrs.end())) { Fail("Coverage points in binary and .sancov file do not match."); @@ -776,7 +795,16 @@ return Files; } + void collectStats(CoverageStats *Stats) const { + Stats->AllPoints += AllCovPoints.size(); + Stats->AllFns += computeAllFunctions().size(); + Stats->CovFns += computeCoveredFunctions().size(); + } + private: + const std::set AllCovPoints; + const std::set CovPoints; + std::vector AllAddrInfo; std::vector CovAddrInfo; }; @@ -954,6 +982,13 @@ } } + void collectStats(CoverageStats *Stats) const { + Stats->CovPoints += Addrs->size(); + + SourceCoverageData SCovData(ObjectFile, *Addrs); + SCovData.collectStats(Stats); + } + private: CoverageDataWithObjectFile(std::string ObjectFile, std::unique_ptr Coverage) @@ -1048,6 +1083,14 @@ } } + void printStats(raw_ostream &OS) const { + CoverageStats Stats; + for (const auto &Cov : Coverage) { + Cov->collectStats(&Stats); + } + OS << Stats; + } + void printReport(raw_ostream &OS) const { auto Title = (llvm::sys::path::filename(MainObjFile) + " Coverage Report").str(); @@ -1172,6 +1215,10 @@ CovDataSet.get()->printReport(outs()); return 0; } + case StatsAction: { + CovDataSet.get()->printStats(outs()); + return 0; + } case PrintAction: case PrintCovPointsAction: llvm_unreachable("unsupported action");