llvm.org GIT mirror llvm / 13ca1cc
[llvm-cov] Optionally use a symbol demangler when preparing reports Add an option to specify a symbol demangler (as well as options to the demangler). This can be used to make reports more human-readable. This option is especially useful in -output-dir mode, since it isn't as easy to manually pipe reports into a demangler in this mode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275640 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 3 years ago
4 changed file(s) with 132 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
247247 PATH/functions.EXTENSION. When used in file view mode, a report for each file
248248 is written to PATH/REL_PATH_TO_FILE.EXTENSION.
249249
250 .. option:: -Xdemangler=|
251
252 Specify a symbol demangler. This can be used to make reports more
253 human-readable. This option can be specified multiple times to supply
254 arguments to the demangler (e.g `-Xdemangler c++filt -Xdemangler -n` for C++).
255 The demangler is expected to read a newline-separated list of symbols from
256 stdin and write a newline-separated list of the same length to stdout.
257
250258 .. option:: -line-coverage-gt=
251259
252260 Show code coverage only for functions with line coverage greater than the
0 // RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -filename-equivalence %S/showTemplateInstantiations.cpp | FileCheck %s
1
2 // CHECK: XZ4funcIbEiTX:
3 // CHECK: XZ4funcIiEiTX:
2525 #include "llvm/Support/CommandLine.h"
2626 #include "llvm/Support/FileSystem.h"
2727 #include "llvm/Support/Format.h"
28 #include "llvm/Support/MemoryBuffer.h"
2829 #include "llvm/Support/Path.h"
2930 #include "llvm/Support/Process.h"
31 #include "llvm/Support/Program.h"
3032 #include "llvm/Support/ThreadPool.h"
33 #include "llvm/Support/ToolOutputFile.h"
3134 #include
3235 #include
3336
8083 /// \brief Load the coverage mapping data. Return nullptr if an error occured.
8184 std::unique_ptr load();
8285
86 /// \brief If a demangler is available, demangle all symbol names.
87 void demangleSymbols(const CoverageMapping &Coverage);
88
89 /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym.
90 StringRef getSymbolForHumans(StringRef Sym) const;
91
8392 int run(Command Cmd, int argc, const char **argv);
8493
8594 typedef llvm::function_ref CommandLineParserType;
100109 std::string CoverageArch;
101110
102111 private:
112 /// A cache for demangled symbol names.
113 StringMap DemangledNames;
114
103115 /// File paths (absolute, or otherwise) to input source files.
104116 std::vector CollectedPaths;
105117
204216 return nullptr;
205217
206218 auto Expansions = FunctionCoverage.getExpansions();
207 auto View = SourceCoverageView::create(Function.Name, SourceBuffer.get(),
208 ViewOpts, std::move(FunctionCoverage));
219 auto View = SourceCoverageView::create(getSymbolForHumans(Function.Name),
220 SourceBuffer.get(), ViewOpts,
221 std::move(FunctionCoverage));
209222 attachExpansionSubViews(*View, Expansions, Coverage);
210223
211224 return View;
229242 for (const auto *Function : Coverage.getInstantiations(SourceFile)) {
230243 auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
231244 auto SubViewExpansions = SubViewCoverage.getExpansions();
232 auto SubView =
233 SourceCoverageView::create(Function->Name, SourceBuffer.get(), ViewOpts,
234 std::move(SubViewCoverage));
245 auto SubView = SourceCoverageView::create(
246 getSymbolForHumans(Function->Name), SourceBuffer.get(), ViewOpts,
247 std::move(SubViewCoverage));
235248 attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
236249
237250 if (SubView) {
288301 }
289302 }
290303
304 demangleSymbols(*Coverage);
305
291306 return Coverage;
307 }
308
309 void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {
310 if (!ViewOpts.hasDemangler())
311 return;
312
313 // Pass function names to the demangler in a temporary file.
314 int InputFD;
315 SmallString<256> InputPath;
316 std::error_code EC =
317 sys::fs::createTemporaryFile("demangle-in", "list", InputFD, InputPath);
318 if (EC) {
319 error(InputPath, EC.message());
320 return;
321 }
322 tool_output_file InputTOF{InputPath, InputFD};
323
324 unsigned NumSymbols = 0;
325 for (const auto &Function : Coverage.getCoveredFunctions()) {
326 InputTOF.os() << Function.Name << '\n';
327 ++NumSymbols;
328 }
329 InputTOF.os().flush();
330
331 // Use another temporary file to store the demangler's output.
332 int OutputFD;
333 SmallString<256> OutputPath;
334 EC = sys::fs::createTemporaryFile("demangle-out", "list", OutputFD,
335 OutputPath);
336 if (EC) {
337 error(OutputPath, EC.message());
338 return;
339 }
340 tool_output_file OutputTOF{OutputPath, OutputFD};
341
342 // Invoke the demangler.
343 std::vector ArgsV;
344 for (const std::string &Arg : ViewOpts.DemanglerOpts)
345 ArgsV.push_back(Arg.c_str());
346 ArgsV.push_back(nullptr);
347 StringRef InputPathRef{InputPath}, OutputPathRef{OutputPath}, StderrRef;
348 const StringRef *Redirects[] = {&InputPathRef, &OutputPathRef, &StderrRef};
349 std::string ErrMsg;
350 int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(),
351 /*env=*/nullptr, Redirects, /*secondsToWait=*/0,
352 /*memoryLimit=*/0, &ErrMsg);
353 if (RC) {
354 error(ErrMsg, ViewOpts.DemanglerOpts[0]);
355 return;
356 }
357
358 // Parse the demangler's output.
359 auto BufOrError = MemoryBuffer::getFile(OutputPath);
360 if (!BufOrError) {
361 error(OutputPath, BufOrError.getError().message());
362 return;
363 }
364
365 std::unique_ptr DemanglerBuf = std::move(*BufOrError);
366
367 SmallVector Symbols;
368 StringRef DemanglerData = DemanglerBuf->getBuffer();
369 DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols,
370 /*KeepEmpty=*/false);
371 if (Symbols.size() != NumSymbols) {
372 error("Demangler did not provide expected number of symbols");
373 return;
374 }
375
376 // Cache the demangled names.
377 unsigned I = 0;
378 for (const auto &Function : Coverage.getCoveredFunctions())
379 DemangledNames[Function.Name] = Symbols[I++];
380 }
381
382 StringRef CodeCoverageTool::getSymbolForHumans(StringRef Sym) const {
383 const auto DemangledName = DemangledNames.find(Sym);
384 if (DemangledName == DemangledNames.end())
385 return Sym;
386 return DemangledName->getValue();
292387 }
293388
294389 int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
364459 cl::opt UseColor(
365460 "use-color", cl::desc("Emit colored output (default=autodetect)"),
366461 cl::init(cl::BOU_UNSET));
462
463 cl::list DemanglerOpts(
464 "Xdemangler", cl::desc("|"));
367465
368466 auto commandLineParser = [&, this](int argc, const char **argv) -> int {
369467 cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
382480 error("Color output cannot be disabled when generating html.");
383481 ViewOpts.Colors = true;
384482 break;
483 }
484
485 // If a demangler is supplied, check if it exists and register it.
486 if (DemanglerOpts.size()) {
487 auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]);
488 if (!DemanglerPathOrErr) {
489 error("Could not find the demangler!",
490 DemanglerPathOrErr.getError().message());
491 return 1;
492 }
493 DemanglerOpts[0] = *DemanglerPathOrErr;
494 ViewOpts.DemanglerOpts.swap(DemanglerOpts);
385495 }
386496
387497 // Create the function filters
1010 #define LLVM_COV_COVERAGEVIEWOPTIONS_H
1111
1212 #include "RenderingSupport.h"
13 #include
1314
1415 namespace llvm {
1516
3132 bool ShowFullFilenames;
3233 OutputFormat Format;
3334 std::string ShowOutputDirectory;
35 std::vector DemanglerOpts;
3436
3537 /// \brief Change the output's stream color if the colors are enabled.
3638 ColoredRawOstream colored_ostream(raw_ostream &OS,
4042
4143 /// \brief Check if an output directory has been specified.
4244 bool hasOutputDirectory() const { return !ShowOutputDirectory.empty(); }
45
46 /// \brief Check if a demangler has been specified.
47 bool hasDemangler() const { return !DemanglerOpts.empty(); }
4348 };
4449 }
4550