xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric //
9*bdd1243dSDimitry Andric // This program is a utility that displays the logical view for the debug
10*bdd1243dSDimitry Andric // information.
11*bdd1243dSDimitry Andric //
12*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
13*bdd1243dSDimitry Andric 
14*bdd1243dSDimitry Andric #include "Options.h"
15*bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
16*bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
17*bdd1243dSDimitry Andric #include "llvm/Support/COM.h"
18*bdd1243dSDimitry Andric #include "llvm/Support/CommandLine.h"
19*bdd1243dSDimitry Andric #include "llvm/Support/InitLLVM.h"
20*bdd1243dSDimitry Andric #include "llvm/Support/TargetSelect.h"
21*bdd1243dSDimitry Andric #include "llvm/Support/ToolOutputFile.h"
22*bdd1243dSDimitry Andric #include "llvm/Support/WithColor.h"
23*bdd1243dSDimitry Andric 
24*bdd1243dSDimitry Andric using namespace llvm;
25*bdd1243dSDimitry Andric using namespace logicalview;
26*bdd1243dSDimitry Andric using namespace cmdline;
27*bdd1243dSDimitry Andric 
28*bdd1243dSDimitry Andric /// Create formatted StringError object.
29*bdd1243dSDimitry Andric static StringRef ToolName = "llvm-debuginfo-analyzer";
30*bdd1243dSDimitry Andric template <typename... Ts>
error(std::error_code EC,char const * Fmt,const Ts &...Vals)31*bdd1243dSDimitry Andric static void error(std::error_code EC, char const *Fmt, const Ts &...Vals) {
32*bdd1243dSDimitry Andric   if (!EC)
33*bdd1243dSDimitry Andric     return;
34*bdd1243dSDimitry Andric   std::string Buffer;
35*bdd1243dSDimitry Andric   raw_string_ostream Stream(Buffer);
36*bdd1243dSDimitry Andric   Stream << format(Fmt, Vals...);
37*bdd1243dSDimitry Andric   WithColor::error(errs(), ToolName) << Stream.str() << "\n";
38*bdd1243dSDimitry Andric   exit(1);
39*bdd1243dSDimitry Andric }
40*bdd1243dSDimitry Andric 
error(Error EC)41*bdd1243dSDimitry Andric static void error(Error EC) {
42*bdd1243dSDimitry Andric   if (!EC)
43*bdd1243dSDimitry Andric     return;
44*bdd1243dSDimitry Andric   handleAllErrors(std::move(EC), [&](const ErrorInfoBase &EI) {
45*bdd1243dSDimitry Andric     errs() << "\n";
46*bdd1243dSDimitry Andric     WithColor::error(errs(), ToolName) << EI.message() << ".\n";
47*bdd1243dSDimitry Andric     exit(1);
48*bdd1243dSDimitry Andric   });
49*bdd1243dSDimitry Andric }
50*bdd1243dSDimitry Andric 
51*bdd1243dSDimitry Andric /// If the input path is a .dSYM bundle (as created by the dsymutil tool),
52*bdd1243dSDimitry Andric /// replace it with individual entries for each of the object files inside the
53*bdd1243dSDimitry Andric /// bundle otherwise return the input path.
expandBundle(const std::string & InputPath)54*bdd1243dSDimitry Andric static std::vector<std::string> expandBundle(const std::string &InputPath) {
55*bdd1243dSDimitry Andric   std::vector<std::string> BundlePaths;
56*bdd1243dSDimitry Andric   SmallString<256> BundlePath(InputPath);
57*bdd1243dSDimitry Andric   // Normalize input path. This is necessary to accept `bundle.dSYM/`.
58*bdd1243dSDimitry Andric   sys::path::remove_dots(BundlePath);
59*bdd1243dSDimitry Andric   // Manually open up the bundle to avoid introducing additional dependencies.
60*bdd1243dSDimitry Andric   if (sys::fs::is_directory(BundlePath) &&
61*bdd1243dSDimitry Andric       sys::path::extension(BundlePath) == ".dSYM") {
62*bdd1243dSDimitry Andric     std::error_code EC;
63*bdd1243dSDimitry Andric     sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
64*bdd1243dSDimitry Andric     for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
65*bdd1243dSDimitry Andric          Dir != DirEnd && !EC; Dir.increment(EC)) {
66*bdd1243dSDimitry Andric       const std::string &Path = Dir->path();
67*bdd1243dSDimitry Andric       sys::fs::file_status Status;
68*bdd1243dSDimitry Andric       EC = sys::fs::status(Path, Status);
69*bdd1243dSDimitry Andric       error(EC, "%s", Path.c_str());
70*bdd1243dSDimitry Andric       switch (Status.type()) {
71*bdd1243dSDimitry Andric       case sys::fs::file_type::regular_file:
72*bdd1243dSDimitry Andric       case sys::fs::file_type::symlink_file:
73*bdd1243dSDimitry Andric       case sys::fs::file_type::type_unknown:
74*bdd1243dSDimitry Andric         BundlePaths.push_back(Path);
75*bdd1243dSDimitry Andric         break;
76*bdd1243dSDimitry Andric       default: /*ignore*/;
77*bdd1243dSDimitry Andric       }
78*bdd1243dSDimitry Andric     }
79*bdd1243dSDimitry Andric   }
80*bdd1243dSDimitry Andric   if (BundlePaths.empty())
81*bdd1243dSDimitry Andric     BundlePaths.push_back(InputPath);
82*bdd1243dSDimitry Andric   return BundlePaths;
83*bdd1243dSDimitry Andric }
84*bdd1243dSDimitry Andric 
main(int argc,char ** argv)85*bdd1243dSDimitry Andric int main(int argc, char **argv) {
86*bdd1243dSDimitry Andric   InitLLVM X(argc, argv);
87*bdd1243dSDimitry Andric 
88*bdd1243dSDimitry Andric   // Initialize targets and assembly printers/parsers.
89*bdd1243dSDimitry Andric   llvm::InitializeAllTargetInfos();
90*bdd1243dSDimitry Andric   llvm::InitializeAllTargetMCs();
91*bdd1243dSDimitry Andric   InitializeAllDisassemblers();
92*bdd1243dSDimitry Andric 
93*bdd1243dSDimitry Andric   llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
94*bdd1243dSDimitry Andric 
95*bdd1243dSDimitry Andric   cl::extrahelp HelpResponse(
96*bdd1243dSDimitry Andric       "\nPass @FILE as argument to read options from FILE.\n");
97*bdd1243dSDimitry Andric 
98*bdd1243dSDimitry Andric   cl::HideUnrelatedOptions(
99*bdd1243dSDimitry Andric       {&AttributeCategory, &CompareCategory, &InternalCategory, &OutputCategory,
100*bdd1243dSDimitry Andric        &PrintCategory, &ReportCategory, &SelectCategory, &WarningCategory});
101*bdd1243dSDimitry Andric   cl::ParseCommandLineOptions(argc, argv,
102*bdd1243dSDimitry Andric                               "Printing a logical representation of low-level "
103*bdd1243dSDimitry Andric                               "debug information.\n");
104*bdd1243dSDimitry Andric   cl::PrintOptionValues();
105*bdd1243dSDimitry Andric 
106*bdd1243dSDimitry Andric   std::error_code EC;
107*bdd1243dSDimitry Andric   ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_None);
108*bdd1243dSDimitry Andric   error(EC, "Unable to open output file %s", OutputFilename.c_str());
109*bdd1243dSDimitry Andric   // Don't remove output file if we exit with an error.
110*bdd1243dSDimitry Andric   OutputFile.keep();
111*bdd1243dSDimitry Andric 
112*bdd1243dSDimitry Andric   // Defaults to a.out if no filenames specified.
113*bdd1243dSDimitry Andric   if (InputFilenames.empty())
114*bdd1243dSDimitry Andric     InputFilenames.push_back("a.out");
115*bdd1243dSDimitry Andric 
116*bdd1243dSDimitry Andric   // Expand any .dSYM bundles to the individual object files contained therein.
117*bdd1243dSDimitry Andric   std::vector<std::string> Objects;
118*bdd1243dSDimitry Andric   for (const std::string &Filename : InputFilenames) {
119*bdd1243dSDimitry Andric     std::vector<std::string> Objs = expandBundle(Filename);
120*bdd1243dSDimitry Andric     Objects.insert(Objects.end(), Objs.begin(), Objs.end());
121*bdd1243dSDimitry Andric   }
122*bdd1243dSDimitry Andric 
123*bdd1243dSDimitry Andric   propagateOptions();
124*bdd1243dSDimitry Andric   ScopedPrinter W(OutputFile.os());
125*bdd1243dSDimitry Andric   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
126*bdd1243dSDimitry Andric 
127*bdd1243dSDimitry Andric   // Print the command line.
128*bdd1243dSDimitry Andric   if (options().getInternalCmdline()) {
129*bdd1243dSDimitry Andric     raw_ostream &Stream = W.getOStream();
130*bdd1243dSDimitry Andric     Stream << "\nCommand line:\n";
131*bdd1243dSDimitry Andric     for (int Index = 0; Index < argc; ++Index)
132*bdd1243dSDimitry Andric       Stream << "  " << argv[Index] << "\n";
133*bdd1243dSDimitry Andric     Stream << "\n";
134*bdd1243dSDimitry Andric   }
135*bdd1243dSDimitry Andric 
136*bdd1243dSDimitry Andric   // Create readers and perform requested tasks on them.
137*bdd1243dSDimitry Andric   if (Error Err = ReaderHandler.process())
138*bdd1243dSDimitry Andric     error(std::move(Err));
139*bdd1243dSDimitry Andric 
140*bdd1243dSDimitry Andric   return EXIT_SUCCESS;
141*bdd1243dSDimitry Andric }
142