Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
35231 views
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/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"
49
50
using namespace llvm;
51
using namespace llvm::object;
52
53
namespace {
54
using namespace llvm::opt; // for HelpHidden in Opts.inc
55
enum ID {
56
OPT_INVALID = 0, // This is not an option ID.
57
#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
58
#include "Opts.inc"
59
#undef OPTION
60
};
61
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);
66
#include "Opts.inc"
67
#undef PREFIX
68
69
static constexpr opt::OptTable::Info InfoTable[] = {
70
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
71
#include "Opts.inc"
72
#undef OPTION
73
};
74
75
class ReadobjOptTable : public opt::GenericOptTable {
76
public:
77
ReadobjOptTable() : opt::GenericOptTable(InfoTable) {
78
setGroupedShortOptions(true);
79
}
80
};
81
82
enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
83
84
enum SortSymbolKeyTy {
85
NAME = 0,
86
TYPE = 1,
87
UNKNOWN = 100,
88
// TODO: add ADDRESS, SIZE as needed.
89
};
90
91
} // namespace
92
93
namespace opts {
94
static bool Addrsig;
95
static bool All;
96
static bool ArchSpecificInfo;
97
static bool BBAddrMap;
98
static bool PrettyPGOAnalysisMap;
99
bool ExpandRelocs;
100
static bool CGProfile;
101
static bool Decompress;
102
bool Demangle;
103
static bool DependentLibraries;
104
static bool DynRelocs;
105
static bool DynamicSymbols;
106
static bool ExtraSymInfo;
107
static bool FileHeaders;
108
static bool Headers;
109
static std::vector<std::string> HexDump;
110
static bool PrettyPrint;
111
static bool PrintStackMap;
112
static bool PrintStackSizes;
113
static bool Relocations;
114
bool SectionData;
115
static bool SectionDetails;
116
static bool SectionHeaders;
117
bool SectionRelocations;
118
bool SectionSymbols;
119
static std::vector<std::string> StringDump;
120
static bool StringTable;
121
static bool Symbols;
122
static bool UnwindInfo;
123
static cl::boolOrDefault SectionMapping;
124
static SmallVector<SortSymbolKeyTy> SortKeys;
125
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;
133
static bool Memtag;
134
static bool NeededLibraries;
135
static bool Notes;
136
static bool ProgramHeaders;
137
static bool SectionGroups;
138
static bool VersionInfo;
139
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;
147
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;
161
162
// XCOFF specific options.
163
static bool XCOFFAuxiliaryHeader;
164
static bool XCOFFLoaderSectionHeader;
165
static bool XCOFFLoaderSectionSymbol;
166
static bool XCOFFLoaderSectionRelocation;
167
static bool XCOFFExceptionSection;
168
169
OutputStyleTy Output = OutputStyleTy::LLVM;
170
static std::vector<std::string> InputFilenames;
171
} // namespace opts
172
173
static StringRef ToolName;
174
175
namespace llvm {
176
177
[[noreturn]] static void error(Twine Msg) {
178
// Flush the standard output to print the error at a
179
// proper place.
180
fouts().flush();
181
WithColor::error(errs(), ToolName) << Msg << "\n";
182
exit(1);
183
}
184
185
[[noreturn]] void reportError(Error Err, StringRef Input) {
186
assert(Err);
187
if (Input == "-")
188
Input = "<stdin>";
189
handleAllErrors(createFileError(Input, std::move(Err)),
190
[&](const ErrorInfoBase &EI) { error(EI.message()); });
191
llvm_unreachable("error() call should never return");
192
}
193
194
void reportWarning(Error Err, StringRef Input) {
195
assert(Err);
196
if (Input == "-")
197
Input = "<stdin>";
198
199
// Flush the standard output to print the warning at a
200
// proper place.
201
fouts().flush();
202
handleAllErrors(
203
createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
204
WithColor::warning(errs(), ToolName) << EI.message() << "\n";
205
});
206
}
207
208
} // namespace llvm
209
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 "
219
"have an effect\n";
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;
241
else
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);
249
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 + "'");
264
}
265
}
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);
287
}
288
}
289
opts::VersionInfo = Args.hasArg(OPT_version_info);
290
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);
298
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);
312
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);
320
321
opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
322
}
323
324
namespace {
325
struct ReadObjTypeTableBuilder {
326
ReadObjTypeTableBuilder()
327
: IDTable(Allocator), TypeTable(Allocator), GlobalIDTable(Allocator),
328
GlobalTypeTable(Allocator) {}
329
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;
336
};
337
} // namespace
338
static ReadObjTypeTableBuilder CVTypes;
339
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);
345
346
if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
347
return createELFDumper(*ELFObj, Writer);
348
349
if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
350
return createMachODumper(*MachOObj, Writer);
351
352
if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
353
return createWasmDumper(*WasmObj, Writer);
354
355
if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
356
return createXCOFFDumper(*XObj, Writer);
357
358
return createStringError(errc::invalid_argument,
359
"unsupported object file format");
360
}
361
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();
368
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));
373
374
ObjDumper *Dumper;
375
std::optional<SymbolComparator> SymComp;
376
Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
377
if (!DumperOrErr)
378
reportError(DumperOrErr.takeError(), FileStr);
379
Dumper = (*DumperOrErr).get();
380
381
if (!opts::SortKeys.empty()) {
382
if (Dumper->canCompareSymbols()) {
383
SymComp = SymbolComparator();
384
for (SortSymbolKeyTy Key : opts::SortKeys) {
385
switch (Key) {
386
case NAME:
387
SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
388
return Dumper->compareSymbolsByName(LHS, RHS);
389
});
390
break;
391
case TYPE:
392
SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
393
return Dumper->compareSymbolsByType(LHS, RHS);
394
});
395
break;
396
case UNKNOWN:
397
llvm_unreachable("Unsupported sort key");
398
}
399
}
400
401
} else {
402
reportWarning(createStringError(
403
errc::invalid_argument,
404
"--sort-symbols is not supported yet for this format"),
405
FileStr);
406
}
407
}
408
Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A);
409
410
if (opts::FileHeaders)
411
Dumper->printFileHeaders();
412
413
// Auxiliary header in XOCFF is right after the file header, so print the data
414
// here.
415
if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
416
Dumper->printAuxiliaryHeader();
417
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);
422
423
if (opts::SectionDetails || opts::SectionHeaders) {
424
if (opts::Output == opts::GNU && opts::SectionDetails)
425
Dumper->printSectionDetails();
426
else
427
Dumper->printSectionHeaders();
428
}
429
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();
440
if (opts::DynRelocs)
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);
451
if (opts::HashTable)
452
Dumper->printHashTable();
453
if (opts::GnuHashTable)
454
Dumper->printGnuHashTable();
455
if (opts::VersionInfo)
456
Dumper->printVersionInfo();
457
if (opts::StringTable)
458
Dumper->printStringTable();
459
if (Obj.isELF()) {
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();
470
if (opts::CGProfile)
471
Dumper->printCGProfile();
472
if (opts::BBAddrMap)
473
Dumper->printBBAddrMaps(opts::PrettyPGOAnalysisMap);
474
if (opts::Addrsig)
475
Dumper->printAddrsig();
476
if (opts::Notes)
477
Dumper->printNotes();
478
if (opts::Memtag)
479
Dumper->printMemtag();
480
}
481
if (Obj.isCOFF()) {
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();
498
if (opts::CGProfile)
499
Dumper->printCGProfile();
500
if (opts::Addrsig)
501
Dumper->printAddrsig();
502
if (opts::CodeView)
503
Dumper->printCodeViewDebugInfo();
504
if (opts::CodeViewMergedTypes)
505
Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
506
CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
507
opts::CodeViewEnableGHash);
508
}
509
if (Obj.isMachO()) {
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();
522
if (opts::CGProfile)
523
Dumper->printCGProfile();
524
}
525
526
if (Obj.isXCOFF()) {
527
if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol ||
528
opts::XCOFFLoaderSectionRelocation)
529
Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader,
530
opts::XCOFFLoaderSectionSymbol,
531
opts::XCOFFLoaderSectionRelocation);
532
533
if (opts::XCOFFExceptionSection)
534
Dumper->printExceptionSection();
535
}
536
537
if (opts::PrintStackMap)
538
Dumper->printStackMap();
539
if (opts::PrintStackSizes)
540
Dumper->printStackSizes();
541
}
542
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();
548
if (!ChildOrErr) {
549
if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
550
reportError(std::move(E), Arc->getFileName());
551
continue;
552
}
553
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);
559
else
560
reportWarning(createStringError(errc::invalid_argument,
561
Bin->getFileName() +
562
" has an unsupported file type"),
563
Arc->getFileName());
564
}
565
if (Err)
566
reportError(std::move(Err), Arc->getFileName());
567
}
568
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();
574
if (ObjOrErr)
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);
580
}
581
}
582
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());
589
}
590
591
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);
599
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"),
605
File);
606
return;
607
}
608
609
Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
610
Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
611
if (!BinaryOrErr)
612
reportError(BinaryOrErr.takeError(), File);
613
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);
626
else
627
llvm_unreachable("unrecognized file type");
628
629
CVTypes.Binaries.push_back(
630
OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
631
}
632
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());
638
}
639
640
int llvm_readobj_main(int argc, char **argv, const llvm::ToolContext &) {
641
BumpPtrAllocator A;
642
StringSaver Saver(A);
643
ReadobjOptTable Tbl;
644
ToolName = argv[0];
645
opt::InputArgList Args =
646
Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
647
error(Msg);
648
exit(1);
649
});
650
if (Args.hasArg(OPT_help)) {
651
Tbl.printHelp(
652
outs(),
653
(Twine(ToolName) + " [options] <input object files>").str().c_str(),
654
"LLVM Object Reader");
655
// TODO Replace this with OptTable API once it adds extrahelp support.
656
outs() << "\nPass @FILE as argument to read options from FILE.\n";
657
return 0;
658
}
659
if (Args.hasArg(OPT_version)) {
660
cl::PrintVersionMessage();
661
return 0;
662
}
663
664
if (sys::path::stem(argv[0]).contains("readelf"))
665
opts::Output = opts::GNU;
666
parseOptions(Args);
667
668
// Default to print error if no filename is specified.
669
if (opts::InputFilenames.empty()) {
670
error("no input files specified");
671
}
672
673
if (opts::All) {
674
opts::FileHeaders = true;
675
opts::XCOFFAuxiliaryHeader = true;
676
opts::ProgramHeaders = true;
677
opts::SectionHeaders = true;
678
opts::Symbols = true;
679
opts::Relocations = true;
680
opts::DynamicTable = true;
681
opts::Notes = true;
682
opts::VersionInfo = true;
683
opts::UnwindInfo = true;
684
opts::SectionGroups = true;
685
opts::HashHistogram = true;
686
if (opts::Output == opts::LLVM) {
687
opts::Addrsig = true;
688
opts::PrintStackSizes = true;
689
}
690
opts::Memtag = true;
691
}
692
693
if (opts::Headers) {
694
opts::FileHeaders = true;
695
opts::XCOFFAuxiliaryHeader = true;
696
opts::ProgramHeaders = true;
697
opts::SectionHeaders = true;
698
}
699
700
std::unique_ptr<ScopedPrinter> Writer = createWriter();
701
702
for (const std::string &I : opts::InputFilenames)
703
dumpInput(I, *Writer);
704
705
if (opts::CodeViewMergedTypes) {
706
if (opts::CodeViewEnableGHash)
707
dumpCodeViewMergedTypes(*Writer, CVTypes.GlobalIDTable.records(),
708
CVTypes.GlobalTypeTable.records());
709
else
710
dumpCodeViewMergedTypes(*Writer, CVTypes.IDTable.records(),
711
CVTypes.TypeTable.records());
712
}
713
714
return 0;
715
}
716
717