1 //===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
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 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
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.
17 // Output should be specialized for each format where appropriate.
19 //===----------------------------------------------------------------------===//
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/MC/TargetRegistry.h"
27 #include "llvm/Object/Archive.h"
28 #include "llvm/Object/COFFImportFile.h"
29 #include "llvm/Object/ELFObjectFile.h"
30 #include "llvm/Object/MachOUniversal.h"
31 #include "llvm/Object/ObjectFile.h"
32 #include "llvm/Object/Wasm.h"
33 #include "llvm/Object/WindowsResource.h"
34 #include "llvm/Object/XCOFFObjectFile.h"
35 #include "llvm/Option/Arg.h"
36 #include "llvm/Option/ArgList.h"
37 #include "llvm/Option/Option.h"
38 #include "llvm/Support/Casting.h"
39 #include "llvm/Support/CommandLine.h"
40 #include "llvm/Support/DataTypes.h"
41 #include "llvm/Support/Debug.h"
42 #include "llvm/Support/Errc.h"
43 #include "llvm/Support/FileSystem.h"
44 #include "llvm/Support/FormatVariadic.h"
45 #include "llvm/Support/InitLLVM.h"
46 #include "llvm/Support/Path.h"
47 #include "llvm/Support/ScopedPrinter.h"
48 #include "llvm/Support/WithColor.h"
51 using namespace llvm::object
;
54 using namespace llvm::opt
; // for HelpHidden in Opts.inc
56 OPT_INVALID
= 0, // This is not an option ID.
57 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
58 HELPTEXT, METAVAR, VALUES) \
64 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
68 const opt::OptTable::Info InfoTable
[] = {
69 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
70 HELPTEXT, METAVAR, VALUES) \
72 PREFIX, NAME, HELPTEXT, \
73 METAVAR, OPT_##ID, opt::Option::KIND##Class, \
74 PARAM, FLAGS, OPT_##GROUP, \
75 OPT_##ALIAS, ALIASARGS, VALUES},
80 class ReadobjOptTable
: public opt::OptTable
{
82 ReadobjOptTable() : OptTable(InfoTable
) { setGroupedShortOptions(true); }
85 enum OutputFormatTy
{ bsd
, sysv
, posix
, darwin
, just_symbols
};
91 static bool ArchSpecificInfo
;
92 static bool BBAddrMap
;
94 static bool CGProfile
;
96 static bool DependentLibraries
;
97 static bool DynRelocs
;
98 static bool DynamicSymbols
;
99 static bool FileHeaders
;
101 static std::vector
<std::string
> HexDump
;
102 static bool PrettyPrint
;
103 static bool PrintStackMap
;
104 static bool PrintStackSizes
;
105 static bool Relocations
;
107 static bool SectionDetails
;
108 static bool SectionHeaders
;
109 bool SectionRelocations
;
111 static std::vector
<std::string
> StringDump
;
112 static bool StringTable
;
114 static bool UnwindInfo
;
115 static cl::boolOrDefault SectionMapping
;
117 // ELF specific options.
118 static bool DynamicTable
;
119 static bool ELFLinkerOptions
;
120 static bool GnuHashTable
;
121 static bool HashSymbols
;
122 static bool HashTable
;
123 static bool HashHistogram
;
124 static bool NeededLibraries
;
126 static bool ProgramHeaders
;
128 static bool SectionGroups
;
129 static bool VersionInfo
;
131 // Mach-O specific options.
132 static bool MachODataInCode
;
133 static bool MachODysymtab
;
134 static bool MachOIndirectSymbols
;
135 static bool MachOLinkerOptions
;
136 static bool MachOSegment
;
137 static bool MachOVersionMin
;
139 // PE/COFF specific options.
140 static bool CodeView
;
141 static bool CodeViewEnableGHash
;
142 static bool CodeViewMergedTypes
;
143 bool CodeViewSubsectionBytes
;
144 static bool COFFBaseRelocs
;
145 static bool COFFDebugDirectory
;
146 static bool COFFDirectives
;
147 static bool COFFExports
;
148 static bool COFFImports
;
149 static bool COFFLoadConfig
;
150 static bool COFFResources
;
151 static bool COFFTLSDirectory
;
153 // XCOFF specific options.
154 static bool XCOFFAuxiliaryHeader
;
156 OutputStyleTy Output
= OutputStyleTy::LLVM
;
157 static std::vector
<std::string
> InputFilenames
;
160 static StringRef ToolName
;
164 [[noreturn
]] static void error(Twine Msg
) {
165 // Flush the standard output to print the error at a
168 WithColor::error(errs(), ToolName
) << Msg
<< "\n";
172 [[noreturn
]] void reportError(Error Err
, StringRef Input
) {
176 handleAllErrors(createFileError(Input
, std::move(Err
)),
177 [&](const ErrorInfoBase
&EI
) { error(EI
.message()); });
178 llvm_unreachable("error() call should never return");
181 void reportWarning(Error Err
, StringRef Input
) {
186 // Flush the standard output to print the warning at a
190 createFileError(Input
, std::move(Err
)), [&](const ErrorInfoBase
&EI
) {
191 WithColor::warning(errs(), ToolName
) << EI
.message() << "\n";
197 static void parseOptions(const opt::InputArgList
&Args
) {
198 opts::Addrsig
= Args
.hasArg(OPT_addrsig
);
199 opts::All
= Args
.hasArg(OPT_all
);
200 opts::ArchSpecificInfo
= Args
.hasArg(OPT_arch_specific
);
201 opts::BBAddrMap
= Args
.hasArg(OPT_bb_addr_map
);
202 opts::CGProfile
= Args
.hasArg(OPT_cg_profile
);
203 opts::Demangle
= Args
.hasFlag(OPT_demangle
, OPT_no_demangle
, false);
204 opts::DependentLibraries
= Args
.hasArg(OPT_dependent_libraries
);
205 opts::DynRelocs
= Args
.hasArg(OPT_dyn_relocations
);
206 opts::DynamicSymbols
= Args
.hasArg(OPT_dyn_syms
);
207 opts::ExpandRelocs
= Args
.hasArg(OPT_expand_relocs
);
208 opts::FileHeaders
= Args
.hasArg(OPT_file_header
);
209 opts::Headers
= Args
.hasArg(OPT_headers
);
210 opts::HexDump
= Args
.getAllArgValues(OPT_hex_dump_EQ
);
211 opts::Relocations
= Args
.hasArg(OPT_relocs
);
212 opts::SectionData
= Args
.hasArg(OPT_section_data
);
213 opts::SectionDetails
= Args
.hasArg(OPT_section_details
);
214 opts::SectionHeaders
= Args
.hasArg(OPT_section_headers
);
215 opts::SectionRelocations
= Args
.hasArg(OPT_section_relocations
);
216 opts::SectionSymbols
= Args
.hasArg(OPT_section_symbols
);
217 if (Args
.hasArg(OPT_section_mapping
))
218 opts::SectionMapping
= cl::BOU_TRUE
;
219 else if (Args
.hasArg(OPT_section_mapping_EQ_false
))
220 opts::SectionMapping
= cl::BOU_FALSE
;
222 opts::SectionMapping
= cl::BOU_UNSET
;
223 opts::PrintStackSizes
= Args
.hasArg(OPT_stack_sizes
);
224 opts::PrintStackMap
= Args
.hasArg(OPT_stackmap
);
225 opts::StringDump
= Args
.getAllArgValues(OPT_string_dump_EQ
);
226 opts::StringTable
= Args
.hasArg(OPT_string_table
);
227 opts::Symbols
= Args
.hasArg(OPT_symbols
);
228 opts::UnwindInfo
= Args
.hasArg(OPT_unwind
);
230 // ELF specific options.
231 opts::DynamicTable
= Args
.hasArg(OPT_dynamic_table
);
232 opts::ELFLinkerOptions
= Args
.hasArg(OPT_elf_linker_options
);
233 if (Arg
*A
= Args
.getLastArg(OPT_elf_output_style_EQ
)) {
234 std::string OutputStyleChoice
= A
->getValue();
235 opts::Output
= StringSwitch
<opts::OutputStyleTy
>(OutputStyleChoice
)
236 .Case("LLVM", opts::OutputStyleTy::LLVM
)
237 .Case("GNU", opts::OutputStyleTy::GNU
)
238 .Case("JSON", opts::OutputStyleTy::JSON
)
239 .Default(opts::OutputStyleTy::UNKNOWN
);
240 if (opts::Output
== opts::OutputStyleTy::UNKNOWN
) {
241 error("--elf-output-style value should be either 'LLVM', 'GNU', or "
242 "'JSON', but was '" +
243 OutputStyleChoice
+ "'");
246 opts::GnuHashTable
= Args
.hasArg(OPT_gnu_hash_table
);
247 opts::HashSymbols
= Args
.hasArg(OPT_hash_symbols
);
248 opts::HashTable
= Args
.hasArg(OPT_hash_table
);
249 opts::HashHistogram
= Args
.hasArg(OPT_histogram
);
250 opts::NeededLibraries
= Args
.hasArg(OPT_needed_libs
);
251 opts::Notes
= Args
.hasArg(OPT_notes
);
252 opts::PrettyPrint
= Args
.hasArg(OPT_pretty_print
);
253 opts::ProgramHeaders
= Args
.hasArg(OPT_program_headers
);
254 opts::RawRelr
= Args
.hasArg(OPT_raw_relr
);
255 opts::SectionGroups
= Args
.hasArg(OPT_section_groups
);
256 opts::VersionInfo
= Args
.hasArg(OPT_version_info
);
258 // Mach-O specific options.
259 opts::MachODataInCode
= Args
.hasArg(OPT_macho_data_in_code
);
260 opts::MachODysymtab
= Args
.hasArg(OPT_macho_dysymtab
);
261 opts::MachOIndirectSymbols
= Args
.hasArg(OPT_macho_indirect_symbols
);
262 opts::MachOLinkerOptions
= Args
.hasArg(OPT_macho_linker_options
);
263 opts::MachOSegment
= Args
.hasArg(OPT_macho_segment
);
264 opts::MachOVersionMin
= Args
.hasArg(OPT_macho_version_min
);
266 // PE/COFF specific options.
267 opts::CodeView
= Args
.hasArg(OPT_codeview
);
268 opts::CodeViewEnableGHash
= Args
.hasArg(OPT_codeview_ghash
);
269 opts::CodeViewMergedTypes
= Args
.hasArg(OPT_codeview_merged_types
);
270 opts::CodeViewSubsectionBytes
= Args
.hasArg(OPT_codeview_subsection_bytes
);
271 opts::COFFBaseRelocs
= Args
.hasArg(OPT_coff_basereloc
);
272 opts::COFFDebugDirectory
= Args
.hasArg(OPT_coff_debug_directory
);
273 opts::COFFDirectives
= Args
.hasArg(OPT_coff_directives
);
274 opts::COFFExports
= Args
.hasArg(OPT_coff_exports
);
275 opts::COFFImports
= Args
.hasArg(OPT_coff_imports
);
276 opts::COFFLoadConfig
= Args
.hasArg(OPT_coff_load_config
);
277 opts::COFFResources
= Args
.hasArg(OPT_coff_resources
);
278 opts::COFFTLSDirectory
= Args
.hasArg(OPT_coff_tls_directory
);
280 // XCOFF specific options.
281 opts::XCOFFAuxiliaryHeader
= Args
.hasArg(OPT_auxiliary_header
);
283 opts::InputFilenames
= Args
.getAllArgValues(OPT_INPUT
);
287 struct ReadObjTypeTableBuilder
{
288 ReadObjTypeTableBuilder()
289 : IDTable(Allocator
), TypeTable(Allocator
), GlobalIDTable(Allocator
),
290 GlobalTypeTable(Allocator
) {}
292 llvm::BumpPtrAllocator Allocator
;
293 llvm::codeview::MergingTypeTableBuilder IDTable
;
294 llvm::codeview::MergingTypeTableBuilder TypeTable
;
295 llvm::codeview::GlobalTypeTableBuilder GlobalIDTable
;
296 llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable
;
297 std::vector
<OwningBinary
<Binary
>> Binaries
;
300 static ReadObjTypeTableBuilder CVTypes
;
302 /// Creates an format-specific object file dumper.
303 static Expected
<std::unique_ptr
<ObjDumper
>>
304 createDumper(const ObjectFile
&Obj
, ScopedPrinter
&Writer
) {
305 if (const COFFObjectFile
*COFFObj
= dyn_cast
<COFFObjectFile
>(&Obj
))
306 return createCOFFDumper(*COFFObj
, Writer
);
308 if (const ELFObjectFileBase
*ELFObj
= dyn_cast
<ELFObjectFileBase
>(&Obj
))
309 return createELFDumper(*ELFObj
, Writer
);
311 if (const MachOObjectFile
*MachOObj
= dyn_cast
<MachOObjectFile
>(&Obj
))
312 return createMachODumper(*MachOObj
, Writer
);
314 if (const WasmObjectFile
*WasmObj
= dyn_cast
<WasmObjectFile
>(&Obj
))
315 return createWasmDumper(*WasmObj
, Writer
);
317 if (const XCOFFObjectFile
*XObj
= dyn_cast
<XCOFFObjectFile
>(&Obj
))
318 return createXCOFFDumper(*XObj
, Writer
);
320 return createStringError(errc::invalid_argument
,
321 "unsupported object file format");
324 /// Dumps the specified object file.
325 static void dumpObject(ObjectFile
&Obj
, ScopedPrinter
&Writer
,
326 const Archive
*A
= nullptr) {
327 std::string FileStr
=
328 A
? Twine(A
->getFileName() + "(" + Obj
.getFileName() + ")").str()
329 : Obj
.getFileName().str();
331 std::string ContentErrString
;
332 if (Error ContentErr
= Obj
.initContent())
333 ContentErrString
= "unable to continue dumping, the file is corrupt: " +
334 toString(std::move(ContentErr
));
337 Expected
<std::unique_ptr
<ObjDumper
>> DumperOrErr
= createDumper(Obj
, Writer
);
339 reportError(DumperOrErr
.takeError(), FileStr
);
340 Dumper
= (*DumperOrErr
).get();
342 Dumper
->printFileSummary(FileStr
, Obj
, opts::InputFilenames
, A
);
344 if (opts::FileHeaders
)
345 Dumper
->printFileHeaders();
347 if (Obj
.isXCOFF() && opts::XCOFFAuxiliaryHeader
)
348 Dumper
->printAuxiliaryHeader();
350 // This is only used for ELF currently. In some cases, when an object is
351 // corrupt (e.g. truncated), we can't dump anything except the file header.
352 if (!ContentErrString
.empty())
353 reportError(createError(ContentErrString
), FileStr
);
355 if (opts::SectionDetails
|| opts::SectionHeaders
) {
356 if (opts::Output
== opts::GNU
&& opts::SectionDetails
)
357 Dumper
->printSectionDetails();
359 Dumper
->printSectionHeaders();
362 if (opts::HashSymbols
)
363 Dumper
->printHashSymbols();
364 if (opts::ProgramHeaders
|| opts::SectionMapping
== cl::BOU_TRUE
)
365 Dumper
->printProgramHeaders(opts::ProgramHeaders
, opts::SectionMapping
);
366 if (opts::DynamicTable
)
367 Dumper
->printDynamicTable();
368 if (opts::NeededLibraries
)
369 Dumper
->printNeededLibraries();
370 if (opts::Relocations
)
371 Dumper
->printRelocations();
373 Dumper
->printDynamicRelocations();
374 if (opts::UnwindInfo
)
375 Dumper
->printUnwindInfo();
376 if (opts::Symbols
|| opts::DynamicSymbols
)
377 Dumper
->printSymbols(opts::Symbols
, opts::DynamicSymbols
);
378 if (!opts::StringDump
.empty())
379 Dumper
->printSectionsAsString(Obj
, opts::StringDump
);
380 if (!opts::HexDump
.empty())
381 Dumper
->printSectionsAsHex(Obj
, opts::HexDump
);
383 Dumper
->printHashTable();
384 if (opts::GnuHashTable
)
385 Dumper
->printGnuHashTable();
386 if (opts::VersionInfo
)
387 Dumper
->printVersionInfo();
388 if (opts::StringTable
)
389 Dumper
->printStringTable();
391 if (opts::DependentLibraries
)
392 Dumper
->printDependentLibs();
393 if (opts::ELFLinkerOptions
)
394 Dumper
->printELFLinkerOptions();
395 if (opts::ArchSpecificInfo
)
396 Dumper
->printArchSpecificInfo();
397 if (opts::SectionGroups
)
398 Dumper
->printGroupSections();
399 if (opts::HashHistogram
)
400 Dumper
->printHashHistograms();
402 Dumper
->printCGProfile();
404 Dumper
->printBBAddrMaps();
406 Dumper
->printAddrsig();
408 Dumper
->printNotes();
411 if (opts::COFFImports
)
412 Dumper
->printCOFFImports();
413 if (opts::COFFExports
)
414 Dumper
->printCOFFExports();
415 if (opts::COFFDirectives
)
416 Dumper
->printCOFFDirectives();
417 if (opts::COFFBaseRelocs
)
418 Dumper
->printCOFFBaseReloc();
419 if (opts::COFFDebugDirectory
)
420 Dumper
->printCOFFDebugDirectory();
421 if (opts::COFFTLSDirectory
)
422 Dumper
->printCOFFTLSDirectory();
423 if (opts::COFFResources
)
424 Dumper
->printCOFFResources();
425 if (opts::COFFLoadConfig
)
426 Dumper
->printCOFFLoadConfig();
428 Dumper
->printCGProfile();
430 Dumper
->printAddrsig();
432 Dumper
->printCodeViewDebugInfo();
433 if (opts::CodeViewMergedTypes
)
434 Dumper
->mergeCodeViewTypes(CVTypes
.IDTable
, CVTypes
.TypeTable
,
435 CVTypes
.GlobalIDTable
, CVTypes
.GlobalTypeTable
,
436 opts::CodeViewEnableGHash
);
439 if (opts::MachODataInCode
)
440 Dumper
->printMachODataInCode();
441 if (opts::MachOIndirectSymbols
)
442 Dumper
->printMachOIndirectSymbols();
443 if (opts::MachOLinkerOptions
)
444 Dumper
->printMachOLinkerOptions();
445 if (opts::MachOSegment
)
446 Dumper
->printMachOSegment();
447 if (opts::MachOVersionMin
)
448 Dumper
->printMachOVersionMin();
449 if (opts::MachODysymtab
)
450 Dumper
->printMachODysymtab();
452 Dumper
->printCGProfile();
454 if (opts::PrintStackMap
)
455 Dumper
->printStackMap();
456 if (opts::PrintStackSizes
)
457 Dumper
->printStackSizes();
460 /// Dumps each object file in \a Arc;
461 static void dumpArchive(const Archive
*Arc
, ScopedPrinter
&Writer
) {
462 Error Err
= Error::success();
463 for (auto &Child
: Arc
->children(Err
)) {
464 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= Child
.getAsBinary();
466 if (auto E
= isNotObjectErrorInvalidFileType(ChildOrErr
.takeError()))
467 reportError(std::move(E
), Arc
->getFileName());
471 Binary
*Bin
= ChildOrErr
->get();
472 if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
))
473 dumpObject(*Obj
, Writer
, Arc
);
474 else if (COFFImportFile
*Imp
= dyn_cast
<COFFImportFile
>(Bin
))
475 dumpCOFFImportFile(Imp
, Writer
);
477 reportWarning(createStringError(errc::invalid_argument
,
479 " has an unsupported file type"),
483 reportError(std::move(Err
), Arc
->getFileName());
486 /// Dumps each object file in \a MachO Universal Binary;
487 static void dumpMachOUniversalBinary(const MachOUniversalBinary
*UBinary
,
488 ScopedPrinter
&Writer
) {
489 for (const MachOUniversalBinary::ObjectForArch
&Obj
: UBinary
->objects()) {
490 Expected
<std::unique_ptr
<MachOObjectFile
>> ObjOrErr
= Obj
.getAsObjectFile();
492 dumpObject(*ObjOrErr
.get(), Writer
);
493 else if (auto E
= isNotObjectErrorInvalidFileType(ObjOrErr
.takeError()))
494 reportError(ObjOrErr
.takeError(), UBinary
->getFileName());
495 else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
= Obj
.getAsArchive())
496 dumpArchive(&*AOrErr
.get(), Writer
);
500 /// Dumps \a WinRes, Windows Resource (.res) file;
501 static void dumpWindowsResourceFile(WindowsResource
*WinRes
,
502 ScopedPrinter
&Printer
) {
503 WindowsRes::Dumper
Dumper(WinRes
, Printer
);
504 if (auto Err
= Dumper
.printData())
505 reportError(std::move(Err
), WinRes
->getFileName());
509 /// Opens \a File and dumps it.
510 static void dumpInput(StringRef File
, ScopedPrinter
&Writer
) {
511 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
512 MemoryBuffer::getFileOrSTDIN(File
, /*IsText=*/false,
513 /*RequiresNullTerminator=*/false);
514 if (std::error_code EC
= FileOrErr
.getError())
515 return reportError(errorCodeToError(EC
), File
);
517 std::unique_ptr
<MemoryBuffer
> &Buffer
= FileOrErr
.get();
518 file_magic Type
= identify_magic(Buffer
->getBuffer());
519 if (Type
== file_magic::bitcode
) {
520 reportWarning(createStringError(errc::invalid_argument
,
521 "bitcode files are not supported"),
526 Expected
<std::unique_ptr
<Binary
>> BinaryOrErr
= createBinary(
527 Buffer
->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
529 reportError(BinaryOrErr
.takeError(), File
);
531 std::unique_ptr
<Binary
> Bin
= std::move(*BinaryOrErr
);
532 if (Archive
*Arc
= dyn_cast
<Archive
>(Bin
.get()))
533 dumpArchive(Arc
, Writer
);
534 else if (MachOUniversalBinary
*UBinary
=
535 dyn_cast
<MachOUniversalBinary
>(Bin
.get()))
536 dumpMachOUniversalBinary(UBinary
, Writer
);
537 else if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
.get()))
538 dumpObject(*Obj
, Writer
);
539 else if (COFFImportFile
*Import
= dyn_cast
<COFFImportFile
>(Bin
.get()))
540 dumpCOFFImportFile(Import
, Writer
);
541 else if (WindowsResource
*WinRes
= dyn_cast
<WindowsResource
>(Bin
.get()))
542 dumpWindowsResourceFile(WinRes
, Writer
);
544 llvm_unreachable("unrecognized file type");
546 CVTypes
.Binaries
.push_back(
547 OwningBinary
<Binary
>(std::move(Bin
), std::move(Buffer
)));
550 std::unique_ptr
<ScopedPrinter
> createWriter() {
551 if (opts::Output
== opts::JSON
)
552 return std::make_unique
<JSONScopedPrinter
>(
553 fouts(), opts::PrettyPrint
? 2 : 0, std::make_unique
<ListScope
>());
554 return std::make_unique
<ScopedPrinter
>(fouts());
557 int main(int argc
, char *argv
[]) {
558 InitLLVM
X(argc
, argv
);
560 StringSaver
Saver(A
);
563 opt::InputArgList Args
=
564 Tbl
.parseArgs(argc
, argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
568 if (Args
.hasArg(OPT_help
)) {
571 (Twine(ToolName
) + " [options] <input object files>").str().c_str(),
572 "LLVM Object Reader");
573 // TODO Replace this with OptTable API once it adds extrahelp support.
574 outs() << "\nPass @FILE as argument to read options from FILE.\n";
577 if (Args
.hasArg(OPT_version
)) {
578 cl::PrintVersionMessage();
582 if (sys::path::stem(argv
[0]).contains("readelf"))
583 opts::Output
= opts::GNU
;
586 // Default to print error if no filename is specified.
587 if (opts::InputFilenames
.empty()) {
588 error("no input files specified");
592 opts::FileHeaders
= true;
593 opts::XCOFFAuxiliaryHeader
= true;
594 opts::ProgramHeaders
= true;
595 opts::SectionHeaders
= true;
596 opts::Symbols
= true;
597 opts::Relocations
= true;
598 opts::DynamicTable
= true;
600 opts::VersionInfo
= true;
601 opts::UnwindInfo
= true;
602 opts::SectionGroups
= true;
603 opts::HashHistogram
= true;
604 if (opts::Output
== opts::LLVM
) {
605 opts::Addrsig
= true;
606 opts::PrintStackSizes
= true;
611 opts::FileHeaders
= true;
612 opts::XCOFFAuxiliaryHeader
= true;
613 opts::ProgramHeaders
= true;
614 opts::SectionHeaders
= true;
617 std::unique_ptr
<ScopedPrinter
> Writer
= createWriter();
619 for (const std::string
&I
: opts::InputFilenames
)
620 dumpInput(I
, *Writer
.get());
622 if (opts::CodeViewMergedTypes
) {
623 if (opts::CodeViewEnableGHash
)
624 dumpCodeViewMergedTypes(*Writer
.get(), CVTypes
.GlobalIDTable
.records(),
625 CVTypes
.GlobalTypeTable
.records());
627 dumpCodeViewMergedTypes(*Writer
.get(), CVTypes
.IDTable
.records(),
628 CVTypes
.TypeTable
.records());