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(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
63 #define PREFIX(NAME, VALUE) \
64 static constexpr StringLiteral NAME##_init[] = VALUE; \
65 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
66 std::size(NAME##_init) - 1);
70 static constexpr opt::OptTable::Info InfoTable
[] = {
71 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
76 class ReadobjOptTable
: public opt::GenericOptTable
{
78 ReadobjOptTable() : opt::GenericOptTable(InfoTable
) {
79 setGroupedShortOptions(true);
83 enum OutputFormatTy
{ bsd
, sysv
, posix
, darwin
, just_symbols
};
85 enum SortSymbolKeyTy
{
89 // TODO: add ADDRESS, SIZE as needed.
97 static bool ArchSpecificInfo
;
98 static bool BBAddrMap
;
100 static bool CGProfile
;
102 static bool DependentLibraries
;
103 static bool DynRelocs
;
104 static bool DynamicSymbols
;
105 static bool ExtraSymInfo
;
106 static bool FileHeaders
;
108 static std::vector
<std::string
> HexDump
;
109 static bool PrettyPrint
;
110 static bool PrintStackMap
;
111 static bool PrintStackSizes
;
112 static bool Relocations
;
114 static bool SectionDetails
;
115 static bool SectionHeaders
;
116 bool SectionRelocations
;
118 static std::vector
<std::string
> StringDump
;
119 static bool StringTable
;
121 static bool UnwindInfo
;
122 static cl::boolOrDefault SectionMapping
;
123 static SmallVector
<SortSymbolKeyTy
> SortKeys
;
125 // ELF specific options.
126 static bool DynamicTable
;
127 static bool ELFLinkerOptions
;
128 static bool GnuHashTable
;
129 static bool HashSymbols
;
130 static bool HashTable
;
131 static bool HashHistogram
;
133 static bool NeededLibraries
;
135 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::CGProfile
= Args
.hasArg(OPT_cg_profile
);
216 opts::Demangle
= Args
.hasFlag(OPT_demangle
, OPT_no_demangle
, false);
217 opts::DependentLibraries
= Args
.hasArg(OPT_dependent_libraries
);
218 opts::DynRelocs
= Args
.hasArg(OPT_dyn_relocations
);
219 opts::DynamicSymbols
= Args
.hasArg(OPT_dyn_syms
);
220 opts::ExpandRelocs
= Args
.hasArg(OPT_expand_relocs
);
221 opts::ExtraSymInfo
= Args
.hasArg(OPT_extra_sym_info
);
222 opts::FileHeaders
= Args
.hasArg(OPT_file_header
);
223 opts::Headers
= Args
.hasArg(OPT_headers
);
224 opts::HexDump
= Args
.getAllArgValues(OPT_hex_dump_EQ
);
225 opts::Relocations
= Args
.hasArg(OPT_relocs
);
226 opts::SectionData
= Args
.hasArg(OPT_section_data
);
227 opts::SectionDetails
= Args
.hasArg(OPT_section_details
);
228 opts::SectionHeaders
= Args
.hasArg(OPT_section_headers
);
229 opts::SectionRelocations
= Args
.hasArg(OPT_section_relocations
);
230 opts::SectionSymbols
= Args
.hasArg(OPT_section_symbols
);
231 if (Args
.hasArg(OPT_section_mapping
))
232 opts::SectionMapping
= cl::BOU_TRUE
;
233 else if (Args
.hasArg(OPT_section_mapping_EQ_false
))
234 opts::SectionMapping
= cl::BOU_FALSE
;
236 opts::SectionMapping
= cl::BOU_UNSET
;
237 opts::PrintStackSizes
= Args
.hasArg(OPT_stack_sizes
);
238 opts::PrintStackMap
= Args
.hasArg(OPT_stackmap
);
239 opts::StringDump
= Args
.getAllArgValues(OPT_string_dump_EQ
);
240 opts::StringTable
= Args
.hasArg(OPT_string_table
);
241 opts::Symbols
= Args
.hasArg(OPT_symbols
);
242 opts::UnwindInfo
= Args
.hasArg(OPT_unwind
);
244 // ELF specific options.
245 opts::DynamicTable
= Args
.hasArg(OPT_dynamic_table
);
246 opts::ELFLinkerOptions
= Args
.hasArg(OPT_elf_linker_options
);
247 if (Arg
*A
= Args
.getLastArg(OPT_elf_output_style_EQ
)) {
248 std::string OutputStyleChoice
= A
->getValue();
249 opts::Output
= StringSwitch
<opts::OutputStyleTy
>(OutputStyleChoice
)
250 .Case("LLVM", opts::OutputStyleTy::LLVM
)
251 .Case("GNU", opts::OutputStyleTy::GNU
)
252 .Case("JSON", opts::OutputStyleTy::JSON
)
253 .Default(opts::OutputStyleTy::UNKNOWN
);
254 if (opts::Output
== opts::OutputStyleTy::UNKNOWN
) {
255 error("--elf-output-style value should be either 'LLVM', 'GNU', or "
256 "'JSON', but was '" +
257 OutputStyleChoice
+ "'");
260 opts::GnuHashTable
= Args
.hasArg(OPT_gnu_hash_table
);
261 opts::HashSymbols
= Args
.hasArg(OPT_hash_symbols
);
262 opts::HashTable
= Args
.hasArg(OPT_hash_table
);
263 opts::HashHistogram
= Args
.hasArg(OPT_histogram
);
264 opts::Memtag
= Args
.hasArg(OPT_memtag
);
265 opts::NeededLibraries
= Args
.hasArg(OPT_needed_libs
);
266 opts::Notes
= Args
.hasArg(OPT_notes
);
267 opts::PrettyPrint
= Args
.hasArg(OPT_pretty_print
);
268 opts::ProgramHeaders
= Args
.hasArg(OPT_program_headers
);
269 opts::RawRelr
= Args
.hasArg(OPT_raw_relr
);
270 opts::SectionGroups
= Args
.hasArg(OPT_section_groups
);
271 if (Arg
*A
= Args
.getLastArg(OPT_sort_symbols_EQ
)) {
272 std::string SortKeysString
= A
->getValue();
273 for (StringRef KeyStr
: llvm::split(A
->getValue(), ",")) {
274 SortSymbolKeyTy KeyType
= StringSwitch
<SortSymbolKeyTy
>(KeyStr
)
275 .Case("name", SortSymbolKeyTy::NAME
)
276 .Case("type", SortSymbolKeyTy::TYPE
)
277 .Default(SortSymbolKeyTy::UNKNOWN
);
278 if (KeyType
== SortSymbolKeyTy::UNKNOWN
)
279 error("--sort-symbols value should be 'name' or 'type', but was '" +
280 Twine(KeyStr
) + "'");
281 opts::SortKeys
.push_back(KeyType
);
284 opts::VersionInfo
= Args
.hasArg(OPT_version_info
);
286 // Mach-O specific options.
287 opts::MachODataInCode
= Args
.hasArg(OPT_macho_data_in_code
);
288 opts::MachODysymtab
= Args
.hasArg(OPT_macho_dysymtab
);
289 opts::MachOIndirectSymbols
= Args
.hasArg(OPT_macho_indirect_symbols
);
290 opts::MachOLinkerOptions
= Args
.hasArg(OPT_macho_linker_options
);
291 opts::MachOSegment
= Args
.hasArg(OPT_macho_segment
);
292 opts::MachOVersionMin
= Args
.hasArg(OPT_macho_version_min
);
294 // PE/COFF specific options.
295 opts::CodeView
= Args
.hasArg(OPT_codeview
);
296 opts::CodeViewEnableGHash
= Args
.hasArg(OPT_codeview_ghash
);
297 opts::CodeViewMergedTypes
= Args
.hasArg(OPT_codeview_merged_types
);
298 opts::CodeViewSubsectionBytes
= Args
.hasArg(OPT_codeview_subsection_bytes
);
299 opts::COFFBaseRelocs
= Args
.hasArg(OPT_coff_basereloc
);
300 opts::COFFDebugDirectory
= Args
.hasArg(OPT_coff_debug_directory
);
301 opts::COFFDirectives
= Args
.hasArg(OPT_coff_directives
);
302 opts::COFFExports
= Args
.hasArg(OPT_coff_exports
);
303 opts::COFFImports
= Args
.hasArg(OPT_coff_imports
);
304 opts::COFFLoadConfig
= Args
.hasArg(OPT_coff_load_config
);
305 opts::COFFResources
= Args
.hasArg(OPT_coff_resources
);
306 opts::COFFTLSDirectory
= Args
.hasArg(OPT_coff_tls_directory
);
308 // XCOFF specific options.
309 opts::XCOFFAuxiliaryHeader
= Args
.hasArg(OPT_auxiliary_header
);
310 opts::XCOFFLoaderSectionHeader
= Args
.hasArg(OPT_loader_section_header
);
311 opts::XCOFFLoaderSectionSymbol
= Args
.hasArg(OPT_loader_section_symbols
);
312 opts::XCOFFLoaderSectionRelocation
=
313 Args
.hasArg(OPT_loader_section_relocations
);
314 opts::XCOFFExceptionSection
= Args
.hasArg(OPT_exception_section
);
316 opts::InputFilenames
= Args
.getAllArgValues(OPT_INPUT
);
320 struct ReadObjTypeTableBuilder
{
321 ReadObjTypeTableBuilder()
322 : IDTable(Allocator
), TypeTable(Allocator
), GlobalIDTable(Allocator
),
323 GlobalTypeTable(Allocator
) {}
325 llvm::BumpPtrAllocator Allocator
;
326 llvm::codeview::MergingTypeTableBuilder IDTable
;
327 llvm::codeview::MergingTypeTableBuilder TypeTable
;
328 llvm::codeview::GlobalTypeTableBuilder GlobalIDTable
;
329 llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable
;
330 std::vector
<OwningBinary
<Binary
>> Binaries
;
333 static ReadObjTypeTableBuilder CVTypes
;
335 /// Creates an format-specific object file dumper.
336 static Expected
<std::unique_ptr
<ObjDumper
>>
337 createDumper(const ObjectFile
&Obj
, ScopedPrinter
&Writer
) {
338 if (const COFFObjectFile
*COFFObj
= dyn_cast
<COFFObjectFile
>(&Obj
))
339 return createCOFFDumper(*COFFObj
, Writer
);
341 if (const ELFObjectFileBase
*ELFObj
= dyn_cast
<ELFObjectFileBase
>(&Obj
))
342 return createELFDumper(*ELFObj
, Writer
);
344 if (const MachOObjectFile
*MachOObj
= dyn_cast
<MachOObjectFile
>(&Obj
))
345 return createMachODumper(*MachOObj
, Writer
);
347 if (const WasmObjectFile
*WasmObj
= dyn_cast
<WasmObjectFile
>(&Obj
))
348 return createWasmDumper(*WasmObj
, Writer
);
350 if (const XCOFFObjectFile
*XObj
= dyn_cast
<XCOFFObjectFile
>(&Obj
))
351 return createXCOFFDumper(*XObj
, Writer
);
353 return createStringError(errc::invalid_argument
,
354 "unsupported object file format");
357 /// Dumps the specified object file.
358 static void dumpObject(ObjectFile
&Obj
, ScopedPrinter
&Writer
,
359 const Archive
*A
= nullptr) {
360 std::string FileStr
=
361 A
? Twine(A
->getFileName() + "(" + Obj
.getFileName() + ")").str()
362 : Obj
.getFileName().str();
364 std::string ContentErrString
;
365 if (Error ContentErr
= Obj
.initContent())
366 ContentErrString
= "unable to continue dumping, the file is corrupt: " +
367 toString(std::move(ContentErr
));
370 std::optional
<SymbolComparator
> SymComp
;
371 Expected
<std::unique_ptr
<ObjDumper
>> DumperOrErr
= createDumper(Obj
, Writer
);
373 reportError(DumperOrErr
.takeError(), FileStr
);
374 Dumper
= (*DumperOrErr
).get();
376 if (!opts::SortKeys
.empty()) {
377 if (Dumper
->canCompareSymbols()) {
378 SymComp
= SymbolComparator();
379 for (SortSymbolKeyTy Key
: opts::SortKeys
) {
382 SymComp
->addPredicate([Dumper
](SymbolRef LHS
, SymbolRef RHS
) {
383 return Dumper
->compareSymbolsByName(LHS
, RHS
);
387 SymComp
->addPredicate([Dumper
](SymbolRef LHS
, SymbolRef RHS
) {
388 return Dumper
->compareSymbolsByType(LHS
, RHS
);
392 llvm_unreachable("Unsupported sort key");
397 reportWarning(createStringError(
398 errc::invalid_argument
,
399 "--sort-symbols is not supported yet for this format"),
403 Dumper
->printFileSummary(FileStr
, Obj
, opts::InputFilenames
, A
);
405 if (opts::FileHeaders
)
406 Dumper
->printFileHeaders();
408 // Auxiliary header in XOCFF is right after the file header, so print the data
410 if (Obj
.isXCOFF() && opts::XCOFFAuxiliaryHeader
)
411 Dumper
->printAuxiliaryHeader();
413 // This is only used for ELF currently. In some cases, when an object is
414 // corrupt (e.g. truncated), we can't dump anything except the file header.
415 if (!ContentErrString
.empty())
416 reportError(createError(ContentErrString
), FileStr
);
418 if (opts::SectionDetails
|| opts::SectionHeaders
) {
419 if (opts::Output
== opts::GNU
&& opts::SectionDetails
)
420 Dumper
->printSectionDetails();
422 Dumper
->printSectionHeaders();
425 if (opts::HashSymbols
)
426 Dumper
->printHashSymbols();
427 if (opts::ProgramHeaders
|| opts::SectionMapping
== cl::BOU_TRUE
)
428 Dumper
->printProgramHeaders(opts::ProgramHeaders
, opts::SectionMapping
);
429 if (opts::DynamicTable
)
430 Dumper
->printDynamicTable();
431 if (opts::NeededLibraries
)
432 Dumper
->printNeededLibraries();
433 if (opts::Relocations
)
434 Dumper
->printRelocations();
436 Dumper
->printDynamicRelocations();
437 if (opts::UnwindInfo
)
438 Dumper
->printUnwindInfo();
439 if (opts::Symbols
|| opts::DynamicSymbols
)
440 Dumper
->printSymbols(opts::Symbols
, opts::DynamicSymbols
,
441 opts::ExtraSymInfo
, SymComp
);
442 if (!opts::StringDump
.empty())
443 Dumper
->printSectionsAsString(Obj
, opts::StringDump
);
444 if (!opts::HexDump
.empty())
445 Dumper
->printSectionsAsHex(Obj
, opts::HexDump
);
447 Dumper
->printHashTable();
448 if (opts::GnuHashTable
)
449 Dumper
->printGnuHashTable();
450 if (opts::VersionInfo
)
451 Dumper
->printVersionInfo();
452 if (opts::StringTable
)
453 Dumper
->printStringTable();
455 if (opts::DependentLibraries
)
456 Dumper
->printDependentLibs();
457 if (opts::ELFLinkerOptions
)
458 Dumper
->printELFLinkerOptions();
459 if (opts::ArchSpecificInfo
)
460 Dumper
->printArchSpecificInfo();
461 if (opts::SectionGroups
)
462 Dumper
->printGroupSections();
463 if (opts::HashHistogram
)
464 Dumper
->printHashHistograms();
466 Dumper
->printCGProfile();
468 Dumper
->printBBAddrMaps();
470 Dumper
->printAddrsig();
472 Dumper
->printNotes();
474 Dumper
->printMemtag();
477 if (opts::COFFImports
)
478 Dumper
->printCOFFImports();
479 if (opts::COFFExports
)
480 Dumper
->printCOFFExports();
481 if (opts::COFFDirectives
)
482 Dumper
->printCOFFDirectives();
483 if (opts::COFFBaseRelocs
)
484 Dumper
->printCOFFBaseReloc();
485 if (opts::COFFDebugDirectory
)
486 Dumper
->printCOFFDebugDirectory();
487 if (opts::COFFTLSDirectory
)
488 Dumper
->printCOFFTLSDirectory();
489 if (opts::COFFResources
)
490 Dumper
->printCOFFResources();
491 if (opts::COFFLoadConfig
)
492 Dumper
->printCOFFLoadConfig();
494 Dumper
->printCGProfile();
496 Dumper
->printAddrsig();
498 Dumper
->printCodeViewDebugInfo();
499 if (opts::CodeViewMergedTypes
)
500 Dumper
->mergeCodeViewTypes(CVTypes
.IDTable
, CVTypes
.TypeTable
,
501 CVTypes
.GlobalIDTable
, CVTypes
.GlobalTypeTable
,
502 opts::CodeViewEnableGHash
);
505 if (opts::MachODataInCode
)
506 Dumper
->printMachODataInCode();
507 if (opts::MachOIndirectSymbols
)
508 Dumper
->printMachOIndirectSymbols();
509 if (opts::MachOLinkerOptions
)
510 Dumper
->printMachOLinkerOptions();
511 if (opts::MachOSegment
)
512 Dumper
->printMachOSegment();
513 if (opts::MachOVersionMin
)
514 Dumper
->printMachOVersionMin();
515 if (opts::MachODysymtab
)
516 Dumper
->printMachODysymtab();
518 Dumper
->printCGProfile();
522 if (opts::XCOFFLoaderSectionHeader
|| opts::XCOFFLoaderSectionSymbol
||
523 opts::XCOFFLoaderSectionRelocation
)
524 Dumper
->printLoaderSection(opts::XCOFFLoaderSectionHeader
,
525 opts::XCOFFLoaderSectionSymbol
,
526 opts::XCOFFLoaderSectionRelocation
);
528 if (opts::XCOFFExceptionSection
)
529 Dumper
->printExceptionSection();
532 if (opts::PrintStackMap
)
533 Dumper
->printStackMap();
534 if (opts::PrintStackSizes
)
535 Dumper
->printStackSizes();
538 /// Dumps each object file in \a Arc;
539 static void dumpArchive(const Archive
*Arc
, ScopedPrinter
&Writer
) {
540 Error Err
= Error::success();
541 for (auto &Child
: Arc
->children(Err
)) {
542 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= Child
.getAsBinary();
544 if (auto E
= isNotObjectErrorInvalidFileType(ChildOrErr
.takeError()))
545 reportError(std::move(E
), Arc
->getFileName());
549 Binary
*Bin
= ChildOrErr
->get();
550 if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
))
551 dumpObject(*Obj
, Writer
, Arc
);
552 else if (COFFImportFile
*Imp
= dyn_cast
<COFFImportFile
>(Bin
))
553 dumpCOFFImportFile(Imp
, Writer
);
555 reportWarning(createStringError(errc::invalid_argument
,
557 " has an unsupported file type"),
561 reportError(std::move(Err
), Arc
->getFileName());
564 /// Dumps each object file in \a MachO Universal Binary;
565 static void dumpMachOUniversalBinary(const MachOUniversalBinary
*UBinary
,
566 ScopedPrinter
&Writer
) {
567 for (const MachOUniversalBinary::ObjectForArch
&Obj
: UBinary
->objects()) {
568 Expected
<std::unique_ptr
<MachOObjectFile
>> ObjOrErr
= Obj
.getAsObjectFile();
570 dumpObject(*ObjOrErr
.get(), Writer
);
571 else if (auto E
= isNotObjectErrorInvalidFileType(ObjOrErr
.takeError()))
572 reportError(ObjOrErr
.takeError(), UBinary
->getFileName());
573 else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
= Obj
.getAsArchive())
574 dumpArchive(&*AOrErr
.get(), Writer
);
578 /// Dumps \a WinRes, Windows Resource (.res) file;
579 static void dumpWindowsResourceFile(WindowsResource
*WinRes
,
580 ScopedPrinter
&Printer
) {
581 WindowsRes::Dumper
Dumper(WinRes
, Printer
);
582 if (auto Err
= Dumper
.printData())
583 reportError(std::move(Err
), WinRes
->getFileName());
587 /// Opens \a File and dumps it.
588 static void dumpInput(StringRef File
, ScopedPrinter
&Writer
) {
589 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
590 MemoryBuffer::getFileOrSTDIN(File
, /*IsText=*/false,
591 /*RequiresNullTerminator=*/false);
592 if (std::error_code EC
= FileOrErr
.getError())
593 return reportError(errorCodeToError(EC
), File
);
595 std::unique_ptr
<MemoryBuffer
> &Buffer
= FileOrErr
.get();
596 file_magic Type
= identify_magic(Buffer
->getBuffer());
597 if (Type
== file_magic::bitcode
) {
598 reportWarning(createStringError(errc::invalid_argument
,
599 "bitcode files are not supported"),
604 Expected
<std::unique_ptr
<Binary
>> BinaryOrErr
= createBinary(
605 Buffer
->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
607 reportError(BinaryOrErr
.takeError(), File
);
609 std::unique_ptr
<Binary
> Bin
= std::move(*BinaryOrErr
);
610 if (Archive
*Arc
= dyn_cast
<Archive
>(Bin
.get()))
611 dumpArchive(Arc
, Writer
);
612 else if (MachOUniversalBinary
*UBinary
=
613 dyn_cast
<MachOUniversalBinary
>(Bin
.get()))
614 dumpMachOUniversalBinary(UBinary
, Writer
);
615 else if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(Bin
.get()))
616 dumpObject(*Obj
, Writer
);
617 else if (COFFImportFile
*Import
= dyn_cast
<COFFImportFile
>(Bin
.get()))
618 dumpCOFFImportFile(Import
, Writer
);
619 else if (WindowsResource
*WinRes
= dyn_cast
<WindowsResource
>(Bin
.get()))
620 dumpWindowsResourceFile(WinRes
, Writer
);
622 llvm_unreachable("unrecognized file type");
624 CVTypes
.Binaries
.push_back(
625 OwningBinary
<Binary
>(std::move(Bin
), std::move(Buffer
)));
628 std::unique_ptr
<ScopedPrinter
> createWriter() {
629 if (opts::Output
== opts::JSON
)
630 return std::make_unique
<JSONScopedPrinter
>(
631 fouts(), opts::PrettyPrint
? 2 : 0, std::make_unique
<ListScope
>());
632 return std::make_unique
<ScopedPrinter
>(fouts());
635 int llvm_readobj_main(int argc
, char **argv
, const llvm::ToolContext
&) {
636 InitLLVM
X(argc
, argv
);
638 StringSaver
Saver(A
);
641 opt::InputArgList Args
=
642 Tbl
.parseArgs(argc
, argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
646 if (Args
.hasArg(OPT_help
)) {
649 (Twine(ToolName
) + " [options] <input object files>").str().c_str(),
650 "LLVM Object Reader");
651 // TODO Replace this with OptTable API once it adds extrahelp support.
652 outs() << "\nPass @FILE as argument to read options from FILE.\n";
655 if (Args
.hasArg(OPT_version
)) {
656 cl::PrintVersionMessage();
660 if (sys::path::stem(argv
[0]).contains("readelf"))
661 opts::Output
= opts::GNU
;
664 // Default to print error if no filename is specified.
665 if (opts::InputFilenames
.empty()) {
666 error("no input files specified");
670 opts::FileHeaders
= true;
671 opts::XCOFFAuxiliaryHeader
= true;
672 opts::ProgramHeaders
= true;
673 opts::SectionHeaders
= true;
674 opts::Symbols
= true;
675 opts::Relocations
= true;
676 opts::DynamicTable
= true;
678 opts::VersionInfo
= true;
679 opts::UnwindInfo
= true;
680 opts::SectionGroups
= true;
681 opts::HashHistogram
= true;
682 if (opts::Output
== opts::LLVM
) {
683 opts::Addrsig
= true;
684 opts::PrintStackSizes
= true;
690 opts::FileHeaders
= true;
691 opts::XCOFFAuxiliaryHeader
= true;
692 opts::ProgramHeaders
= true;
693 opts::SectionHeaders
= true;
696 std::unique_ptr
<ScopedPrinter
> Writer
= createWriter();
698 for (const std::string
&I
: opts::InputFilenames
)
699 dumpInput(I
, *Writer
.get());
701 if (opts::CodeViewMergedTypes
) {
702 if (opts::CodeViewEnableGHash
)
703 dumpCodeViewMergedTypes(*Writer
.get(), CVTypes
.GlobalIDTable
.records(),
704 CVTypes
.GlobalTypeTable
.records());
706 dumpCodeViewMergedTypes(*Writer
.get(), CVTypes
.IDTable
.records(),
707 CVTypes
.TypeTable
.records());