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/LLVMDriver.h"
47 #include "llvm/Support/Path.h"
48 #include "llvm/Support/ScopedPrinter.h"
49 #include "llvm/Support/WithColor.h"
52 using namespace llvm::object
;
55 using namespace llvm::opt
; // for HelpHidden in Opts.inc
57 OPT_INVALID
= 0, // This is not an option ID.
58 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
59 HELPTEXT, METAVAR, VALUES) \
65 #define PREFIX(NAME, VALUE) \
66 static constexpr StringLiteral NAME##_init[] = VALUE; \
67 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
68 std::size(NAME##_init) - 1);
72 static constexpr opt::OptTable::Info InfoTable
[] = {
73 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
74 HELPTEXT, METAVAR, VALUES) \
76 PREFIX, NAME, HELPTEXT, \
77 METAVAR, OPT_##ID, opt::Option::KIND##Class, \
78 PARAM, FLAGS, OPT_##GROUP, \
79 OPT_##ALIAS, ALIASARGS, VALUES},
84 class ReadobjOptTable
: public opt::GenericOptTable
{
86 ReadobjOptTable() : opt::GenericOptTable(InfoTable
) {
87 setGroupedShortOptions(true);
91 enum OutputFormatTy
{ bsd
, sysv
, posix
, darwin
, just_symbols
};
93 enum SortSymbolKeyTy
{
97 // TODO: add ADDRESS, SIZE as needed.
105 static bool ArchSpecificInfo
;
106 static bool BBAddrMap
;
108 static bool CGProfile
;
110 static bool DependentLibraries
;
111 static bool DynRelocs
;
112 static bool DynamicSymbols
;
113 static bool FileHeaders
;
115 static std::vector
<std::string
> HexDump
;
116 static bool PrettyPrint
;
117 static bool PrintStackMap
;
118 static bool PrintStackSizes
;
119 static bool Relocations
;
121 static bool SectionDetails
;
122 static bool SectionHeaders
;
123 bool SectionRelocations
;
125 static std::vector
<std::string
> StringDump
;
126 static bool StringTable
;
128 static bool UnwindInfo
;
129 static cl::boolOrDefault SectionMapping
;
130 static SmallVector
<SortSymbolKeyTy
> SortKeys
;
132 // ELF specific options.
133 static bool DynamicTable
;
134 static bool ELFLinkerOptions
;
135 static bool GnuHashTable
;
136 static bool HashSymbols
;
137 static bool HashTable
;
138 static bool HashHistogram
;
140 static bool NeededLibraries
;
142 static bool ProgramHeaders
;
144 static bool SectionGroups
;
145 static bool VersionInfo
;
147 // Mach-O specific options.
148 static bool MachODataInCode
;
149 static bool MachODysymtab
;
150 static bool MachOIndirectSymbols
;
151 static bool MachOLinkerOptions
;
152 static bool MachOSegment
;
153 static bool MachOVersionMin
;
155 // PE/COFF specific options.
156 static bool CodeView
;
157 static bool CodeViewEnableGHash
;
158 static bool CodeViewMergedTypes
;
159 bool CodeViewSubsectionBytes
;
160 static bool COFFBaseRelocs
;
161 static bool COFFDebugDirectory
;
162 static bool COFFDirectives
;
163 static bool COFFExports
;
164 static bool COFFImports
;
165 static bool COFFLoadConfig
;
166 static bool COFFResources
;
167 static bool COFFTLSDirectory
;
169 // XCOFF specific options.
170 static bool XCOFFAuxiliaryHeader
;
171 static bool XCOFFLoaderSectionHeader
;
172 static bool XCOFFLoaderSectionSymbol
;
173 static bool XCOFFLoaderSectionRelocation
;
174 static bool XCOFFExceptionSection
;
176 OutputStyleTy Output
= OutputStyleTy::LLVM
;
177 static std::vector
<std::string
> InputFilenames
;
180 static StringRef ToolName
;
184 [[noreturn
]] static void error(Twine Msg
) {
185 // Flush the standard output to print the error at a
188 WithColor::error(errs(), ToolName
) << Msg
<< "\n";
192 [[noreturn
]] void reportError(Error Err
, StringRef Input
) {
196 handleAllErrors(createFileError(Input
, std::move(Err
)),
197 [&](const ErrorInfoBase
&EI
) { error(EI
.message()); });
198 llvm_unreachable("error() call should never return");
201 void reportWarning(Error Err
, StringRef Input
) {
206 // Flush the standard output to print the warning at a
210 createFileError(Input
, std::move(Err
)), [&](const ErrorInfoBase
&EI
) {
211 WithColor::warning(errs(), ToolName
) << EI
.message() << "\n";
217 static void parseOptions(const opt::InputArgList
&Args
) {
218 opts::Addrsig
= Args
.hasArg(OPT_addrsig
);
219 opts::All
= Args
.hasArg(OPT_all
);
220 opts::ArchSpecificInfo
= Args
.hasArg(OPT_arch_specific
);
221 opts::BBAddrMap
= Args
.hasArg(OPT_bb_addr_map
);
222 opts::CGProfile
= Args
.hasArg(OPT_cg_profile
);
223 opts::Demangle
= Args
.hasFlag(OPT_demangle
, OPT_no_demangle
, false);
224 opts::DependentLibraries
= Args
.hasArg(OPT_dependent_libraries
);
225 opts::DynRelocs
= Args
.hasArg(OPT_dyn_relocations
);
226 opts::DynamicSymbols
= Args
.hasArg(OPT_dyn_syms
);
227 opts::ExpandRelocs
= Args
.hasArg(OPT_expand_relocs
);
228 opts::FileHeaders
= Args
.hasArg(OPT_file_header
);
229 opts::Headers
= Args
.hasArg(OPT_headers
);
230 opts::HexDump
= Args
.getAllArgValues(OPT_hex_dump_EQ
);
231 opts::Relocations
= Args
.hasArg(OPT_relocs
);
232 opts::SectionData
= Args
.hasArg(OPT_section_data
);
233 opts::SectionDetails
= Args
.hasArg(OPT_section_details
);
234 opts::SectionHeaders
= Args
.hasArg(OPT_section_headers
);
235 opts::SectionRelocations
= Args
.hasArg(OPT_section_relocations
);
236 opts::SectionSymbols
= Args
.hasArg(OPT_section_symbols
);
237 if (Args
.hasArg(OPT_section_mapping
))
238 opts::SectionMapping
= cl::BOU_TRUE
;
239 else if (Args
.hasArg(OPT_section_mapping_EQ_false
))
240 opts::SectionMapping
= cl::BOU_FALSE
;
242 opts::SectionMapping
= cl::BOU_UNSET
;
243 opts::PrintStackSizes
= Args
.hasArg(OPT_stack_sizes
);
244 opts::PrintStackMap
= Args
.hasArg(OPT_stackmap
);
245 opts::StringDump
= Args
.getAllArgValues(OPT_string_dump_EQ
);
246 opts::StringTable
= Args
.hasArg(OPT_string_table
);
247 opts::Symbols
= Args
.hasArg(OPT_symbols
);
248 opts::UnwindInfo
= Args
.hasArg(OPT_unwind
);
250 // ELF specific options.
251 opts::DynamicTable
= Args
.hasArg(OPT_dynamic_table
);
252 opts::ELFLinkerOptions
= Args
.hasArg(OPT_elf_linker_options
);
253 if (Arg
*A
= Args
.getLastArg(OPT_elf_output_style_EQ
)) {
254 std::string OutputStyleChoice
= A
->getValue();
255 opts::Output
= StringSwitch
<opts::OutputStyleTy
>(OutputStyleChoice
)
256 .Case("LLVM", opts::OutputStyleTy::LLVM
)
257 .Case("GNU", opts::OutputStyleTy::GNU
)
258 .Case("JSON", opts::OutputStyleTy::JSON
)
259 .Default(opts::OutputStyleTy::UNKNOWN
);
260 if (opts::Output
== opts::OutputStyleTy::UNKNOWN
) {
261 error("--elf-output-style value should be either 'LLVM', 'GNU', or "
262 "'JSON', but was '" +
263 OutputStyleChoice
+ "'");
266 opts::GnuHashTable
= Args
.hasArg(OPT_gnu_hash_table
);
267 opts::HashSymbols
= Args
.hasArg(OPT_hash_symbols
);
268 opts::HashTable
= Args
.hasArg(OPT_hash_table
);
269 opts::HashHistogram
= Args
.hasArg(OPT_histogram
);
270 opts::Memtag
= Args
.hasArg(OPT_memtag
);
271 opts::NeededLibraries
= Args
.hasArg(OPT_needed_libs
);
272 opts::Notes
= Args
.hasArg(OPT_notes
);
273 opts::PrettyPrint
= Args
.hasArg(OPT_pretty_print
);
274 opts::ProgramHeaders
= Args
.hasArg(OPT_program_headers
);
275 opts::RawRelr
= Args
.hasArg(OPT_raw_relr
);
276 opts::SectionGroups
= Args
.hasArg(OPT_section_groups
);
277 if (Arg
*A
= Args
.getLastArg(OPT_sort_symbols_EQ
)) {
278 std::string SortKeysString
= A
->getValue();
279 for (StringRef KeyStr
: llvm::split(A
->getValue(), ",")) {
280 SortSymbolKeyTy KeyType
= StringSwitch
<SortSymbolKeyTy
>(KeyStr
)
281 .Case("name", SortSymbolKeyTy::NAME
)
282 .Case("type", SortSymbolKeyTy::TYPE
)
283 .Default(SortSymbolKeyTy::UNKNOWN
);
284 if (KeyType
== SortSymbolKeyTy::UNKNOWN
)
285 error("--sort-symbols value should be 'name' or 'type', but was '" +
286 Twine(KeyStr
) + "'");
287 opts::SortKeys
.push_back(KeyType
);
290 opts::VersionInfo
= Args
.hasArg(OPT_version_info
);
292 // Mach-O specific options.
293 opts::MachODataInCode
= Args
.hasArg(OPT_macho_data_in_code
);
294 opts::MachODysymtab
= Args
.hasArg(OPT_macho_dysymtab
);
295 opts::MachOIndirectSymbols
= Args
.hasArg(OPT_macho_indirect_symbols
);
296 opts::MachOLinkerOptions
= Args
.hasArg(OPT_macho_linker_options
);
297 opts::MachOSegment
= Args
.hasArg(OPT_macho_segment
);
298 opts::MachOVersionMin
= Args
.hasArg(OPT_macho_version_min
);
300 // PE/COFF specific options.
301 opts::CodeView
= Args
.hasArg(OPT_codeview
);
302 opts::CodeViewEnableGHash
= Args
.hasArg(OPT_codeview_ghash
);
303 opts::CodeViewMergedTypes
= Args
.hasArg(OPT_codeview_merged_types
);
304 opts::CodeViewSubsectionBytes
= Args
.hasArg(OPT_codeview_subsection_bytes
);
305 opts::COFFBaseRelocs
= Args
.hasArg(OPT_coff_basereloc
);
306 opts::COFFDebugDirectory
= Args
.hasArg(OPT_coff_debug_directory
);
307 opts::COFFDirectives
= Args
.hasArg(OPT_coff_directives
);
308 opts::COFFExports
= Args
.hasArg(OPT_coff_exports
);
309 opts::COFFImports
= Args
.hasArg(OPT_coff_imports
);
310 opts::COFFLoadConfig
= Args
.hasArg(OPT_coff_load_config
);
311 opts::COFFResources
= Args
.hasArg(OPT_coff_resources
);
312 opts::COFFTLSDirectory
= Args
.hasArg(OPT_coff_tls_directory
);
314 // XCOFF specific options.
315 opts::XCOFFAuxiliaryHeader
= Args
.hasArg(OPT_auxiliary_header
);
316 opts::XCOFFLoaderSectionHeader
= Args
.hasArg(OPT_loader_section_header
);
317 opts::XCOFFLoaderSectionSymbol
= Args
.hasArg(OPT_loader_section_symbols
);
318 opts::XCOFFLoaderSectionRelocation
=
319 Args
.hasArg(OPT_loader_section_relocations
);
320 opts::XCOFFExceptionSection
= Args
.hasArg(OPT_exception_section
);
322 opts::InputFilenames
= Args
.getAllArgValues(OPT_INPUT
);
326 struct ReadObjTypeTableBuilder
{
327 ReadObjTypeTableBuilder()
328 : IDTable(Allocator
), TypeTable(Allocator
), GlobalIDTable(Allocator
),
329 GlobalTypeTable(Allocator
) {}
331 llvm::BumpPtrAllocator Allocator
;
332 llvm::codeview::MergingTypeTableBuilder IDTable
;
333 llvm::codeview::MergingTypeTableBuilder TypeTable
;
334 llvm::codeview::GlobalTypeTableBuilder GlobalIDTable
;
335 llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable
;
336 std::vector
<OwningBinary
<Binary
>> Binaries
;
339 static ReadObjTypeTableBuilder CVTypes
;
341 /// Creates an format-specific object file dumper.
342 static Expected
<std::unique_ptr
<ObjDumper
>>
343 createDumper(const ObjectFile
&Obj
, ScopedPrinter
&Writer
) {
344 if (const COFFObjectFile
*COFFObj
= dyn_cast
<COFFObjectFile
>(&Obj
))
345 return createCOFFDumper(*COFFObj
, Writer
);
347 if (const ELFObjectFileBase
*ELFObj
= dyn_cast
<ELFObjectFileBase
>(&Obj
))
348 return createELFDumper(*ELFObj
, Writer
);
350 if (const MachOObjectFile
*MachOObj
= dyn_cast
<MachOObjectFile
>(&Obj
))
351 return createMachODumper(*MachOObj
, Writer
);
353 if (const WasmObjectFile
*WasmObj
= dyn_cast
<WasmObjectFile
>(&Obj
))
354 return createWasmDumper(*WasmObj
, Writer
);
356 if (const XCOFFObjectFile
*XObj
= dyn_cast
<XCOFFObjectFile
>(&Obj
))
357 return createXCOFFDumper(*XObj
, Writer
);
359 return createStringError(errc::invalid_argument
,
360 "unsupported object file format");
363 /// Dumps the specified object file.
364 static void dumpObject(ObjectFile
&Obj
, ScopedPrinter
&Writer
,
365 const Archive
*A
= nullptr) {
366 std::string FileStr
=
367 A
? Twine(A
->getFileName() + "(" + Obj
.getFileName() + ")").str()
368 : Obj
.getFileName().str();
370 std::string ContentErrString
;
371 if (Error ContentErr
= Obj
.initContent())
372 ContentErrString
= "unable to continue dumping, the file is corrupt: " +
373 toString(std::move(ContentErr
));
376 std::optional
<SymbolComparator
> SymComp
;
377 Expected
<std::unique_ptr
<ObjDumper
>> DumperOrErr
= createDumper(Obj
, Writer
);
379 reportError(DumperOrErr
.takeError(), FileStr
);
380 Dumper
= (*DumperOrErr
).get();
382 if (!opts::SortKeys
.empty()) {
383 if (Dumper
->canCompareSymbols()) {
384 SymComp
= SymbolComparator();
385 for (SortSymbolKeyTy Key
: opts::SortKeys
) {
388 SymComp
->addPredicate([Dumper
](SymbolRef LHS
, SymbolRef RHS
) {
389 return Dumper
->compareSymbolsByName(LHS
, RHS
);
393 SymComp
->addPredicate([Dumper
](SymbolRef LHS
, SymbolRef RHS
) {
394 return Dumper
->compareSymbolsByType(LHS
, RHS
);
398 llvm_unreachable("Unsupported sort key");
403 reportWarning(createStringError(
404 errc::invalid_argument
,
405 "--sort-symbols is not supported yet for this format"),
409 Dumper
->printFileSummary(FileStr
, Obj
, opts::InputFilenames
, A
);
411 if (opts::FileHeaders
)
412 Dumper
->printFileHeaders();
414 // Auxiliary header in XOCFF is right after the file header, so print the data
416 if (Obj
.isXCOFF() && opts::XCOFFAuxiliaryHeader
)
417 Dumper
->printAuxiliaryHeader();
419 // This is only used for ELF currently. In some cases, when an object is
420 // corrupt (e.g. truncated), we can't dump anything except the file header.
421 if (!ContentErrString
.empty())
422 reportError(createError(ContentErrString
), FileStr
);
424 if (opts::SectionDetails
|| opts::SectionHeaders
) {
425 if (opts::Output
== opts::GNU
&& opts::SectionDetails
)
426 Dumper
->printSectionDetails();
428 Dumper
->printSectionHeaders();
431 if (opts::HashSymbols
)
432 Dumper
->printHashSymbols();
433 if (opts::ProgramHeaders
|| opts::SectionMapping
== cl::BOU_TRUE
)
434 Dumper
->printProgramHeaders(opts::ProgramHeaders
, opts::SectionMapping
);
435 if (opts::DynamicTable
)
436 Dumper
->printDynamicTable();
437 if (opts::NeededLibraries
)
438 Dumper
->printNeededLibraries();
439 if (opts::Relocations
)
440 Dumper
->printRelocations();
442 Dumper
->printDynamicRelocations();
443 if (opts::UnwindInfo
)
444 Dumper
->printUnwindInfo();
445 if (opts::Symbols
|| opts::DynamicSymbols
)
446 Dumper
->printSymbols(opts::Symbols
, opts::DynamicSymbols
, SymComp
);
447 if (!opts::StringDump
.empty())
448 Dumper
->printSectionsAsString(Obj
, opts::StringDump
);
449 if (!opts::HexDump
.empty())
450 Dumper
->printSectionsAsHex(Obj
, opts::HexDump
);
452 Dumper
->printHashTable();
453 if (opts::GnuHashTable
)
454 Dumper
->printGnuHashTable();
455 if (opts::VersionInfo
)
456 Dumper
->printVersionInfo();
457 if (opts::StringTable
)
458 Dumper
->printStringTable();
460 if (opts::DependentLibraries
)
461 Dumper
->printDependentLibs();
462 if (opts::ELFLinkerOptions
)
463 Dumper
->printELFLinkerOptions();
464 if (opts::ArchSpecificInfo
)
465 Dumper
->printArchSpecificInfo();
466 if (opts::SectionGroups
)
467 Dumper
->printGroupSections();
468 if (opts::HashHistogram
)
469 Dumper
->printHashHistograms();
471 Dumper
->printCGProfile();
473 Dumper
->printBBAddrMaps();
475 Dumper
->printAddrsig();
477 Dumper
->printNotes();
479 Dumper
->printMemtag();
482 if (opts::COFFImports
)
483 Dumper
->printCOFFImports();
484 if (opts::COFFExports
)
485 Dumper
->printCOFFExports();
486 if (opts::COFFDirectives
)
487 Dumper
->printCOFFDirectives();
488 if (opts::COFFBaseRelocs
)
489 Dumper
->printCOFFBaseReloc();
490 if (opts::COFFDebugDirectory
)
491 Dumper
->printCOFFDebugDirectory();
492 if (opts::COFFTLSDirectory
)
493 Dumper
->printCOFFTLSDirectory();
494 if (opts::COFFResources
)
495 Dumper
->printCOFFResources();
496 if (opts::COFFLoadConfig
)
497 Dumper
->printCOFFLoadConfig();
499 Dumper
->printCGProfile();
501 Dumper
->printAddrsig();
503 Dumper
->printCodeViewDebugInfo();
504 if (opts::CodeViewMergedTypes
)
505 Dumper
->mergeCodeViewTypes(CVTypes
.IDTable
, CVTypes
.TypeTable
,
506 CVTypes
.GlobalIDTable
, CVTypes
.GlobalTypeTable
,
507 opts::CodeViewEnableGHash
);
510 if (opts::MachODataInCode
)
511 Dumper
->printMachODataInCode();
512 if (opts::MachOIndirectSymbols
)
513 Dumper
->printMachOIndirectSymbols();
514 if (opts::MachOLinkerOptions
)
515 Dumper
->printMachOLinkerOptions();
516 if (opts::MachOSegment
)
517 Dumper
->printMachOSegment();
518 if (opts::MachOVersionMin
)
519 Dumper
->printMachOVersionMin();
520 if (opts::MachODysymtab
)
521 Dumper
->printMachODysymtab();
523 Dumper
->printCGProfile();
527 if (opts::XCOFFLoaderSectionHeader
|| opts::XCOFFLoaderSectionSymbol
||
528 opts::XCOFFLoaderSectionRelocation
)
529 Dumper
->printLoaderSection(opts::XCOFFLoaderSectionHeader
,
530 opts::XCOFFLoaderSectionSymbol
,
531 opts::XCOFFLoaderSectionRelocation
);
533 if (opts::XCOFFExceptionSection
)
534 Dumper
->printExceptionSection();
537 if (opts::PrintStackMap
)
538 Dumper
->printStackMap();
539 if (opts::PrintStackSizes
)
540 Dumper
->printStackSizes();
543 /// Dumps each object file in \a Arc;
544 static void dumpArchive(const Archive
*Arc
, ScopedPrinter
&Writer
) {
545 Error Err
= Error::success();
546 for (auto &Child
: Arc
->children(Err
)) {
547 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= Child
.getAsBinary();
549 if (auto E
= isNotObjectErrorInvalidFileType(ChildOrErr
.takeError()))
550 reportError(std::move(E
), Arc
->getFileName());
554 Binary
*Bin
= ChildOrErr
->get();
555 if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
))
556 dumpObject(*Obj
, Writer
, Arc
);
557 else if (COFFImportFile
*Imp
= dyn_cast
<COFFImportFile
>(Bin
))
558 dumpCOFFImportFile(Imp
, Writer
);
560 reportWarning(createStringError(errc::invalid_argument
,
562 " has an unsupported file type"),
566 reportError(std::move(Err
), Arc
->getFileName());
569 /// Dumps each object file in \a MachO Universal Binary;
570 static void dumpMachOUniversalBinary(const MachOUniversalBinary
*UBinary
,
571 ScopedPrinter
&Writer
) {
572 for (const MachOUniversalBinary::ObjectForArch
&Obj
: UBinary
->objects()) {
573 Expected
<std::unique_ptr
<MachOObjectFile
>> ObjOrErr
= Obj
.getAsObjectFile();
575 dumpObject(*ObjOrErr
.get(), Writer
);
576 else if (auto E
= isNotObjectErrorInvalidFileType(ObjOrErr
.takeError()))
577 reportError(ObjOrErr
.takeError(), UBinary
->getFileName());
578 else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
= Obj
.getAsArchive())
579 dumpArchive(&*AOrErr
.get(), Writer
);
583 /// Dumps \a WinRes, Windows Resource (.res) file;
584 static void dumpWindowsResourceFile(WindowsResource
*WinRes
,
585 ScopedPrinter
&Printer
) {
586 WindowsRes::Dumper
Dumper(WinRes
, Printer
);
587 if (auto Err
= Dumper
.printData())
588 reportError(std::move(Err
), WinRes
->getFileName());
592 /// Opens \a File and dumps it.
593 static void dumpInput(StringRef File
, ScopedPrinter
&Writer
) {
594 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
595 MemoryBuffer::getFileOrSTDIN(File
, /*IsText=*/false,
596 /*RequiresNullTerminator=*/false);
597 if (std::error_code EC
= FileOrErr
.getError())
598 return reportError(errorCodeToError(EC
), File
);
600 std::unique_ptr
<MemoryBuffer
> &Buffer
= FileOrErr
.get();
601 file_magic Type
= identify_magic(Buffer
->getBuffer());
602 if (Type
== file_magic::bitcode
) {
603 reportWarning(createStringError(errc::invalid_argument
,
604 "bitcode files are not supported"),
609 Expected
<std::unique_ptr
<Binary
>> BinaryOrErr
= createBinary(
610 Buffer
->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
612 reportError(BinaryOrErr
.takeError(), File
);
614 std::unique_ptr
<Binary
> Bin
= std::move(*BinaryOrErr
);
615 if (Archive
*Arc
= dyn_cast
<Archive
>(Bin
.get()))
616 dumpArchive(Arc
, Writer
);
617 else if (MachOUniversalBinary
*UBinary
=
618 dyn_cast
<MachOUniversalBinary
>(Bin
.get()))
619 dumpMachOUniversalBinary(UBinary
, Writer
);
620 else if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
.get()))
621 dumpObject(*Obj
, Writer
);
622 else if (COFFImportFile
*Import
= dyn_cast
<COFFImportFile
>(Bin
.get()))
623 dumpCOFFImportFile(Import
, Writer
);
624 else if (WindowsResource
*WinRes
= dyn_cast
<WindowsResource
>(Bin
.get()))
625 dumpWindowsResourceFile(WinRes
, Writer
);
627 llvm_unreachable("unrecognized file type");
629 CVTypes
.Binaries
.push_back(
630 OwningBinary
<Binary
>(std::move(Bin
), std::move(Buffer
)));
633 std::unique_ptr
<ScopedPrinter
> createWriter() {
634 if (opts::Output
== opts::JSON
)
635 return std::make_unique
<JSONScopedPrinter
>(
636 fouts(), opts::PrettyPrint
? 2 : 0, std::make_unique
<ListScope
>());
637 return std::make_unique
<ScopedPrinter
>(fouts());
640 int llvm_readobj_main(int argc
, char **argv
, const llvm::ToolContext
&) {
641 InitLLVM
X(argc
, argv
);
643 StringSaver
Saver(A
);
646 opt::InputArgList Args
=
647 Tbl
.parseArgs(argc
, argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
651 if (Args
.hasArg(OPT_help
)) {
654 (Twine(ToolName
) + " [options] <input object files>").str().c_str(),
655 "LLVM Object Reader");
656 // TODO Replace this with OptTable API once it adds extrahelp support.
657 outs() << "\nPass @FILE as argument to read options from FILE.\n";
660 if (Args
.hasArg(OPT_version
)) {
661 cl::PrintVersionMessage();
665 if (sys::path::stem(argv
[0]).contains("readelf"))
666 opts::Output
= opts::GNU
;
669 // Default to print error if no filename is specified.
670 if (opts::InputFilenames
.empty()) {
671 error("no input files specified");
675 opts::FileHeaders
= true;
676 opts::XCOFFAuxiliaryHeader
= true;
677 opts::ProgramHeaders
= true;
678 opts::SectionHeaders
= true;
679 opts::Symbols
= true;
680 opts::Relocations
= true;
681 opts::DynamicTable
= true;
683 opts::VersionInfo
= true;
684 opts::UnwindInfo
= true;
685 opts::SectionGroups
= true;
686 opts::HashHistogram
= true;
687 if (opts::Output
== opts::LLVM
) {
688 opts::Addrsig
= true;
689 opts::PrintStackSizes
= true;
695 opts::FileHeaders
= true;
696 opts::XCOFFAuxiliaryHeader
= true;
697 opts::ProgramHeaders
= true;
698 opts::SectionHeaders
= true;
701 std::unique_ptr
<ScopedPrinter
> Writer
= createWriter();
703 for (const std::string
&I
: opts::InputFilenames
)
704 dumpInput(I
, *Writer
.get());
706 if (opts::CodeViewMergedTypes
) {
707 if (opts::CodeViewEnableGHash
)
708 dumpCodeViewMergedTypes(*Writer
.get(), CVTypes
.GlobalIDTable
.records(),
709 CVTypes
.GlobalTypeTable
.records());
711 dumpCodeViewMergedTypes(*Writer
.get(), CVTypes
.IDTable
.records(),
712 CVTypes
.TypeTable
.records());