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/LLVMDriver.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(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
62 #define PREFIX(NAME, VALUE) \
63 static constexpr StringLiteral NAME##_init[] = VALUE; \
64 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
65 std::size(NAME##_init) - 1);
69 static constexpr opt::OptTable::Info InfoTable
[] = {
70 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
75 class ReadobjOptTable
: public opt::GenericOptTable
{
77 ReadobjOptTable() : opt::GenericOptTable(InfoTable
) {
78 setGroupedShortOptions(true);
82 enum OutputFormatTy
{ bsd
, sysv
, posix
, darwin
, just_symbols
};
84 enum SortSymbolKeyTy
{
88 // TODO: add ADDRESS, SIZE as needed.
96 static bool ArchSpecificInfo
;
97 static bool BBAddrMap
;
98 static bool PrettyPGOAnalysisMap
;
100 static bool CGProfile
;
101 static bool Decompress
;
103 static bool DependentLibraries
;
104 static bool DynRelocs
;
105 static bool DynamicSymbols
;
106 static bool ExtraSymInfo
;
107 static bool FileHeaders
;
109 static std::vector
<std::string
> HexDump
;
110 static bool PrettyPrint
;
111 static bool PrintStackMap
;
112 static bool PrintStackSizes
;
113 static bool Relocations
;
115 static bool SectionDetails
;
116 static bool SectionHeaders
;
117 bool SectionRelocations
;
119 static std::vector
<std::string
> StringDump
;
120 static bool StringTable
;
122 static bool UnwindInfo
;
123 static cl::boolOrDefault SectionMapping
;
124 static SmallVector
<SortSymbolKeyTy
> SortKeys
;
126 // ELF specific options.
127 static bool DynamicTable
;
128 static bool ELFLinkerOptions
;
129 static bool GnuHashTable
;
130 static bool HashSymbols
;
131 static bool HashTable
;
132 static bool HashHistogram
;
134 static bool NeededLibraries
;
136 static bool ProgramHeaders
;
137 static bool SectionGroups
;
138 static bool VersionInfo
;
140 // Mach-O specific options.
141 static bool MachODataInCode
;
142 static bool MachODysymtab
;
143 static bool MachOIndirectSymbols
;
144 static bool MachOLinkerOptions
;
145 static bool MachOSegment
;
146 static bool MachOVersionMin
;
148 // PE/COFF specific options.
149 static bool CodeView
;
150 static bool CodeViewEnableGHash
;
151 static bool CodeViewMergedTypes
;
152 bool CodeViewSubsectionBytes
;
153 static bool COFFBaseRelocs
;
154 static bool COFFDebugDirectory
;
155 static bool COFFDirectives
;
156 static bool COFFExports
;
157 static bool COFFImports
;
158 static bool COFFLoadConfig
;
159 static bool COFFResources
;
160 static bool COFFTLSDirectory
;
162 // XCOFF specific options.
163 static bool XCOFFAuxiliaryHeader
;
164 static bool XCOFFLoaderSectionHeader
;
165 static bool XCOFFLoaderSectionSymbol
;
166 static bool XCOFFLoaderSectionRelocation
;
167 static bool XCOFFExceptionSection
;
169 OutputStyleTy Output
= OutputStyleTy::LLVM
;
170 static std::vector
<std::string
> InputFilenames
;
173 static StringRef ToolName
;
177 [[noreturn
]] static void error(Twine Msg
) {
178 // Flush the standard output to print the error at a
181 WithColor::error(errs(), ToolName
) << Msg
<< "\n";
185 [[noreturn
]] void reportError(Error Err
, StringRef Input
) {
189 handleAllErrors(createFileError(Input
, std::move(Err
)),
190 [&](const ErrorInfoBase
&EI
) { error(EI
.message()); });
191 llvm_unreachable("error() call should never return");
194 void reportWarning(Error Err
, StringRef Input
) {
199 // Flush the standard output to print the warning at a
203 createFileError(Input
, std::move(Err
)), [&](const ErrorInfoBase
&EI
) {
204 WithColor::warning(errs(), ToolName
) << EI
.message() << "\n";
210 static void parseOptions(const opt::InputArgList
&Args
) {
211 opts::Addrsig
= Args
.hasArg(OPT_addrsig
);
212 opts::All
= Args
.hasArg(OPT_all
);
213 opts::ArchSpecificInfo
= Args
.hasArg(OPT_arch_specific
);
214 opts::BBAddrMap
= Args
.hasArg(OPT_bb_addr_map
);
215 opts::PrettyPGOAnalysisMap
= Args
.hasArg(OPT_pretty_pgo_analysis_map
);
216 if (opts::PrettyPGOAnalysisMap
&& !opts::BBAddrMap
)
217 WithColor::warning(errs(), ToolName
)
218 << "--bb-addr-map must be enabled for --pretty-pgo-analysis-map to "
220 opts::CGProfile
= Args
.hasArg(OPT_cg_profile
);
221 opts::Decompress
= Args
.hasArg(OPT_decompress
);
222 opts::Demangle
= Args
.hasFlag(OPT_demangle
, OPT_no_demangle
, false);
223 opts::DependentLibraries
= Args
.hasArg(OPT_dependent_libraries
);
224 opts::DynRelocs
= Args
.hasArg(OPT_dyn_relocations
);
225 opts::DynamicSymbols
= Args
.hasArg(OPT_dyn_syms
);
226 opts::ExpandRelocs
= Args
.hasArg(OPT_expand_relocs
);
227 opts::ExtraSymInfo
= Args
.hasArg(OPT_extra_sym_info
);
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::SectionGroups
= Args
.hasArg(OPT_section_groups
);
276 if (Arg
*A
= Args
.getLastArg(OPT_sort_symbols_EQ
)) {
277 std::string SortKeysString
= A
->getValue();
278 for (StringRef KeyStr
: llvm::split(A
->getValue(), ",")) {
279 SortSymbolKeyTy KeyType
= StringSwitch
<SortSymbolKeyTy
>(KeyStr
)
280 .Case("name", SortSymbolKeyTy::NAME
)
281 .Case("type", SortSymbolKeyTy::TYPE
)
282 .Default(SortSymbolKeyTy::UNKNOWN
);
283 if (KeyType
== SortSymbolKeyTy::UNKNOWN
)
284 error("--sort-symbols value should be 'name' or 'type', but was '" +
285 Twine(KeyStr
) + "'");
286 opts::SortKeys
.push_back(KeyType
);
289 opts::VersionInfo
= Args
.hasArg(OPT_version_info
);
291 // Mach-O specific options.
292 opts::MachODataInCode
= Args
.hasArg(OPT_macho_data_in_code
);
293 opts::MachODysymtab
= Args
.hasArg(OPT_macho_dysymtab
);
294 opts::MachOIndirectSymbols
= Args
.hasArg(OPT_macho_indirect_symbols
);
295 opts::MachOLinkerOptions
= Args
.hasArg(OPT_macho_linker_options
);
296 opts::MachOSegment
= Args
.hasArg(OPT_macho_segment
);
297 opts::MachOVersionMin
= Args
.hasArg(OPT_macho_version_min
);
299 // PE/COFF specific options.
300 opts::CodeView
= Args
.hasArg(OPT_codeview
);
301 opts::CodeViewEnableGHash
= Args
.hasArg(OPT_codeview_ghash
);
302 opts::CodeViewMergedTypes
= Args
.hasArg(OPT_codeview_merged_types
);
303 opts::CodeViewSubsectionBytes
= Args
.hasArg(OPT_codeview_subsection_bytes
);
304 opts::COFFBaseRelocs
= Args
.hasArg(OPT_coff_basereloc
);
305 opts::COFFDebugDirectory
= Args
.hasArg(OPT_coff_debug_directory
);
306 opts::COFFDirectives
= Args
.hasArg(OPT_coff_directives
);
307 opts::COFFExports
= Args
.hasArg(OPT_coff_exports
);
308 opts::COFFImports
= Args
.hasArg(OPT_coff_imports
);
309 opts::COFFLoadConfig
= Args
.hasArg(OPT_coff_load_config
);
310 opts::COFFResources
= Args
.hasArg(OPT_coff_resources
);
311 opts::COFFTLSDirectory
= Args
.hasArg(OPT_coff_tls_directory
);
313 // XCOFF specific options.
314 opts::XCOFFAuxiliaryHeader
= Args
.hasArg(OPT_auxiliary_header
);
315 opts::XCOFFLoaderSectionHeader
= Args
.hasArg(OPT_loader_section_header
);
316 opts::XCOFFLoaderSectionSymbol
= Args
.hasArg(OPT_loader_section_symbols
);
317 opts::XCOFFLoaderSectionRelocation
=
318 Args
.hasArg(OPT_loader_section_relocations
);
319 opts::XCOFFExceptionSection
= Args
.hasArg(OPT_exception_section
);
321 opts::InputFilenames
= Args
.getAllArgValues(OPT_INPUT
);
325 struct ReadObjTypeTableBuilder
{
326 ReadObjTypeTableBuilder()
327 : IDTable(Allocator
), TypeTable(Allocator
), GlobalIDTable(Allocator
),
328 GlobalTypeTable(Allocator
) {}
330 llvm::BumpPtrAllocator Allocator
;
331 llvm::codeview::MergingTypeTableBuilder IDTable
;
332 llvm::codeview::MergingTypeTableBuilder TypeTable
;
333 llvm::codeview::GlobalTypeTableBuilder GlobalIDTable
;
334 llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable
;
335 std::vector
<OwningBinary
<Binary
>> Binaries
;
338 static ReadObjTypeTableBuilder CVTypes
;
340 /// Creates an format-specific object file dumper.
341 static Expected
<std::unique_ptr
<ObjDumper
>>
342 createDumper(const ObjectFile
&Obj
, ScopedPrinter
&Writer
) {
343 if (const COFFObjectFile
*COFFObj
= dyn_cast
<COFFObjectFile
>(&Obj
))
344 return createCOFFDumper(*COFFObj
, Writer
);
346 if (const ELFObjectFileBase
*ELFObj
= dyn_cast
<ELFObjectFileBase
>(&Obj
))
347 return createELFDumper(*ELFObj
, Writer
);
349 if (const MachOObjectFile
*MachOObj
= dyn_cast
<MachOObjectFile
>(&Obj
))
350 return createMachODumper(*MachOObj
, Writer
);
352 if (const WasmObjectFile
*WasmObj
= dyn_cast
<WasmObjectFile
>(&Obj
))
353 return createWasmDumper(*WasmObj
, Writer
);
355 if (const XCOFFObjectFile
*XObj
= dyn_cast
<XCOFFObjectFile
>(&Obj
))
356 return createXCOFFDumper(*XObj
, Writer
);
358 return createStringError(errc::invalid_argument
,
359 "unsupported object file format");
362 /// Dumps the specified object file.
363 static void dumpObject(ObjectFile
&Obj
, ScopedPrinter
&Writer
,
364 const Archive
*A
= nullptr) {
365 std::string FileStr
=
366 A
? Twine(A
->getFileName() + "(" + Obj
.getFileName() + ")").str()
367 : Obj
.getFileName().str();
369 std::string ContentErrString
;
370 if (Error ContentErr
= Obj
.initContent())
371 ContentErrString
= "unable to continue dumping, the file is corrupt: " +
372 toString(std::move(ContentErr
));
375 std::optional
<SymbolComparator
> SymComp
;
376 Expected
<std::unique_ptr
<ObjDumper
>> DumperOrErr
= createDumper(Obj
, Writer
);
378 reportError(DumperOrErr
.takeError(), FileStr
);
379 Dumper
= (*DumperOrErr
).get();
381 if (!opts::SortKeys
.empty()) {
382 if (Dumper
->canCompareSymbols()) {
383 SymComp
= SymbolComparator();
384 for (SortSymbolKeyTy Key
: opts::SortKeys
) {
387 SymComp
->addPredicate([Dumper
](SymbolRef LHS
, SymbolRef RHS
) {
388 return Dumper
->compareSymbolsByName(LHS
, RHS
);
392 SymComp
->addPredicate([Dumper
](SymbolRef LHS
, SymbolRef RHS
) {
393 return Dumper
->compareSymbolsByType(LHS
, RHS
);
397 llvm_unreachable("Unsupported sort key");
402 reportWarning(createStringError(
403 errc::invalid_argument
,
404 "--sort-symbols is not supported yet for this format"),
408 Dumper
->printFileSummary(FileStr
, Obj
, opts::InputFilenames
, A
);
410 if (opts::FileHeaders
)
411 Dumper
->printFileHeaders();
413 // Auxiliary header in XOCFF is right after the file header, so print the data
415 if (Obj
.isXCOFF() && opts::XCOFFAuxiliaryHeader
)
416 Dumper
->printAuxiliaryHeader();
418 // This is only used for ELF currently. In some cases, when an object is
419 // corrupt (e.g. truncated), we can't dump anything except the file header.
420 if (!ContentErrString
.empty())
421 reportError(createError(ContentErrString
), FileStr
);
423 if (opts::SectionDetails
|| opts::SectionHeaders
) {
424 if (opts::Output
== opts::GNU
&& opts::SectionDetails
)
425 Dumper
->printSectionDetails();
427 Dumper
->printSectionHeaders();
430 if (opts::HashSymbols
)
431 Dumper
->printHashSymbols();
432 if (opts::ProgramHeaders
|| opts::SectionMapping
== cl::BOU_TRUE
)
433 Dumper
->printProgramHeaders(opts::ProgramHeaders
, opts::SectionMapping
);
434 if (opts::DynamicTable
)
435 Dumper
->printDynamicTable();
436 if (opts::NeededLibraries
)
437 Dumper
->printNeededLibraries();
438 if (opts::Relocations
)
439 Dumper
->printRelocations();
441 Dumper
->printDynamicRelocations();
442 if (opts::UnwindInfo
)
443 Dumper
->printUnwindInfo();
444 if (opts::Symbols
|| opts::DynamicSymbols
)
445 Dumper
->printSymbols(opts::Symbols
, opts::DynamicSymbols
,
446 opts::ExtraSymInfo
, SymComp
);
447 if (!opts::StringDump
.empty())
448 Dumper
->printSectionsAsString(Obj
, opts::StringDump
, opts::Decompress
);
449 if (!opts::HexDump
.empty())
450 Dumper
->printSectionsAsHex(Obj
, opts::HexDump
, opts::Decompress
);
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(opts::PrettyPGOAnalysisMap
);
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 COFF file;
584 static void dumpCOFFObject(COFFObjectFile
*Obj
, ScopedPrinter
&Writer
) {
585 dumpObject(*Obj
, Writer
);
587 // Dump a hybrid object when available.
588 std::unique_ptr
<MemoryBuffer
> HybridView
= Obj
->getHybridObjectView();
591 Expected
<std::unique_ptr
<COFFObjectFile
>> HybridObjOrErr
=
592 COFFObjectFile::create(*HybridView
);
594 reportError(HybridObjOrErr
.takeError(), Obj
->getFileName().str());
595 DictScope
D(Writer
, "HybridObject");
596 dumpObject(**HybridObjOrErr
, Writer
);
599 /// Dumps \a WinRes, Windows Resource (.res) file;
600 static void dumpWindowsResourceFile(WindowsResource
*WinRes
,
601 ScopedPrinter
&Printer
) {
602 WindowsRes::Dumper
Dumper(WinRes
, Printer
);
603 if (auto Err
= Dumper
.printData())
604 reportError(std::move(Err
), WinRes
->getFileName());
608 /// Opens \a File and dumps it.
609 static void dumpInput(StringRef File
, ScopedPrinter
&Writer
) {
610 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
611 MemoryBuffer::getFileOrSTDIN(File
, /*IsText=*/false,
612 /*RequiresNullTerminator=*/false);
613 if (std::error_code EC
= FileOrErr
.getError())
614 return reportError(errorCodeToError(EC
), File
);
616 std::unique_ptr
<MemoryBuffer
> &Buffer
= FileOrErr
.get();
617 file_magic Type
= identify_magic(Buffer
->getBuffer());
618 if (Type
== file_magic::bitcode
) {
619 reportWarning(createStringError(errc::invalid_argument
,
620 "bitcode files are not supported"),
625 Expected
<std::unique_ptr
<Binary
>> BinaryOrErr
= createBinary(
626 Buffer
->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
628 reportError(BinaryOrErr
.takeError(), File
);
630 std::unique_ptr
<Binary
> Bin
= std::move(*BinaryOrErr
);
631 if (Archive
*Arc
= dyn_cast
<Archive
>(Bin
.get()))
632 dumpArchive(Arc
, Writer
);
633 else if (MachOUniversalBinary
*UBinary
=
634 dyn_cast
<MachOUniversalBinary
>(Bin
.get()))
635 dumpMachOUniversalBinary(UBinary
, Writer
);
636 else if (COFFObjectFile
*Obj
= dyn_cast
<COFFObjectFile
>(Bin
.get()))
637 dumpCOFFObject(Obj
, Writer
);
638 else if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
.get()))
639 dumpObject(*Obj
, Writer
);
640 else if (COFFImportFile
*Import
= dyn_cast
<COFFImportFile
>(Bin
.get()))
641 dumpCOFFImportFile(Import
, Writer
);
642 else if (WindowsResource
*WinRes
= dyn_cast
<WindowsResource
>(Bin
.get()))
643 dumpWindowsResourceFile(WinRes
, Writer
);
645 llvm_unreachable("unrecognized file type");
647 CVTypes
.Binaries
.push_back(
648 OwningBinary
<Binary
>(std::move(Bin
), std::move(Buffer
)));
651 std::unique_ptr
<ScopedPrinter
> createWriter() {
652 if (opts::Output
== opts::JSON
)
653 return std::make_unique
<JSONScopedPrinter
>(
654 fouts(), opts::PrettyPrint
? 2 : 0, std::make_unique
<ListScope
>());
655 return std::make_unique
<ScopedPrinter
>(fouts());
658 int llvm_readobj_main(int argc
, char **argv
, const llvm::ToolContext
&) {
660 StringSaver
Saver(A
);
663 opt::InputArgList Args
=
664 Tbl
.parseArgs(argc
, argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
668 if (Args
.hasArg(OPT_help
)) {
671 (Twine(ToolName
) + " [options] <input object files>").str().c_str(),
672 "LLVM Object Reader");
673 // TODO Replace this with OptTable API once it adds extrahelp support.
674 outs() << "\nPass @FILE as argument to read options from FILE.\n";
677 if (Args
.hasArg(OPT_version
)) {
678 cl::PrintVersionMessage();
682 if (sys::path::stem(argv
[0]).contains("readelf"))
683 opts::Output
= opts::GNU
;
686 // Default to print error if no filename is specified.
687 if (opts::InputFilenames
.empty()) {
688 error("no input files specified");
692 opts::FileHeaders
= true;
693 opts::XCOFFAuxiliaryHeader
= true;
694 opts::ProgramHeaders
= true;
695 opts::SectionHeaders
= true;
696 opts::Symbols
= true;
697 opts::Relocations
= true;
698 opts::DynamicTable
= true;
700 opts::VersionInfo
= true;
701 opts::UnwindInfo
= true;
702 opts::SectionGroups
= true;
703 opts::HashHistogram
= true;
704 if (opts::Output
== opts::LLVM
) {
705 opts::Addrsig
= true;
706 opts::PrintStackSizes
= true;
712 opts::FileHeaders
= true;
713 opts::XCOFFAuxiliaryHeader
= true;
714 opts::ProgramHeaders
= true;
715 opts::SectionHeaders
= true;
718 std::unique_ptr
<ScopedPrinter
> Writer
= createWriter();
720 for (const std::string
&I
: opts::InputFilenames
)
721 dumpInput(I
, *Writer
);
723 if (opts::CodeViewMergedTypes
) {
724 if (opts::CodeViewEnableGHash
)
725 dumpCodeViewMergedTypes(*Writer
, CVTypes
.GlobalIDTable
.records(),
726 CVTypes
.GlobalTypeTable
.records());
728 dumpCodeViewMergedTypes(*Writer
, CVTypes
.IDTable
.records(),
729 CVTypes
.TypeTable
.records());