Index: test/tools/sancov/print_cov_points.test =================================================================== --- /dev/null +++ test/tools/sancov/print_cov_points.test @@ -0,0 +1,20 @@ +REQUIRES: x86_64-linux +RUN: sancov -print-coverage-points %p/Inputs/test-linux_x86_64 | FileCheck %s + +CHECK: 0x4cced1 +CHECK: 0x4ccf01 +CHECK: 0x4dbe2b +CHECK: 0x4dbf72 +CHECK: 0x4dbfc2 +CHECK: 0x4dbfec +CHECK: 0x4dc033 +CHECK: 0x4dc06a +CHECK: 0x4dc09d +CHECK: 0x4dc0d0 +CHECK: 0x4dc17f +CHECK: 0x4dc1c6 +CHECK: 0x4dc20d +CHECK: 0x4dc237 +CHECK: 0x4dc265 +CHECK: 0x4dc34c + Index: tools/sancov/sancov.cc =================================================================== --- tools/sancov/sancov.cc +++ tools/sancov/sancov.cc @@ -59,6 +59,7 @@ enum ActionType { PrintAction, + PrintCovPointsAction, CoveredFunctionsAction, NotCoveredFunctionsAction, HtmlReportAction @@ -67,6 +68,8 @@ cl::opt Action( cl::desc("Action (required)"), cl::Required, cl::values(clEnumValN(PrintAction, "print", "Print coverage addresses"), + clEnumValN(PrintCovPointsAction, "print-coverage-points", + "Print coverage instrumentation points addresses."), clEnumValN(CoveredFunctionsAction, "covered-functions", "Print all covered funcions."), clEnumValN(NotCoveredFunctionsAction, "not-covered-functions", @@ -449,6 +452,14 @@ return Result; } +static void printCovPoints(std::string ObjFile, raw_ostream &OS) { + for (uint64_t Addr : getCoveragePoints(ObjFile)) { + OS << "0x"; + OS.write_hex(Addr); + OS << "\n"; + } +} + static std::string escapeHtml(const std::string &S) { std::string Result; Result.reserve(S.size()); @@ -922,8 +933,9 @@ static ErrorOr> readCmdArguments(std::vector FileNames) { // Short name => file name. - std::map ObjFiles; + std::map ObjFilesMap; std::string FirstObjFile; + std::set ObjFiles; std::set CovFiles; // Partition input values into coverage/object files. @@ -938,7 +950,8 @@ Fail("Duplicate binary file with a short name: " + ShortFileName); } - ObjFiles[ShortFileName] = FileName; + ObjFilesMap[ShortFileName] = FileName; + ObjFiles.insert(FileName); if (FirstObjFile.empty()) FirstObjFile = FileName; } @@ -957,8 +970,8 @@ FileName); } - auto Iter = ObjFiles.find(Components[1]); - if (Iter == ObjFiles.end()) { + auto Iter = ObjFilesMap.find(Components[1]); + if (Iter == ObjFilesMap.end()) { Fail("Object file for coverage not found: " + FileName); } return Iter->second; @@ -986,7 +999,7 @@ } return std::unique_ptr( - new CoverageDataSet(FirstObjFile, &MergedCoverage, CovFiles)); + new CoverageDataSet(FirstObjFile, &MergedCoverage, ObjFiles, CovFiles)); } void printCoveredFunctions(raw_ostream &OS) const { @@ -1062,13 +1075,16 @@ explicit CoverageDataSet( const std::string &MainObjFile, std::vector> *Data, + const std::set &ObjectFiles, const std::set &CoverageFiles) - : MainObjFile(MainObjFile), CoverageFiles(CoverageFiles) { + : MainObjFile(MainObjFile), ObjectFiles(ObjectFiles), + CoverageFiles(CoverageFiles) { Data->swap(this->Coverage); } const std::string MainObjFile; std::vector> Coverage; + const std::set ObjectFiles; const std::set CoverageFiles; }; @@ -1092,6 +1108,12 @@ FailIfError(CovData); CovData.get()->printAddrs(outs()); return 0; + } else if (Action == PrintCovPointsAction) { + // -print-coverage-points doesn't need coverage files. + for (std::string ObjFile : ClInputFiles) { + printCovPoints(ObjFile, outs()); + } + return 0; } auto CovDataSet = CoverageDataSet::readCmdArguments(ClInputFiles); @@ -1115,6 +1137,7 @@ return 0; } case PrintAction: + case PrintCovPointsAction: llvm_unreachable("unsupported action"); } }