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