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