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   // -addrsig
371   cl::opt<bool> Addrsig("addrsig",
372                         cl::desc("Display address-significance table"));
373 
374   // -elf-output-style
375   cl::opt<OutputStyleTy>
376       Output("elf-output-style", cl::desc("Specify ELF dump style"),
377              cl::values(clEnumVal(LLVM, "LLVM default style"),
378                         clEnumVal(GNU, "GNU readelf style")),
379              cl::init(LLVM));
380 
381   cl::extrahelp
382       HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
383 } // namespace opts
384 
385 static StringRef ToolName;
386 
387 namespace llvm {
388 
error(Twine Msg)389 LLVM_ATTRIBUTE_NORETURN static void error(Twine Msg) {
390   // Flush the standard output to print the error at a
391   // proper place.
392   fouts().flush();
393   WithColor::error(errs(), ToolName) << Msg << "\n";
394   exit(1);
395 }
396 
reportError(Error Err,StringRef Input)397 LLVM_ATTRIBUTE_NORETURN void reportError(Error Err, StringRef Input) {
398   assert(Err);
399   if (Input == "-")
400     Input = "<stdin>";
401   handleAllErrors(createFileError(Input, std::move(Err)),
402                   [&](const ErrorInfoBase &EI) { error(EI.message()); });
403   llvm_unreachable("error() call should never return");
404 }
405 
reportWarning(Error Err,StringRef Input)406 void reportWarning(Error Err, StringRef Input) {
407   assert(Err);
408   if (Input == "-")
409     Input = "<stdin>";
410 
411   // Flush the standard output to print the warning at a
412   // proper place.
413   fouts().flush();
414   handleAllErrors(
415       createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
416         WithColor::warning(errs(), ToolName) << EI.message() << "\n";
417       });
418 }
419 
420 } // namespace llvm
421 
422 namespace {
423 struct ReadObjTypeTableBuilder {
ReadObjTypeTableBuilder__anone3f281d00311::ReadObjTypeTableBuilder424   ReadObjTypeTableBuilder()
425       : Allocator(), IDTable(Allocator), TypeTable(Allocator),
426         GlobalIDTable(Allocator), GlobalTypeTable(Allocator) {}
427 
428   llvm::BumpPtrAllocator Allocator;
429   llvm::codeview::MergingTypeTableBuilder IDTable;
430   llvm::codeview::MergingTypeTableBuilder TypeTable;
431   llvm::codeview::GlobalTypeTableBuilder GlobalIDTable;
432   llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable;
433   std::vector<OwningBinary<Binary>> Binaries;
434 };
435 } // namespace
436 static ReadObjTypeTableBuilder CVTypes;
437 
438 /// Creates an format-specific object file dumper.
439 static Expected<std::unique_ptr<ObjDumper>>
createDumper(const ObjectFile & Obj,ScopedPrinter & Writer)440 createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
441   if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj))
442     return createCOFFDumper(*COFFObj, Writer);
443 
444   if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
445     return createELFDumper(*ELFObj, Writer);
446 
447   if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
448     return createMachODumper(*MachOObj, Writer);
449 
450   if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
451     return createWasmDumper(*WasmObj, Writer);
452 
453   if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
454     return createXCOFFDumper(*XObj, Writer);
455 
456   return createStringError(errc::invalid_argument,
457                            "unsupported object file format");
458 }
459 
460 /// Dumps the specified object file.
dumpObject(ObjectFile & Obj,ScopedPrinter & Writer,const Archive * A=nullptr)461 static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
462                        const Archive *A = nullptr) {
463   std::string FileStr =
464       A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
465         : Obj.getFileName().str();
466 
467   std::string ContentErrString;
468   if (Error ContentErr = Obj.initContent())
469     ContentErrString = "unable to continue dumping, the file is corrupt: " +
470                        toString(std::move(ContentErr));
471 
472   ObjDumper *Dumper;
473   Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
474   if (!DumperOrErr)
475     reportError(DumperOrErr.takeError(), FileStr);
476   Dumper = (*DumperOrErr).get();
477 
478   if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || A) {
479     Writer.startLine() << "\n";
480     Writer.printString("File", FileStr);
481   }
482   if (opts::Output == opts::LLVM) {
483     Writer.printString("Format", Obj.getFileFormatName());
484     Writer.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
485     Writer.printString(
486         "AddressSize",
487         std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
488     Dumper->printLoadName();
489   }
490 
491   if (opts::FileHeaders)
492     Dumper->printFileHeaders();
493 
494   // This is only used for ELF currently. In some cases, when an object is
495   // corrupt (e.g. truncated), we can't dump anything except the file header.
496   if (!ContentErrString.empty())
497     reportError(createError(ContentErrString), FileStr);
498 
499   if (opts::SectionDetails || opts::SectionHeaders) {
500     if (opts::Output == opts::GNU && opts::SectionDetails)
501       Dumper->printSectionDetails();
502     else
503       Dumper->printSectionHeaders();
504   }
505 
506   if (opts::HashSymbols)
507     Dumper->printHashSymbols();
508   if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
509     Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
510   if (opts::DynamicTable)
511     Dumper->printDynamicTable();
512   if (opts::NeededLibraries)
513     Dumper->printNeededLibraries();
514   if (opts::Relocations)
515     Dumper->printRelocations();
516   if (opts::DynRelocs)
517     Dumper->printDynamicRelocations();
518   if (opts::UnwindInfo)
519     Dumper->printUnwindInfo();
520   if (opts::Symbols || opts::DynamicSymbols)
521     Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols);
522   if (!opts::StringDump.empty())
523     Dumper->printSectionsAsString(Obj, opts::StringDump);
524   if (!opts::HexDump.empty())
525     Dumper->printSectionsAsHex(Obj, opts::HexDump);
526   if (opts::HashTable)
527     Dumper->printHashTable();
528   if (opts::GnuHashTable)
529     Dumper->printGnuHashTable();
530   if (opts::VersionInfo)
531     Dumper->printVersionInfo();
532   if (Obj.isELF()) {
533     if (opts::DependentLibraries)
534       Dumper->printDependentLibs();
535     if (opts::ELFLinkerOptions)
536       Dumper->printELFLinkerOptions();
537     if (opts::ArchSpecificInfo)
538       Dumper->printArchSpecificInfo();
539     if (opts::SectionGroups)
540       Dumper->printGroupSections();
541     if (opts::HashHistogram)
542       Dumper->printHashHistograms();
543     if (opts::CGProfile)
544       Dumper->printCGProfile();
545     if (opts::Addrsig)
546       Dumper->printAddrsig();
547     if (opts::Notes)
548       Dumper->printNotes();
549   }
550   if (Obj.isCOFF()) {
551     if (opts::COFFImports)
552       Dumper->printCOFFImports();
553     if (opts::COFFExports)
554       Dumper->printCOFFExports();
555     if (opts::COFFDirectives)
556       Dumper->printCOFFDirectives();
557     if (opts::COFFBaseRelocs)
558       Dumper->printCOFFBaseReloc();
559     if (opts::COFFDebugDirectory)
560       Dumper->printCOFFDebugDirectory();
561     if (opts::COFFTLSDirectory)
562       Dumper->printCOFFTLSDirectory();
563     if (opts::COFFResources)
564       Dumper->printCOFFResources();
565     if (opts::COFFLoadConfig)
566       Dumper->printCOFFLoadConfig();
567     if (opts::CGProfile)
568       Dumper->printCGProfile();
569     if (opts::Addrsig)
570       Dumper->printAddrsig();
571     if (opts::CodeView)
572       Dumper->printCodeViewDebugInfo();
573     if (opts::CodeViewMergedTypes)
574       Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
575                                  CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
576                                  opts::CodeViewEnableGHash);
577   }
578   if (Obj.isMachO()) {
579     if (opts::MachODataInCode)
580       Dumper->printMachODataInCode();
581     if (opts::MachOIndirectSymbols)
582       Dumper->printMachOIndirectSymbols();
583     if (opts::MachOLinkerOptions)
584       Dumper->printMachOLinkerOptions();
585     if (opts::MachOSegment)
586       Dumper->printMachOSegment();
587     if (opts::MachOVersionMin)
588       Dumper->printMachOVersionMin();
589     if (opts::MachODysymtab)
590       Dumper->printMachODysymtab();
591   }
592   if (opts::PrintStackMap)
593     Dumper->printStackMap();
594   if (opts::PrintStackSizes)
595     Dumper->printStackSizes();
596 }
597 
598 /// Dumps each object file in \a Arc;
dumpArchive(const Archive * Arc,ScopedPrinter & Writer)599 static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
600   Error Err = Error::success();
601   for (auto &Child : Arc->children(Err)) {
602     Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
603     if (!ChildOrErr) {
604       if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
605         reportError(std::move(E), Arc->getFileName());
606       continue;
607     }
608 
609     Binary *Bin = ChildOrErr->get();
610     if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
611       dumpObject(*Obj, Writer, Arc);
612     else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
613       dumpCOFFImportFile(Imp, Writer);
614     else
615       reportWarning(createStringError(errc::invalid_argument,
616                                       Bin->getFileName() +
617                                           " has an unsupported file type"),
618                     Arc->getFileName());
619   }
620   if (Err)
621     reportError(std::move(Err), Arc->getFileName());
622 }
623 
624 /// Dumps each object file in \a MachO Universal Binary;
dumpMachOUniversalBinary(const MachOUniversalBinary * UBinary,ScopedPrinter & Writer)625 static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
626                                      ScopedPrinter &Writer) {
627   for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
628     Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
629     if (ObjOrErr)
630       dumpObject(*ObjOrErr.get(), Writer);
631     else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
632       reportError(ObjOrErr.takeError(), UBinary->getFileName());
633     else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
634       dumpArchive(&*AOrErr.get(), Writer);
635   }
636 }
637 
638 /// Dumps \a WinRes, Windows Resource (.res) file;
dumpWindowsResourceFile(WindowsResource * WinRes,ScopedPrinter & Printer)639 static void dumpWindowsResourceFile(WindowsResource *WinRes,
640                                     ScopedPrinter &Printer) {
641   WindowsRes::Dumper Dumper(WinRes, Printer);
642   if (auto Err = Dumper.printData())
643     reportError(std::move(Err), WinRes->getFileName());
644 }
645 
646 
647 /// Opens \a File and dumps it.
dumpInput(StringRef File,ScopedPrinter & Writer)648 static void dumpInput(StringRef File, ScopedPrinter &Writer) {
649   // Attempt to open the binary.
650   Expected<OwningBinary<Binary>> BinaryOrErr =
651       createBinary(File, /*Context=*/nullptr, /*InitContent=*/false);
652   if (!BinaryOrErr)
653     reportError(BinaryOrErr.takeError(), File);
654   Binary &Binary = *BinaryOrErr.get().getBinary();
655 
656   if (Archive *Arc = dyn_cast<Archive>(&Binary))
657     dumpArchive(Arc, Writer);
658   else if (MachOUniversalBinary *UBinary =
659                dyn_cast<MachOUniversalBinary>(&Binary))
660     dumpMachOUniversalBinary(UBinary, Writer);
661   else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
662     dumpObject(*Obj, Writer);
663   else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary))
664     dumpCOFFImportFile(Import, Writer);
665   else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary))
666     dumpWindowsResourceFile(WinRes, Writer);
667   else
668     llvm_unreachable("unrecognized file type");
669 
670   CVTypes.Binaries.push_back(std::move(*BinaryOrErr));
671 }
672 
673 /// Registers aliases that should only be allowed by readobj.
registerReadobjAliases()674 static void registerReadobjAliases() {
675   // -s has meant --sections for a very long time in llvm-readobj despite
676   // meaning --symbols in readelf.
677   static cl::alias SectionsShort("s", cl::desc("Alias for --section-headers"),
678                                  cl::aliasopt(opts::SectionHeaders),
679                                  cl::NotHidden);
680 
681   // llvm-readelf reserves it for --section-details.
682   static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"),
683                                 cl::aliasopt(opts::Symbols), cl::NotHidden);
684 
685   // The following two-letter aliases are only provided for readobj, as readelf
686   // allows single-letter args to be grouped together.
687   static cl::alias SectionRelocationsShort(
688       "sr", cl::desc("Alias for --section-relocations"),
689       cl::aliasopt(opts::SectionRelocations));
690   static cl::alias SectionDataShort("sd", cl::desc("Alias for --section-data"),
691                                     cl::aliasopt(opts::SectionData));
692   static cl::alias SectionSymbolsShort("st",
693                                        cl::desc("Alias for --section-symbols"),
694                                        cl::aliasopt(opts::SectionSymbols));
695   static cl::alias DynamicSymbolsShort("dt",
696                                        cl::desc("Alias for --dyn-symbols"),
697                                        cl::aliasopt(opts::DynamicSymbols));
698 }
699 
700 /// Registers aliases that should only be allowed by readelf.
registerReadelfAliases()701 static void registerReadelfAliases() {
702   // -s is here because for readobj it means --sections.
703   static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"),
704                                 cl::aliasopt(opts::Symbols), cl::NotHidden,
705                                 cl::Grouping);
706 
707   // -t is here because for readobj it is an alias for --symbols.
708   static cl::alias SectionDetailsShort(
709       "t", cl::desc("Alias for --section-details"),
710       cl::aliasopt(opts::SectionDetails), cl::NotHidden);
711 
712   // Allow all single letter flags to be grouped together.
713   for (auto &OptEntry : cl::getRegisteredOptions()) {
714     StringRef ArgName = OptEntry.getKey();
715     cl::Option *Option = OptEntry.getValue();
716     if (ArgName.size() == 1)
717       apply(Option, cl::Grouping);
718   }
719 }
720 
main(int argc,const char * argv[])721 int main(int argc, const char *argv[]) {
722   InitLLVM X(argc, argv);
723   ToolName = argv[0];
724 
725   // Register the target printer for --version.
726   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
727 
728   if (sys::path::stem(argv[0]).contains("readelf")) {
729     opts::Output = opts::GNU;
730     registerReadelfAliases();
731   } else {
732     registerReadobjAliases();
733   }
734 
735   cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n");
736 
737   // Default to print error if no filename is specified.
738   if (opts::InputFilenames.empty()) {
739     error("no input files specified");
740   }
741 
742   if (opts::All) {
743     opts::FileHeaders = true;
744     opts::ProgramHeaders = true;
745     opts::SectionHeaders = true;
746     opts::Symbols = true;
747     opts::Relocations = true;
748     opts::DynamicTable = true;
749     opts::Notes = true;
750     opts::VersionInfo = true;
751     opts::UnwindInfo = true;
752     opts::SectionGroups = true;
753     opts::HashHistogram = true;
754     if (opts::Output == opts::LLVM) {
755       opts::Addrsig = true;
756       opts::PrintStackSizes = true;
757     }
758   }
759 
760   if (opts::Headers) {
761     opts::FileHeaders = true;
762     opts::ProgramHeaders = true;
763     opts::SectionHeaders = true;
764   }
765 
766   ScopedPrinter Writer(fouts());
767   for (const std::string &I : opts::InputFilenames)
768     dumpInput(I, Writer);
769 
770   if (opts::CodeViewMergedTypes) {
771     if (opts::CodeViewEnableGHash)
772       dumpCodeViewMergedTypes(Writer, CVTypes.GlobalIDTable.records(),
773                               CVTypes.GlobalTypeTable.records());
774     else
775       dumpCodeViewMergedTypes(Writer, CVTypes.IDTable.records(),
776                               CVTypes.TypeTable.records());
777   }
778 
779   return 0;
780 }
781