blob: 823eb8e81334f5831319d77811d0e8b1b715a451 [file] [log] [blame]
Eric Christopher3680f882012-10-16 23:46:21 +00001//===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm ----------===//
Benjamin Krameraa2f78f2011-09-13 19:42:23 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This program is a utility that works like "dwarfdump".
11//
12//===----------------------------------------------------------------------===//
13
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000014#include "llvm/ADT/STLExtras.h"
Chandler Carruth4d88a1c2012-12-04 10:44:52 +000015#include "llvm/ADT/Triple.h"
Zachary Turner6489d7b2015-04-23 17:37:47 +000016#include "llvm/DebugInfo/DIContext.h"
17#include "llvm/DebugInfo/DWARF/DWARFContext.h"
Adrian Prantl5fd3d492017-09-14 17:01:53 +000018#include "llvm/Object/Archive.h"
Frederic Riss4c5d3572015-08-03 00:10:31 +000019#include "llvm/Object/MachOUniversal.h"
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000020#include "llvm/Object/ObjectFile.h"
Eric Christopher7c678de2012-11-07 23:22:07 +000021#include "llvm/Object/RelocVisitor.h"
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000022#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/Debug.h"
24#include "llvm/Support/Format.h"
25#include "llvm/Support/ManagedStatic.h"
26#include "llvm/Support/MemoryBuffer.h"
Adrian Prantl8e7d3b92015-12-23 21:51:13 +000027#include "llvm/Support/Path.h"
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000028#include "llvm/Support/PrettyStackTrace.h"
29#include "llvm/Support/Signals.h"
Reid Klecknera0587362017-08-29 21:41:21 +000030#include "llvm/Support/TargetSelect.h"
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000031#include "llvm/Support/raw_ostream.h"
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000032#include <algorithm>
33#include <cstring>
Eric Christopher7c678de2012-11-07 23:22:07 +000034#include <string>
Rafael Espindolaa6e9c3e2014-06-12 17:38:55 +000035#include <system_error>
Eric Christopher7c678de2012-11-07 23:22:07 +000036
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000037using namespace llvm;
38using namespace object;
39
Adrian Prantl7c5b45d2017-09-12 22:32:53 +000040namespace {
Adrian Prantlb5abcc52017-09-15 22:47:16 +000041using namespace llvm::cl;
Benjamin Krameraa2f78f2011-09-13 19:42:23 +000042
Adrian Prantl7c5b45d2017-09-12 22:32:53 +000043OptionCategory DwarfDumpCategory("Specific Options");
44static opt<bool> Help("h", desc("Alias for -help"), Hidden,
45 cat(DwarfDumpCategory));
46static list<std::string>
47 InputFilenames(Positional, desc("<input object files or .dSYM bundles>"),
48 ZeroOrMore, cat(DwarfDumpCategory));
49
Adrian Prantlb5abcc52017-09-15 22:47:16 +000050cl::OptionCategory
51 SectionCategory("Section-specific Dump Options",
52 "These control which sections are dumped.");
Adrian Prantl7c5b45d2017-09-12 22:32:53 +000053static opt<bool> DumpAll("all", desc("Dump all debug info sections"),
54 cat(SectionCategory));
55static alias DumpAllAlias("a", desc("Alias for -all"), aliasopt(DumpAll));
Adrian Prantl7bc1b282017-09-11 22:59:45 +000056
Adrian Prantl3ae35eb2017-09-13 22:09:01 +000057static unsigned DumpType = DIDT_Null;
Adrian Prantl7bc1b282017-09-11 22:59:45 +000058#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
Adrian Prantlb5abcc52017-09-15 22:47:16 +000059 static opt<bool> Dump##ENUM_NAME(CMDLINE_NAME, \
60 desc("Dump the " ELF_NAME " section"), \
61 cat(SectionCategory));
Adrian Prantl7bc1b282017-09-11 22:59:45 +000062#include "llvm/BinaryFormat/Dwarf.def"
63#undef HANDLE_DWARF_SECTION
Adrian Prantl3dcd1222017-09-13 18:22:59 +000064static opt<bool> DumpUUID("uuid", desc("Show the UUID for each architecture"),
65 cat(DwarfDumpCategory));
66static alias DumpUUIDAlias("u", desc("Alias for -uuid"), aliasopt(DumpUUID));
Eli Bendersky7a94daa2013-01-25 20:26:43 +000067
Adrian Prantl7c5b45d2017-09-12 22:32:53 +000068static opt<bool>
David Blaikie50cc27e2016-10-18 21:09:48 +000069 SummarizeTypes("summarize-types",
Adrian Prantl7c5b45d2017-09-12 22:32:53 +000070 desc("Abbreviate the description of type unit entries"));
71static opt<bool> Verify("verify", desc("Verify the DWARF debug info"),
72 cat(DwarfDumpCategory));
73static opt<bool> Quiet("quiet", desc("Use with -verify to not emit to STDOUT."),
74 cat(DwarfDumpCategory));
75static opt<bool> Verbose("verbose",
76 desc("Print more low-level encoding details"),
77 cat(DwarfDumpCategory));
78static alias VerboseAlias("v", desc("Alias for -verbose"), aliasopt(Verbose),
79 cat(DwarfDumpCategory));
80} // namespace
Adrian Prantl318d1192017-06-06 23:28:45 +000081
Davide Italiano4376ddb2015-07-26 05:35:59 +000082static void error(StringRef Filename, std::error_code EC) {
Alexey Samsonov85c7d662015-06-25 23:40:15 +000083 if (!EC)
Davide Italiano4376ddb2015-07-26 05:35:59 +000084 return;
Alexey Samsonov85c7d662015-06-25 23:40:15 +000085 errs() << Filename << ": " << EC.message() << "\n";
Davide Italiano4376ddb2015-07-26 05:35:59 +000086 exit(1);
Alexey Samsonov85c7d662015-06-25 23:40:15 +000087}
88
Adrian Prantl2611ffe2017-09-13 23:07:24 +000089static DIDumpOptions getDumpOpts() {
Jonas Devlieghere27476ce2017-09-13 09:43:05 +000090 DIDumpOptions DumpOpts;
91 DumpOpts.DumpType = DumpType;
92 DumpOpts.SummarizeTypes = SummarizeTypes;
93 DumpOpts.Verbose = Verbose;
94 return DumpOpts;
95}
96
Adrian Prantl2611ffe2017-09-13 23:07:24 +000097static bool dumpObjectFile(ObjectFile &Obj, Twine Filename) {
Reid Klecknera0587362017-08-29 21:41:21 +000098 std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
99 logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), errs(),
100 Filename.str() + ": ");
Adrian Prantl3dcd1222017-09-13 18:22:59 +0000101 // The UUID dump already contains all the same information.
102 if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
Adrian Prantl3ae35eb2017-09-13 22:09:01 +0000103 outs() << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n';
Spyridoula Gravanicc0d13a2017-06-12 19:04:28 +0000104
Frederic Riss40c017932015-08-03 00:10:25 +0000105 // Dump the complete DWARF structure.
Adrian Prantlb5abcc52017-09-15 22:47:16 +0000106 DICtx->dump(outs(), getDumpOpts());
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000107 return true;
Frederic Riss40c017932015-08-03 00:10:25 +0000108}
109
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000110static bool verifyObjectFile(ObjectFile &Obj, Twine Filename) {
Rafael Espindolac398e672017-07-19 22:27:28 +0000111 std::unique_ptr<DIContext> DICtx = DWARFContext::create(Obj);
112
Greg Clayton48432cf2017-05-01 22:07:02 +0000113 // Verify the DWARF and exit with non-zero exit status if verification
114 // fails.
115 raw_ostream &stream = Quiet ? nulls() : outs();
116 stream << "Verifying " << Filename.str() << ":\tfile format "
117 << Obj.getFileFormatName() << "\n";
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000118 bool Result = DICtx->verify(stream, DumpType, getDumpOpts());
Greg Clayton48432cf2017-05-01 22:07:02 +0000119 if (Result)
120 stream << "No errors.\n";
121 else
122 stream << "Errors detected.\n";
123 return Result;
124}
125
Adrian Prantld866b472017-09-13 23:16:13 +0000126static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
Adrian Prantl5fd3d492017-09-14 17:01:53 +0000127 std::function<bool(ObjectFile &, Twine)> HandleObj);
128
129static bool handleArchive(StringRef Filename, Archive &Arch,
130 std::function<bool(ObjectFile &, Twine)> HandleObj) {
131 bool Result = true;
132 Error Err = Error::success();
133 for (auto Child : Arch.children(Err)) {
134 auto BuffOrErr = Child.getMemoryBufferRef();
135 error(Filename, errorToErrorCode(BuffOrErr.takeError()));
136 auto NameOrErr = Child.getName();
137 error(Filename, errorToErrorCode(NameOrErr.takeError()));
138 std::string Name = (Filename + "(" + NameOrErr.get() + ")").str();
139 Result &= handleBuffer(Name, BuffOrErr.get(), HandleObj);
140 }
141 error(Filename, errorToErrorCode(std::move(Err)));
142
143 return Result;
144}
145
146static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000147 std::function<bool(ObjectFile &, Twine)> HandleObj) {
Adrian Prantld866b472017-09-13 23:16:13 +0000148 Expected<std::unique_ptr<Binary>> BinOrErr = object::createBinary(Buffer);
Adrian Prantl5fd3d492017-09-14 17:01:53 +0000149 error(Filename, errorToErrorCode(BinOrErr.takeError()));
Jonas Devlieghere8ac8df02017-08-31 16:44:47 +0000150
Greg Clayton48432cf2017-05-01 22:07:02 +0000151 bool Result = true;
152 if (auto *Obj = dyn_cast<ObjectFile>(BinOrErr->get()))
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000153 Result = HandleObj(*Obj, Filename);
Greg Clayton48432cf2017-05-01 22:07:02 +0000154 else if (auto *Fat = dyn_cast<MachOUniversalBinary>(BinOrErr->get()))
155 for (auto &ObjForArch : Fat->objects()) {
Adrian Prantl5fd3d492017-09-14 17:01:53 +0000156 std::string ObjName =
157 (Filename + "(" + ObjForArch.getArchFlagName() + ")").str();
158 if (auto MachOOrErr = ObjForArch.getAsObjectFile()) {
159 Result &= HandleObj(**MachOOrErr, ObjName);
160 continue;
161 } else
162 consumeError(MachOOrErr.takeError());
163 if (auto ArchiveOrErr = ObjForArch.getAsArchive()) {
164 error(ObjName, errorToErrorCode(ArchiveOrErr.takeError()));
165 Result &= handleArchive(ObjName, *ArchiveOrErr.get(), HandleObj);
166 continue;
167 } else
168 consumeError(ArchiveOrErr.takeError());
Greg Clayton48432cf2017-05-01 22:07:02 +0000169 }
Adrian Prantl5fd3d492017-09-14 17:01:53 +0000170 else if (auto *Arch = dyn_cast<Archive>(BinOrErr->get()))
171 Result = handleArchive(Filename, *Arch, HandleObj);
Greg Clayton48432cf2017-05-01 22:07:02 +0000172 return Result;
173}
174
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000175static bool handleFile(StringRef Filename,
176 std::function<bool(ObjectFile &, Twine)> HandleObj) {
177 ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
178 MemoryBuffer::getFileOrSTDIN(Filename);
179 error(Filename, BuffOrErr.getError());
180 std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.get());
181 return handleBuffer(Filename, *Buffer, HandleObj);
182}
183
Adrian Prantl8e7d3b92015-12-23 21:51:13 +0000184/// If the input path is a .dSYM bundle (as created by the dsymutil tool),
185/// replace it with individual entries for each of the object files inside the
186/// bundle otherwise return the input path.
Benjamin Kramerc321e532016-06-08 19:09:22 +0000187static std::vector<std::string> expandBundle(const std::string &InputPath) {
Adrian Prantl8e7d3b92015-12-23 21:51:13 +0000188 std::vector<std::string> BundlePaths;
189 SmallString<256> BundlePath(InputPath);
190 // Manually open up the bundle to avoid introducing additional dependencies.
191 if (sys::fs::is_directory(BundlePath) &&
192 sys::path::extension(BundlePath) == ".dSYM") {
193 std::error_code EC;
194 sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
195 for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
196 Dir != DirEnd && !EC; Dir.increment(EC)) {
197 const std::string &Path = Dir->path();
198 sys::fs::file_status Status;
199 EC = sys::fs::status(Path, Status);
200 error(Path, EC);
201 switch (Status.type()) {
202 case sys::fs::file_type::regular_file:
203 case sys::fs::file_type::symlink_file:
204 case sys::fs::file_type::type_unknown:
205 BundlePaths.push_back(Path);
206 break;
207 default: /*ignore*/;
208 }
209 }
210 error(BundlePath, EC);
211 }
212 if (!BundlePaths.size())
213 BundlePaths.push_back(InputPath);
214 return BundlePaths;
215}
216
Benjamin Krameraa2f78f2011-09-13 19:42:23 +0000217int main(int argc, char **argv) {
218 // Print a stack trace if we signal out.
Richard Smith2ad6d482016-06-09 00:53:21 +0000219 sys::PrintStackTraceOnErrorSignal(argv[0]);
Benjamin Krameraa2f78f2011-09-13 19:42:23 +0000220 PrettyStackTraceProgram X(argc, argv);
221 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
222
Reid Klecknera0587362017-08-29 21:41:21 +0000223 llvm::InitializeAllTargetInfos();
224 llvm::InitializeAllTargetMCs();
225
Adrian Prantl7c5b45d2017-09-12 22:32:53 +0000226 HideUnrelatedOptions({&DwarfDumpCategory, &SectionCategory});
227 cl::ParseCommandLineOptions(
228 argc, argv,
229 "pretty-print DWARF debug information in object files"
230 " and debug info archives.\n");
231
232 if (Help) {
233 PrintHelpMessage(/*Hidden =*/false, /*Categorized =*/true);
234 return 0;
235 }
Benjamin Krameraa2f78f2011-09-13 19:42:23 +0000236
Jonas Devlieghere8ac8df02017-08-31 16:44:47 +0000237 // Defaults to dumping all sections, unless brief mode is specified in which
238 // case only the .debug_info section in dumped.
Adrian Prantl7bc1b282017-09-11 22:59:45 +0000239#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
Adrian Prantlb5abcc52017-09-15 22:47:16 +0000240 if (Dump##ENUM_NAME) \
241 DumpType |= DIDT_##ENUM_NAME;
Adrian Prantl7bc1b282017-09-11 22:59:45 +0000242#include "llvm/BinaryFormat/Dwarf.def"
243#undef HANDLE_DWARF_SECTION
Adrian Prantl3dcd1222017-09-13 18:22:59 +0000244 if (DumpUUID)
245 DumpType |= DIDT_UUID;
Adrian Prantl7bc1b282017-09-11 22:59:45 +0000246 if (DumpAll)
247 DumpType = DIDT_All;
Jonas Devlieghere8ac8df02017-08-31 16:44:47 +0000248 if (DumpType == DIDT_Null) {
Adrian Prantl16aa4cf2017-09-11 23:05:20 +0000249 if (Verbose)
Jonas Devlieghere8ac8df02017-08-31 16:44:47 +0000250 DumpType = DIDT_All;
Adrian Prantl16aa4cf2017-09-11 23:05:20 +0000251 else
252 DumpType = DIDT_DebugInfo;
Jonas Devlieghere8ac8df02017-08-31 16:44:47 +0000253 }
254
Benjamin Krameraa2f78f2011-09-13 19:42:23 +0000255 // Defaults to a.out if no filenames specified.
256 if (InputFilenames.size() == 0)
257 InputFilenames.push_back("a.out");
258
Adrian Prantl8e7d3b92015-12-23 21:51:13 +0000259 // Expand any .dSYM bundles to the individual object files contained therein.
260 std::vector<std::string> Objects;
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000261 for (const auto &F : InputFilenames) {
Adrian Prantl8e7d3b92015-12-23 21:51:13 +0000262 auto Objs = expandBundle(F);
263 Objects.insert(Objects.end(), Objs.begin(), Objs.end());
264 }
265
Greg Clayton48432cf2017-05-01 22:07:02 +0000266 if (Verify) {
267 // If we encountered errors during verify, exit with a non-zero exit status.
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000268 if (!std::all_of(Objects.begin(), Objects.end(), [](std::string Object) {
269 return handleFile(Object, verifyObjectFile);
270 }))
Greg Clayton48432cf2017-05-01 22:07:02 +0000271 exit(1);
272 } else {
Adrian Prantl2611ffe2017-09-13 23:07:24 +0000273 std::for_each(Objects.begin(), Objects.end(), [](std::string Object) {
274 handleFile(Object, dumpObjectFile);
275 });
Greg Clayton48432cf2017-05-01 22:07:02 +0000276 }
Benjamin Krameraa2f78f2011-09-13 19:42:23 +0000277
Davide Italiano4376ddb2015-07-26 05:35:59 +0000278 return EXIT_SUCCESS;
Benjamin Krameraa2f78f2011-09-13 19:42:23 +0000279}