void TracePC::PrintNewPCs() { if (!DoPrintNewPCs) return; assert(PrintedPCs); for (size_t i = 1; i < GetNumPCs(); i++) if (PCs()[i] && PrintedPCs->insert(PCs()[i]).second) PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PCs()[i]); }
void TracePC::DumpCoverage() { if (EF->__sanitizer_dump_coverage) { std::vector<uintptr_t> PCsCopy(GetNumPCs()); for (size_t i = 0; i < GetNumPCs(); i++) PCsCopy[i] = PCs()[i] ? GetPreviousInstructionPc(PCs()[i]) : 0; EF->__sanitizer_dump_coverage(PCsCopy.data(), PCsCopy.size()); } }
void TracePC::InitializePrintNewPCs() { if (!DoPrintNewPCs) return; assert(!PrintedPCs); PrintedPCs = new std::set<uintptr_t>; for (size_t i = 1; i < GetNumPCs(); i++) if (PCs()[i]) PrintedPCs->insert(PCs()[i]); }
size_t TracePC::GetTotalPCCoverage() { size_t Res = 0; for (size_t i = 1, N = GetNumPCs(); i < N; i++) if (PCs()[i]) Res++; return Res; }
size_t TracePC::GetTotalPCCoverage() { if (ObservedPCs.size()) return ObservedPCs.size(); size_t Res = 0; for (size_t i = 1, N = GetNumPCs(); i < N; i++) if (PCs()[i]) Res++; return Res; }
void TracePC::PrintCoverage() { if (!EF->__sanitizer_symbolize_pc || !EF->__sanitizer_get_module_and_offset_for_pc) { Printf("INFO: __sanitizer_symbolize_pc or " "__sanitizer_get_module_and_offset_for_pc is not available," " 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 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; } 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); } } 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()); } }