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