/// \brief Render the CoverageMapping object. void renderRoot() { // Start Root of JSON object. emitDictStart(); emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR); emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR); emitDictKey("data"); // Start List of Exports. emitArrayStart(); // Start Export. emitDictStart(); emitDictElement("object", getObjectFilename()); emitDictKey("files"); FileCoverageSummary Totals = FileCoverageSummary("Totals"); std::vector<std::string> SourceFiles; for (StringRef SF : Coverage.getUniqueSourceFiles()) SourceFiles.emplace_back(SF); auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals, SourceFiles); renderFiles(SourceFiles, FileReports); emitDictKey("functions"); renderFunctions(Coverage.getCoveredFunctions()); emitDictKey("totals"); renderSummary(Totals); // End Export. emitDictEnd(); // End List of Exports. emitArrayEnd(); // End Root of JSON Object. emitDictEnd(); assert((State.top() == JsonState::None) && "All Elements In JSON were Closed"); }
void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) { if (!ViewOpts.hasDemangler()) return; // Pass function names to the demangler in a temporary file. int InputFD; SmallString<256> InputPath; std::error_code EC = sys::fs::createTemporaryFile("demangle-in", "list", InputFD, InputPath); if (EC) { error(InputPath, EC.message()); return; } tool_output_file InputTOF{InputPath, InputFD}; unsigned NumSymbols = 0; for (const auto &Function : Coverage.getCoveredFunctions()) { InputTOF.os() << Function.Name << '\n'; ++NumSymbols; } InputTOF.os().close(); // Use another temporary file to store the demangler's output. int OutputFD; SmallString<256> OutputPath; EC = sys::fs::createTemporaryFile("demangle-out", "list", OutputFD, OutputPath); if (EC) { error(OutputPath, EC.message()); return; } tool_output_file OutputTOF{OutputPath, OutputFD}; OutputTOF.os().close(); // Invoke the demangler. std::vector<const char *> ArgsV; for (const std::string &Arg : ViewOpts.DemanglerOpts) ArgsV.push_back(Arg.c_str()); ArgsV.push_back(nullptr); StringRef InputPathRef = InputPath.str(); StringRef OutputPathRef = OutputPath.str(); StringRef StderrRef; const StringRef *Redirects[] = {&InputPathRef, &OutputPathRef, &StderrRef}; std::string ErrMsg; int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(), /*env=*/nullptr, Redirects, /*secondsToWait=*/0, /*memoryLimit=*/0, &ErrMsg); if (RC) { error(ErrMsg, ViewOpts.DemanglerOpts[0]); return; } // Parse the demangler's output. auto BufOrError = MemoryBuffer::getFile(OutputPath); if (!BufOrError) { error(OutputPath, BufOrError.getError().message()); return; } std::unique_ptr<MemoryBuffer> DemanglerBuf = std::move(*BufOrError); SmallVector<StringRef, 8> Symbols; StringRef DemanglerData = DemanglerBuf->getBuffer(); DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols, /*KeepEmpty=*/false); if (Symbols.size() != NumSymbols) { error("Demangler did not provide expected number of symbols"); return; } // Cache the demangled names. unsigned I = 0; for (const auto &Function : Coverage.getCoveredFunctions()) DemangledNames[Function.Name] = Symbols[I++]; }