xref: /llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp (revision c83cd8feef7eb8319131d968bb8c94fdc8dbb6a6)
1 //===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This is a tool similar to readelf, except it works on multiple object file
10 // formats. The main purpose of this tool is to provide detailed output suitable
11 // for FileCheck.
12 //
13 // Flags should be similar to readelf where supported, but the output format
14 // does not need to be identical. The point is to not make users learn yet
15 // another set of flags.
16 //
17 // Output should be specialized for each format where appropriate.
18 //
19 //===----------------------------------------------------------------------===//
20 
21 #include "llvm-readobj.h"
22 #include "ObjDumper.h"
23 #include "WindowsResourceDumper.h"
24 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
25 #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
26 #include "llvm/Object/Archive.h"
27 #include "llvm/Object/COFFImportFile.h"
28 #include "llvm/Object/ELFObjectFile.h"
29 #include "llvm/Object/MachOUniversal.h"
30 #include "llvm/Object/ObjectFile.h"
31 #include "llvm/Object/Wasm.h"
32 #include "llvm/Object/WindowsResource.h"
33 #include "llvm/Object/XCOFFObjectFile.h"
34 #include "llvm/Support/Casting.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/DataTypes.h"
37 #include "llvm/Support/Debug.h"
38 #include "llvm/Support/Errc.h"
39 #include "llvm/Support/FileSystem.h"
40 #include "llvm/Support/FormatVariadic.h"
41 #include "llvm/Support/InitLLVM.h"
42 #include "llvm/Support/Path.h"
43 #include "llvm/Support/ScopedPrinter.h"
44 #include "llvm/Support/TargetRegistry.h"
45 #include "llvm/Support/WithColor.h"
46 
47 using namespace llvm;
48 using namespace llvm::object;
49 
50 namespace opts {
51   cl::list<std::string> InputFilenames(cl::Positional,
52     cl::desc("<input object files>"),
53     cl::ZeroOrMore);
54 
55   // --all, -a
56   cl::opt<bool>
57       All("all",
58           cl::desc("Equivalent to setting: --file-headers, --program-headers, "
59                    "--section-headers, --symbols, --relocations, "
60                    "--dynamic-table, --notes, --version-info, --unwind, "
61                    "--section-groups and --elf-hash-histogram."));
62   cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All));
63 
64   // --dependent-libraries
65   cl::opt<bool>
66       DependentLibraries("dependent-libraries",
67                          cl::desc("Display the dependent libraries section"));
68 
69   // --headers, -e
70   cl::opt<bool>
71       Headers("headers",
72           cl::desc("Equivalent to setting: --file-headers, --program-headers, "
73                    "--section-headers"));
74   cl::alias HeadersShort("e", cl::desc("Alias for --headers"),
75      cl::aliasopt(Headers));
76 
77   // --wide, -W
78   cl::opt<bool>
79       WideOutput("wide", cl::desc("Ignored for compatibility with GNU readelf"),
80                  cl::Hidden);
81   cl::alias WideOutputShort("W",
82     cl::desc("Alias for --wide"),
83     cl::aliasopt(WideOutput));
84 
85   // --file-headers, --file-header, -h
86   cl::opt<bool> FileHeaders("file-headers",
87     cl::desc("Display file headers "));
88   cl::alias FileHeadersShort("h", cl::desc("Alias for --file-headers"),
89                              cl::aliasopt(FileHeaders), cl::NotHidden);
90   cl::alias FileHeadersSingular("file-header",
91                                 cl::desc("Alias for --file-headers"),
92                                 cl::aliasopt(FileHeaders));
93 
94   // --section-headers, --sections, -S
95   // Also -s in llvm-readobj mode.
96   cl::opt<bool> SectionHeaders("section-headers",
97                                cl::desc("Display all section headers."));
98   cl::alias SectionsShortUpper("S", cl::desc("Alias for --section-headers"),
99                                cl::aliasopt(SectionHeaders), cl::NotHidden);
100   cl::alias SectionHeadersAlias("sections",
101                                 cl::desc("Alias for --section-headers"),
102                                 cl::aliasopt(SectionHeaders), cl::NotHidden);
103 
104   // --section-relocations
105   // Also --sr in llvm-readobj mode.
106   cl::opt<bool> SectionRelocations("section-relocations",
107     cl::desc("Display relocations for each section shown."));
108 
109   // --section-symbols
110   // Also --st in llvm-readobj mode.
111   cl::opt<bool> SectionSymbols("section-symbols",
112     cl::desc("Display symbols for each section shown."));
113 
114   // --section-data
115   // Also --sd in llvm-readobj mode.
116   cl::opt<bool> SectionData("section-data",
117     cl::desc("Display section data for each section shown."));
118 
119   // --section-mapping
120   cl::opt<cl::boolOrDefault>
121       SectionMapping("section-mapping",
122                      cl::desc("Display the section to segment mapping."));
123 
124   // --relocations, --relocs, -r
125   cl::opt<bool> Relocations("relocations",
126     cl::desc("Display the relocation entries in the file"));
127   cl::alias RelocationsShort("r", cl::desc("Alias for --relocations"),
128                              cl::aliasopt(Relocations), cl::NotHidden);
129   cl::alias RelocationsGNU("relocs", cl::desc("Alias for --relocations"),
130                            cl::aliasopt(Relocations));
131 
132   // --notes, -n
133   cl::opt<bool> Notes("notes", cl::desc("Display the ELF notes in the file"));
134   cl::alias NotesShort("n", cl::desc("Alias for --notes"), cl::aliasopt(Notes));
135 
136   // --dyn-relocations
137   cl::opt<bool> DynRelocs("dyn-relocations",
138     cl::desc("Display the dynamic relocation entries in the file"));
139 
140   // --section-details
141   // Also -t in llvm-readelf mode.
142   cl::opt<bool> SectionDetails("section-details",
143                                cl::desc("Display the section details"));
144 
145   // --symbols
146   // Also -s in llvm-readelf mode, or -t in llvm-readobj mode.
147   cl::opt<bool>
148       Symbols("symbols",
149               cl::desc("Display the symbol table. Also display the dynamic "
150                        "symbol table when using GNU output style for ELF"));
151   cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"),
152                        cl::aliasopt(Symbols));
153 
154   // --dyn-symbols, --dyn-syms
155   // Also --dt in llvm-readobj mode.
156   cl::opt<bool> DynamicSymbols("dyn-symbols",
157     cl::desc("Display the dynamic symbol table"));
158   cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"),
159                        cl::aliasopt(DynamicSymbols));
160 
161   // --hash-symbols
162   cl::opt<bool> HashSymbols(
163       "hash-symbols",
164       cl::desc("Display the dynamic symbols derived from the hash section"));
165 
166   // --unwind, -u
167   cl::opt<bool> UnwindInfo("unwind",
168     cl::desc("Display unwind information"));
169   cl::alias UnwindInfoShort("u",
170     cl::desc("Alias for --unwind"),
171     cl::aliasopt(UnwindInfo));
172 
173   // --dynamic-table, --dynamic, -d
174   cl::opt<bool> DynamicTable("dynamic-table",
175     cl::desc("Display the ELF .dynamic section table"));
176   cl::alias DynamicTableShort("d", cl::desc("Alias for --dynamic-table"),
177                               cl::aliasopt(DynamicTable), cl::NotHidden);
178   cl::alias DynamicTableAlias("dynamic", cl::desc("Alias for --dynamic-table"),
179                               cl::aliasopt(DynamicTable));
180 
181   // --needed-libs
182   cl::opt<bool> NeededLibraries("needed-libs",
183     cl::desc("Display the needed libraries"));
184 
185   // --program-headers, --segments, -l
186   cl::opt<bool> ProgramHeaders("program-headers",
187     cl::desc("Display ELF program headers"));
188   cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"),
189                                 cl::aliasopt(ProgramHeaders), cl::NotHidden);
190   cl::alias SegmentsAlias("segments", cl::desc("Alias for --program-headers"),
191                           cl::aliasopt(ProgramHeaders));
192 
193   // --string-dump, -p
194   cl::list<std::string> StringDump(
195       "string-dump", cl::value_desc("number|name"),
196       cl::desc("Display the specified section(s) as a list of strings"),
197       cl::ZeroOrMore);
198   cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"),
199                             cl::aliasopt(StringDump), cl::Prefix);
200 
201   // --hex-dump, -x
202   cl::list<std::string>
203       HexDump("hex-dump", cl::value_desc("number|name"),
204               cl::desc("Display the specified section(s) as hexadecimal bytes"),
205               cl::ZeroOrMore);
206   cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"),
207                          cl::aliasopt(HexDump), cl::Prefix);
208 
209   // --demangle, -C
210   cl::opt<bool> Demangle("demangle",
211                          cl::desc("Demangle symbol names in output"));
212   cl::alias DemangleShort("C", cl::desc("Alias for --demangle"),
213                           cl::aliasopt(Demangle), cl::NotHidden);
214 
215   // --hash-table
216   cl::opt<bool> HashTable("hash-table",
217     cl::desc("Display ELF hash table"));
218 
219   // --gnu-hash-table
220   cl::opt<bool> GnuHashTable("gnu-hash-table",
221     cl::desc("Display ELF .gnu.hash section"));
222 
223   // --expand-relocs
224   cl::opt<bool> ExpandRelocs("expand-relocs",
225     cl::desc("Expand each shown relocation to multiple lines"));
226 
227   // --raw-relr
228   cl::opt<bool> RawRelr("raw-relr",
229     cl::desc("Do not decode relocations in SHT_RELR section, display raw contents"));
230 
231   // --codeview
232   cl::opt<bool> CodeView("codeview",
233                          cl::desc("Display CodeView debug information"));
234 
235   // --codeview-merged-types
236   cl::opt<bool>
237       CodeViewMergedTypes("codeview-merged-types",
238                           cl::desc("Display the merged CodeView type stream"));
239 
240   // --codeview-ghash
241   cl::opt<bool> CodeViewEnableGHash(
242       "codeview-ghash",
243       cl::desc(
244           "Enable global hashing for CodeView type stream de-duplication"));
245 
246   // --codeview-subsection-bytes
247   cl::opt<bool> CodeViewSubsectionBytes(
248       "codeview-subsection-bytes",
249       cl::desc("Dump raw contents of codeview debug sections and records"));
250 
251   // --arch-specific
252   cl::opt<bool> ArchSpecificInfo("arch-specific",
253                               cl::desc("Displays architecture-specific information, if there is any."));
254   cl::alias ArchSpecifcInfoShort("A", cl::desc("Alias for --arch-specific"),
255                                  cl::aliasopt(ArchSpecificInfo), cl::NotHidden);
256 
257   // --coff-imports
258   cl::opt<bool>
259   COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
260 
261   // --coff-exports
262   cl::opt<bool>
263   COFFExports("coff-exports", cl::desc("Display the PE/COFF export table"));
264 
265   // --coff-directives
266   cl::opt<bool>
267   COFFDirectives("coff-directives",
268                  cl::desc("Display the PE/COFF .drectve section"));
269 
270   // --coff-basereloc
271   cl::opt<bool>
272   COFFBaseRelocs("coff-basereloc",
273                  cl::desc("Display the PE/COFF .reloc section"));
274 
275   // --coff-debug-directory
276   cl::opt<bool>
277   COFFDebugDirectory("coff-debug-directory",
278                      cl::desc("Display the PE/COFF debug directory"));
279 
280   // --coff-tls-directory
281   cl::opt<bool> COFFTLSDirectory("coff-tls-directory",
282                                  cl::desc("Display the PE/COFF TLS directory"));
283 
284   // --coff-resources
285   cl::opt<bool> COFFResources("coff-resources",
286                               cl::desc("Display the PE/COFF .rsrc section"));
287 
288   // --coff-load-config
289   cl::opt<bool>
290   COFFLoadConfig("coff-load-config",
291                  cl::desc("Display the PE/COFF load config"));
292 
293   // --elf-linker-options
294   cl::opt<bool>
295   ELFLinkerOptions("elf-linker-options",
296                    cl::desc("Display the ELF .linker-options section"));
297 
298   // --macho-data-in-code
299   cl::opt<bool>
300   MachODataInCode("macho-data-in-code",
301                   cl::desc("Display MachO Data in Code command"));
302 
303   // --macho-indirect-symbols
304   cl::opt<bool>
305   MachOIndirectSymbols("macho-indirect-symbols",
306                   cl::desc("Display MachO indirect symbols"));
307 
308   // --macho-linker-options
309   cl::opt<bool>
310   MachOLinkerOptions("macho-linker-options",
311                   cl::desc("Display MachO linker options"));
312 
313   // --macho-segment
314   cl::opt<bool>
315   MachOSegment("macho-segment",
316                   cl::desc("Display MachO Segment command"));
317 
318   // --macho-version-min
319   cl::opt<bool>
320   MachOVersionMin("macho-version-min",
321                   cl::desc("Display MachO version min command"));
322 
323   // --macho-dysymtab
324   cl::opt<bool>
325   MachODysymtab("macho-dysymtab",
326                   cl::desc("Display MachO Dysymtab command"));
327 
328   // --stackmap
329   cl::opt<bool>
330   PrintStackMap("stackmap",
331                 cl::desc("Display contents of stackmap section"));
332 
333   // --stack-sizes
334   cl::opt<bool>
335       PrintStackSizes("stack-sizes",
336                       cl::desc("Display contents of all stack sizes sections"));
337 
338   // --version-info, -V
339   cl::opt<bool>
340       VersionInfo("version-info",
341                   cl::desc("Display ELF version sections (if present)"));
342   cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"),
343                              cl::aliasopt(VersionInfo));
344 
345   // --elf-section-groups, --section-groups, -g
346   cl::opt<bool> SectionGroups("elf-section-groups",
347                               cl::desc("Display ELF section group contents"));
348   cl::alias SectionGroupsAlias("section-groups",
349                                cl::desc("Alias for -elf-sections-groups"),
350                                cl::aliasopt(SectionGroups));
351   cl::alias SectionGroupsShort("g", cl::desc("Alias for -elf-sections-groups"),
352                                cl::aliasopt(SectionGroups));
353 
354   // --elf-hash-histogram, --histogram, -I
355   cl::opt<bool> HashHistogram(
356       "elf-hash-histogram",
357       cl::desc("Display bucket list histogram for hash sections"));
358   cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"),
359                                cl::aliasopt(HashHistogram));
360   cl::alias HistogramAlias("histogram",
361                            cl::desc("Alias for --elf-hash-histogram"),
362                            cl::aliasopt(HashHistogram));
363 
364   // --cg-profile
365   cl::opt<bool> CGProfile("cg-profile",
366                           cl::desc("Display callgraph profile section"));
367   cl::alias ELFCGProfile("elf-cg-profile", cl::desc("Alias for --cg-profile"),
368                          cl::aliasopt(CGProfile));
369 
370   // --bb-addr-map
371   cl::opt<bool> BBAddrMap("bb-addr-map",
372                           cl::desc("Display the BB address map section"));
373 
374   // -addrsig
375   cl::opt<bool> Addrsig("addrsig",
376                         cl::desc("Display address-significance table"));
377 
378   // -elf-output-style
379   cl::opt<OutputStyleTy>
380       Output("elf-output-style", cl::desc("Specify ELF dump style"),
381              cl::values(clEnumVal(LLVM, "LLVM default style"),
382                         clEnumVal(GNU, "GNU readelf style")),
383              cl::init(LLVM));
384 
385   cl::extrahelp
386       HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
387 } // namespace opts
388 
389 static StringRef ToolName;
390 
391 namespace llvm {
392 
393 LLVM_ATTRIBUTE_NORETURN static void error(Twine Msg) {
394   // Flush the standard output to print the error at a
395   // proper place.
396   fouts().flush();
397   WithColor::error(errs(), ToolName) << Msg << "\n";
398   exit(1);
399 }
400 
401 LLVM_ATTRIBUTE_NORETURN void reportError(Error Err, StringRef Input) {
402   assert(Err);
403   if (Input == "-")
404     Input = "<stdin>";
405   handleAllErrors(createFileError(Input, std::move(Err)),
406                   [&](const ErrorInfoBase &EI) { error(EI.message()); });
407   llvm_unreachable("error() call should never return");
408 }
409 
410 void reportWarning(Error Err, StringRef Input) {
411   assert(Err);
412   if (Input == "-")
413     Input = "<stdin>";
414 
415   // Flush the standard output to print the warning at a
416   // proper place.
417   fouts().flush();
418   handleAllErrors(
419       createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
420         WithColor::warning(errs(), ToolName) << EI.message() << "\n";
421       });
422 }
423 
424 } // namespace llvm
425 
426 namespace {
427 struct ReadObjTypeTableBuilder {
428   ReadObjTypeTableBuilder()
429       : Allocator(), IDTable(Allocator), TypeTable(Allocator),
430         GlobalIDTable(Allocator), GlobalTypeTable(Allocator) {}
431 
432   llvm::BumpPtrAllocator Allocator;
433   llvm::codeview::MergingTypeTableBuilder IDTable;
434   llvm::codeview::MergingTypeTableBuilder TypeTable;
435   llvm::codeview::GlobalTypeTableBuilder GlobalIDTable;
436   llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable;
437   std::vector<OwningBinary<Binary>> Binaries;
438 };
439 } // namespace
440 static ReadObjTypeTableBuilder CVTypes;
441 
442 /// Creates an format-specific object file dumper.
443 static Expected<std::unique_ptr<ObjDumper>>
444 createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
445   if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj))
446     return createCOFFDumper(*COFFObj, Writer);
447 
448   if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
449     return createELFDumper(*ELFObj, Writer);
450 
451   if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
452     return createMachODumper(*MachOObj, Writer);
453 
454   if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
455     return createWasmDumper(*WasmObj, Writer);
456 
457   if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
458     return createXCOFFDumper(*XObj, Writer);
459 
460   return createStringError(errc::invalid_argument,
461                            "unsupported object file format");
462 }
463 
464 /// Dumps the specified object file.
465 static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
466                        const Archive *A = nullptr) {
467   std::string FileStr =
468       A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
469         : Obj.getFileName().str();
470 
471   std::string ContentErrString;
472   if (Error ContentErr = Obj.initContent())
473     ContentErrString = "unable to continue dumping, the file is corrupt: " +
474                        toString(std::move(ContentErr));
475 
476   ObjDumper *Dumper;
477   Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
478   if (!DumperOrErr)
479     reportError(DumperOrErr.takeError(), FileStr);
480   Dumper = (*DumperOrErr).get();
481 
482   if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || A) {
483     Writer.startLine() << "\n";
484     Writer.printString("File", FileStr);
485   }
486   if (opts::Output == opts::LLVM) {
487     Writer.printString("Format", Obj.getFileFormatName());
488     Writer.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
489     Writer.printString(
490         "AddressSize",
491         std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
492     Dumper->printLoadName();
493   }
494 
495   if (opts::FileHeaders)
496     Dumper->printFileHeaders();
497 
498   // This is only used for ELF currently. In some cases, when an object is
499   // corrupt (e.g. truncated), we can't dump anything except the file header.
500   if (!ContentErrString.empty())
501     reportError(createError(ContentErrString), FileStr);
502 
503   if (opts::SectionDetails || opts::SectionHeaders) {
504     if (opts::Output == opts::GNU && opts::SectionDetails)
505       Dumper->printSectionDetails();
506     else
507       Dumper->printSectionHeaders();
508   }
509 
510   if (opts::HashSymbols)
511     Dumper->printHashSymbols();
512   if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
513     Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
514   if (opts::DynamicTable)
515     Dumper->printDynamicTable();
516   if (opts::NeededLibraries)
517     Dumper->printNeededLibraries();
518   if (opts::Relocations)
519     Dumper->printRelocations();
520   if (opts::DynRelocs)
521     Dumper->printDynamicRelocations();
522   if (opts::UnwindInfo)
523     Dumper->printUnwindInfo();
524   if (opts::Symbols || opts::DynamicSymbols)
525     Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols);
526   if (!opts::StringDump.empty())
527     Dumper->printSectionsAsString(Obj, opts::StringDump);
528   if (!opts::HexDump.empty())
529     Dumper->printSectionsAsHex(Obj, opts::HexDump);
530   if (opts::HashTable)
531     Dumper->printHashTable();
532   if (opts::GnuHashTable)
533     Dumper->printGnuHashTable();
534   if (opts::VersionInfo)
535     Dumper->printVersionInfo();
536   if (Obj.isELF()) {
537     if (opts::DependentLibraries)
538       Dumper->printDependentLibs();
539     if (opts::ELFLinkerOptions)
540       Dumper->printELFLinkerOptions();
541     if (opts::ArchSpecificInfo)
542       Dumper->printArchSpecificInfo();
543     if (opts::SectionGroups)
544       Dumper->printGroupSections();
545     if (opts::HashHistogram)
546       Dumper->printHashHistograms();
547     if (opts::CGProfile)
548       Dumper->printCGProfile();
549     if (opts::BBAddrMap)
550       Dumper->printBBAddrMaps();
551     if (opts::Addrsig)
552       Dumper->printAddrsig();
553     if (opts::Notes)
554       Dumper->printNotes();
555   }
556   if (Obj.isCOFF()) {
557     if (opts::COFFImports)
558       Dumper->printCOFFImports();
559     if (opts::COFFExports)
560       Dumper->printCOFFExports();
561     if (opts::COFFDirectives)
562       Dumper->printCOFFDirectives();
563     if (opts::COFFBaseRelocs)
564       Dumper->printCOFFBaseReloc();
565     if (opts::COFFDebugDirectory)
566       Dumper->printCOFFDebugDirectory();
567     if (opts::COFFTLSDirectory)
568       Dumper->printCOFFTLSDirectory();
569     if (opts::COFFResources)
570       Dumper->printCOFFResources();
571     if (opts::COFFLoadConfig)
572       Dumper->printCOFFLoadConfig();
573     if (opts::CGProfile)
574       Dumper->printCGProfile();
575     if (opts::Addrsig)
576       Dumper->printAddrsig();
577     if (opts::CodeView)
578       Dumper->printCodeViewDebugInfo();
579     if (opts::CodeViewMergedTypes)
580       Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
581                                  CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
582                                  opts::CodeViewEnableGHash);
583   }
584   if (Obj.isMachO()) {
585     if (opts::MachODataInCode)
586       Dumper->printMachODataInCode();
587     if (opts::MachOIndirectSymbols)
588       Dumper->printMachOIndirectSymbols();
589     if (opts::MachOLinkerOptions)
590       Dumper->printMachOLinkerOptions();
591     if (opts::MachOSegment)
592       Dumper->printMachOSegment();
593     if (opts::MachOVersionMin)
594       Dumper->printMachOVersionMin();
595     if (opts::MachODysymtab)
596       Dumper->printMachODysymtab();
597   }
598   if (opts::PrintStackMap)
599     Dumper->printStackMap();
600   if (opts::PrintStackSizes)
601     Dumper->printStackSizes();
602 }
603 
604 /// Dumps each object file in \a Arc;
605 static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
606   Error Err = Error::success();
607   for (auto &Child : Arc->children(Err)) {
608     Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
609     if (!ChildOrErr) {
610       if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
611         reportError(std::move(E), Arc->getFileName());
612       continue;
613     }
614 
615     Binary *Bin = ChildOrErr->get();
616     if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
617       dumpObject(*Obj, Writer, Arc);
618     else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
619       dumpCOFFImportFile(Imp, Writer);
620     else
621       reportWarning(createStringError(errc::invalid_argument,
622                                       Bin->getFileName() +
623                                           " has an unsupported file type"),
624                     Arc->getFileName());
625   }
626   if (Err)
627     reportError(std::move(Err), Arc->getFileName());
628 }
629 
630 /// Dumps each object file in \a MachO Universal Binary;
631 static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
632                                      ScopedPrinter &Writer) {
633   for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
634     Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
635     if (ObjOrErr)
636       dumpObject(*ObjOrErr.get(), Writer);
637     else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
638       reportError(ObjOrErr.takeError(), UBinary->getFileName());
639     else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
640       dumpArchive(&*AOrErr.get(), Writer);
641   }
642 }
643 
644 /// Dumps \a WinRes, Windows Resource (.res) file;
645 static void dumpWindowsResourceFile(WindowsResource *WinRes,
646                                     ScopedPrinter &Printer) {
647   WindowsRes::Dumper Dumper(WinRes, Printer);
648   if (auto Err = Dumper.printData())
649     reportError(std::move(Err), WinRes->getFileName());
650 }
651 
652 
653 /// Opens \a File and dumps it.
654 static void dumpInput(StringRef File, ScopedPrinter &Writer) {
655   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
656       MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
657                                    /*RequiresNullTerminator=*/false);
658   if (std::error_code EC = FileOrErr.getError())
659     return reportError(errorCodeToError(EC), File);
660 
661   std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
662   file_magic Type = identify_magic(Buffer->getBuffer());
663   if (Type == file_magic::bitcode) {
664     reportWarning(createStringError(errc::invalid_argument,
665                                     "bitcode files are not supported"),
666                   File);
667     return;
668   }
669 
670   Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
671       Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
672   if (!BinaryOrErr)
673     reportError(BinaryOrErr.takeError(), File);
674 
675   std::unique_ptr<Binary> Bin = std::move(*BinaryOrErr);
676   if (Archive *Arc = dyn_cast<Archive>(Bin.get()))
677     dumpArchive(Arc, Writer);
678   else if (MachOUniversalBinary *UBinary =
679                dyn_cast<MachOUniversalBinary>(Bin.get()))
680     dumpMachOUniversalBinary(UBinary, Writer);
681   else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
682     dumpObject(*Obj, Writer);
683   else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
684     dumpCOFFImportFile(Import, Writer);
685   else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))
686     dumpWindowsResourceFile(WinRes, Writer);
687   else
688     llvm_unreachable("unrecognized file type");
689 
690   CVTypes.Binaries.push_back(
691       OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
692 }
693 
694 /// Registers aliases that should only be allowed by readobj.
695 static void registerReadobjAliases() {
696   // -s has meant --sections for a very long time in llvm-readobj despite
697   // meaning --symbols in readelf.
698   static cl::alias SectionsShort("s", cl::desc("Alias for --section-headers"),
699                                  cl::aliasopt(opts::SectionHeaders),
700                                  cl::NotHidden);
701 
702   // llvm-readelf reserves it for --section-details.
703   static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"),
704                                 cl::aliasopt(opts::Symbols), cl::NotHidden);
705 
706   // The following two-letter aliases are only provided for readobj, as readelf
707   // allows single-letter args to be grouped together.
708   static cl::alias SectionRelocationsShort(
709       "sr", cl::desc("Alias for --section-relocations"),
710       cl::aliasopt(opts::SectionRelocations));
711   static cl::alias SectionDataShort("sd", cl::desc("Alias for --section-data"),
712                                     cl::aliasopt(opts::SectionData));
713   static cl::alias SectionSymbolsShort("st",
714                                        cl::desc("Alias for --section-symbols"),
715                                        cl::aliasopt(opts::SectionSymbols));
716   static cl::alias DynamicSymbolsShort("dt",
717                                        cl::desc("Alias for --dyn-symbols"),
718                                        cl::aliasopt(opts::DynamicSymbols));
719 }
720 
721 /// Registers aliases that should only be allowed by readelf.
722 static void registerReadelfAliases() {
723   // -s is here because for readobj it means --sections.
724   static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"),
725                                 cl::aliasopt(opts::Symbols), cl::NotHidden,
726                                 cl::Grouping);
727 
728   // -t is here because for readobj it is an alias for --symbols.
729   static cl::alias SectionDetailsShort(
730       "t", cl::desc("Alias for --section-details"),
731       cl::aliasopt(opts::SectionDetails), cl::NotHidden);
732 
733   // Allow all single letter flags to be grouped together.
734   for (auto &OptEntry : cl::getRegisteredOptions()) {
735     StringRef ArgName = OptEntry.getKey();
736     cl::Option *Option = OptEntry.getValue();
737     if (ArgName.size() == 1)
738       apply(Option, cl::Grouping);
739   }
740 }
741 
742 int main(int argc, const char *argv[]) {
743   InitLLVM X(argc, argv);
744   ToolName = argv[0];
745 
746   // Register the target printer for --version.
747   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
748 
749   if (sys::path::stem(argv[0]).contains("readelf")) {
750     opts::Output = opts::GNU;
751     registerReadelfAliases();
752   } else {
753     registerReadobjAliases();
754   }
755 
756   cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n");
757 
758   // Default to print error if no filename is specified.
759   if (opts::InputFilenames.empty()) {
760     error("no input files specified");
761   }
762 
763   if (opts::All) {
764     opts::FileHeaders = true;
765     opts::ProgramHeaders = true;
766     opts::SectionHeaders = true;
767     opts::Symbols = true;
768     opts::Relocations = true;
769     opts::DynamicTable = true;
770     opts::Notes = true;
771     opts::VersionInfo = true;
772     opts::UnwindInfo = true;
773     opts::SectionGroups = true;
774     opts::HashHistogram = true;
775     if (opts::Output == opts::LLVM) {
776       opts::Addrsig = true;
777       opts::PrintStackSizes = true;
778     }
779   }
780 
781   if (opts::Headers) {
782     opts::FileHeaders = true;
783     opts::ProgramHeaders = true;
784     opts::SectionHeaders = true;
785   }
786 
787   ScopedPrinter Writer(fouts());
788   for (const std::string &I : opts::InputFilenames)
789     dumpInput(I, Writer);
790 
791   if (opts::CodeViewMergedTypes) {
792     if (opts::CodeViewEnableGHash)
793       dumpCodeViewMergedTypes(Writer, CVTypes.GlobalIDTable.records(),
794                               CVTypes.GlobalTypeTable.records());
795     else
796       dumpCodeViewMergedTypes(Writer, CVTypes.IDTable.records(),
797                               CVTypes.TypeTable.records());
798   }
799 
800   return 0;
801 }
802