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 "Error.h" 23 #include "ObjDumper.h" 24 #include "WindowsResourceDumper.h" 25 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" 26 #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" 27 #include "llvm/Object/Archive.h" 28 #include "llvm/Object/COFFImportFile.h" 29 #include "llvm/Object/MachOUniversal.h" 30 #include "llvm/Object/ObjectFile.h" 31 #include "llvm/Object/WindowsResource.h" 32 #include "llvm/Support/Casting.h" 33 #include "llvm/Support/CommandLine.h" 34 #include "llvm/Support/DataTypes.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/FileSystem.h" 37 #include "llvm/Support/FormatVariadic.h" 38 #include "llvm/Support/InitLLVM.h" 39 #include "llvm/Support/Path.h" 40 #include "llvm/Support/ScopedPrinter.h" 41 #include "llvm/Support/TargetRegistry.h" 42 43 using namespace llvm; 44 using namespace llvm::object; 45 46 namespace opts { 47 cl::list<std::string> InputFilenames(cl::Positional, 48 cl::desc("<input object files>"), 49 cl::ZeroOrMore); 50 51 // -all, -a 52 cl::opt<bool> 53 All("all", 54 cl::desc("Equivalent to setting: --file-headers, --program-headers, " 55 "--section-headers, --symbols, --relocations, " 56 "--dynamic-table, --notes, --version-info, --unwind, " 57 "--section-groups and --elf-hash-histogram.")); 58 cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All)); 59 60 // --headers -e 61 cl::opt<bool> 62 Headers("headers", 63 cl::desc("Equivalent to setting: --file-headers, --program-headers, " 64 "--section-headers")); 65 cl::alias HeadersShort("e", cl::desc("Alias for --headers"), 66 cl::aliasopt(Headers)); 67 68 // -wide, -W 69 cl::opt<bool> 70 WideOutput("wide", cl::desc("Ignored for compatibility with GNU readelf"), 71 cl::Hidden); 72 cl::alias WideOutputShort("W", 73 cl::desc("Alias for --wide"), 74 cl::aliasopt(WideOutput)); 75 76 // -file-headers, -file-header, -h 77 cl::opt<bool> FileHeaders("file-headers", 78 cl::desc("Display file headers ")); 79 cl::alias FileHeadersShort("h", cl::desc("Alias for --file-headers"), 80 cl::aliasopt(FileHeaders), cl::NotHidden); 81 cl::alias FileHeadersSingular("file-header", 82 cl::desc("Alias for --file-headers"), 83 cl::aliasopt(FileHeaders)); 84 85 // -section-headers, -sections, -S 86 // Also -s in llvm-readobj mode. 87 cl::opt<bool> SectionHeaders("section-headers", 88 cl::desc("Display all section headers.")); 89 cl::alias SectionsShortUpper("S", cl::desc("Alias for --section-headers"), 90 cl::aliasopt(SectionHeaders), cl::NotHidden); 91 cl::alias SectionHeadersAlias("sections", 92 cl::desc("Alias for --section-headers"), 93 cl::aliasopt(SectionHeaders), cl::NotHidden); 94 95 // -section-relocations 96 // Also -sr in llvm-readobj mode. 97 cl::opt<bool> SectionRelocations("section-relocations", 98 cl::desc("Display relocations for each section shown.")); 99 100 // -section-symbols 101 // Also -st in llvm-readobj mode. 102 cl::opt<bool> SectionSymbols("section-symbols", 103 cl::desc("Display symbols for each section shown.")); 104 105 // -section-data 106 // Also -sd in llvm-readobj mode. 107 cl::opt<bool> SectionData("section-data", 108 cl::desc("Display section data for each section shown.")); 109 110 // -section-mapping 111 cl::opt<cl::boolOrDefault> 112 SectionMapping("section-mapping", 113 cl::desc("Display the section to segment mapping.")); 114 115 // -relocations, -relocs, -r 116 cl::opt<bool> Relocations("relocations", 117 cl::desc("Display the relocation entries in the file")); 118 cl::alias RelocationsShort("r", cl::desc("Alias for --relocations"), 119 cl::aliasopt(Relocations), cl::NotHidden); 120 cl::alias RelocationsGNU("relocs", cl::desc("Alias for --relocations"), 121 cl::aliasopt(Relocations)); 122 123 // -notes, -n 124 cl::opt<bool> Notes("notes", cl::desc("Display the ELF notes in the file")); 125 cl::alias NotesShort("n", cl::desc("Alias for --notes"), cl::aliasopt(Notes)); 126 127 // -dyn-relocations 128 cl::opt<bool> DynRelocs("dyn-relocations", 129 cl::desc("Display the dynamic relocation entries in the file")); 130 131 // -symbols 132 // Also -s in llvm-readelf mode, or -t in llvm-readobj mode. 133 cl::opt<bool> 134 Symbols("symbols", 135 cl::desc("Display the symbol table. Also display the dynamic " 136 "symbol table when using GNU output style for ELF")); 137 cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"), 138 cl::aliasopt(Symbols)); 139 140 // -dyn-symbols, -dyn-syms 141 // Also -dt in llvm-readobj mode. 142 cl::opt<bool> DynamicSymbols("dyn-symbols", 143 cl::desc("Display the dynamic symbol table")); 144 cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"), 145 cl::aliasopt(DynamicSymbols)); 146 147 // -hash-symbols 148 cl::opt<bool> HashSymbols( 149 "hash-symbols", 150 cl::desc("Display the dynamic symbols derived from the hash section")); 151 152 // -unwind, -u 153 cl::opt<bool> UnwindInfo("unwind", 154 cl::desc("Display unwind information")); 155 cl::alias UnwindInfoShort("u", 156 cl::desc("Alias for --unwind"), 157 cl::aliasopt(UnwindInfo)); 158 159 // -dynamic-table, -dynamic, -d 160 cl::opt<bool> DynamicTable("dynamic-table", 161 cl::desc("Display the ELF .dynamic section table")); 162 cl::alias DynamicTableShort("d", cl::desc("Alias for --dynamic-table"), 163 cl::aliasopt(DynamicTable), cl::NotHidden); 164 cl::alias DynamicTableAlias("dynamic", cl::desc("Alias for --dynamic-table"), 165 cl::aliasopt(DynamicTable)); 166 167 // -needed-libs 168 cl::opt<bool> NeededLibraries("needed-libs", 169 cl::desc("Display the needed libraries")); 170 171 // -program-headers, -segments, -l 172 cl::opt<bool> ProgramHeaders("program-headers", 173 cl::desc("Display ELF program headers")); 174 cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"), 175 cl::aliasopt(ProgramHeaders), cl::NotHidden); 176 cl::alias SegmentsAlias("segments", cl::desc("Alias for --program-headers"), 177 cl::aliasopt(ProgramHeaders)); 178 179 // -string-dump, -p 180 cl::list<std::string> StringDump("string-dump", cl::desc("<number|name>"), 181 cl::ZeroOrMore); 182 cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"), 183 cl::aliasopt(StringDump)); 184 185 // -hex-dump, -x 186 cl::list<std::string> HexDump("hex-dump", cl::desc("<number|name>"), 187 cl::ZeroOrMore); 188 cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"), 189 cl::aliasopt(HexDump)); 190 191 // -demangle, -C 192 cl::opt<bool> Demangle("demangle", 193 cl::desc("Demangle symbol names in output")); 194 cl::alias DemangleShort("C", cl::desc("Alias for --demangle"), 195 cl::aliasopt(Demangle), cl::NotHidden); 196 197 // -hash-table 198 cl::opt<bool> HashTable("hash-table", 199 cl::desc("Display ELF hash table")); 200 201 // -gnu-hash-table 202 cl::opt<bool> GnuHashTable("gnu-hash-table", 203 cl::desc("Display ELF .gnu.hash section")); 204 205 // -expand-relocs 206 cl::opt<bool> ExpandRelocs("expand-relocs", 207 cl::desc("Expand each shown relocation to multiple lines")); 208 209 // -raw-relr 210 cl::opt<bool> RawRelr("raw-relr", 211 cl::desc("Do not decode relocations in SHT_RELR section, display raw contents")); 212 213 // -codeview 214 cl::opt<bool> CodeView("codeview", 215 cl::desc("Display CodeView debug information")); 216 217 // -codeview-merged-types 218 cl::opt<bool> 219 CodeViewMergedTypes("codeview-merged-types", 220 cl::desc("Display the merged CodeView type stream")); 221 222 // -codeview-ghash 223 cl::opt<bool> CodeViewEnableGHash( 224 "codeview-ghash", 225 cl::desc( 226 "Enable global hashing for CodeView type stream de-duplication")); 227 228 // -codeview-subsection-bytes 229 cl::opt<bool> CodeViewSubsectionBytes( 230 "codeview-subsection-bytes", 231 cl::desc("Dump raw contents of codeview debug sections and records")); 232 233 // -arm-attributes 234 cl::opt<bool> ARMAttributes("arm-attributes", 235 cl::desc("Display the ARM attributes section")); 236 237 // -mips-plt-got 238 cl::opt<bool> 239 MipsPLTGOT("mips-plt-got", 240 cl::desc("Display the MIPS GOT and PLT GOT sections")); 241 242 // -mips-abi-flags 243 cl::opt<bool> MipsABIFlags("mips-abi-flags", 244 cl::desc("Display the MIPS.abiflags section")); 245 246 // -mips-reginfo 247 cl::opt<bool> MipsReginfo("mips-reginfo", 248 cl::desc("Display the MIPS .reginfo section")); 249 250 // -mips-options 251 cl::opt<bool> MipsOptions("mips-options", 252 cl::desc("Display the MIPS .MIPS.options section")); 253 254 // -coff-imports 255 cl::opt<bool> 256 COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); 257 258 // -coff-exports 259 cl::opt<bool> 260 COFFExports("coff-exports", cl::desc("Display the PE/COFF export table")); 261 262 // -coff-directives 263 cl::opt<bool> 264 COFFDirectives("coff-directives", 265 cl::desc("Display the PE/COFF .drectve section")); 266 267 // -coff-basereloc 268 cl::opt<bool> 269 COFFBaseRelocs("coff-basereloc", 270 cl::desc("Display the PE/COFF .reloc section")); 271 272 // -coff-debug-directory 273 cl::opt<bool> 274 COFFDebugDirectory("coff-debug-directory", 275 cl::desc("Display the PE/COFF debug directory")); 276 277 // -coff-resources 278 cl::opt<bool> COFFResources("coff-resources", 279 cl::desc("Display the PE/COFF .rsrc section")); 280 281 // -coff-load-config 282 cl::opt<bool> 283 COFFLoadConfig("coff-load-config", 284 cl::desc("Display the PE/COFF load config")); 285 286 // -elf-linker-options 287 cl::opt<bool> 288 ELFLinkerOptions("elf-linker-options", 289 cl::desc("Display the ELF .linker-options section")); 290 291 // -macho-data-in-code 292 cl::opt<bool> 293 MachODataInCode("macho-data-in-code", 294 cl::desc("Display MachO Data in Code command")); 295 296 // -macho-indirect-symbols 297 cl::opt<bool> 298 MachOIndirectSymbols("macho-indirect-symbols", 299 cl::desc("Display MachO indirect symbols")); 300 301 // -macho-linker-options 302 cl::opt<bool> 303 MachOLinkerOptions("macho-linker-options", 304 cl::desc("Display MachO linker options")); 305 306 // -macho-segment 307 cl::opt<bool> 308 MachOSegment("macho-segment", 309 cl::desc("Display MachO Segment command")); 310 311 // -macho-version-min 312 cl::opt<bool> 313 MachOVersionMin("macho-version-min", 314 cl::desc("Display MachO version min command")); 315 316 // -macho-dysymtab 317 cl::opt<bool> 318 MachODysymtab("macho-dysymtab", 319 cl::desc("Display MachO Dysymtab command")); 320 321 // -stackmap 322 cl::opt<bool> 323 PrintStackMap("stackmap", 324 cl::desc("Display contents of stackmap section")); 325 326 // -version-info, -V 327 cl::opt<bool> 328 VersionInfo("version-info", 329 cl::desc("Display ELF version sections (if present)")); 330 cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"), 331 cl::aliasopt(VersionInfo)); 332 333 // -elf-section-groups, -section-groups, -g 334 cl::opt<bool> SectionGroups("elf-section-groups", 335 cl::desc("Display ELF section group contents")); 336 cl::alias SectionGroupsAlias("section-groups", 337 cl::desc("Alias for -elf-sections-groups"), 338 cl::aliasopt(SectionGroups)); 339 cl::alias SectionGroupsShort("g", cl::desc("Alias for -elf-sections-groups"), 340 cl::aliasopt(SectionGroups)); 341 342 // -elf-hash-histogram, -histogram, -I 343 cl::opt<bool> HashHistogram( 344 "elf-hash-histogram", 345 cl::desc("Display bucket list histogram for hash sections")); 346 cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"), 347 cl::aliasopt(HashHistogram)); 348 cl::alias HistogramAlias("histogram", 349 cl::desc("Alias for --elf-hash-histogram"), 350 cl::aliasopt(HashHistogram)); 351 352 // -elf-cg-profile 353 cl::opt<bool> CGProfile("elf-cg-profile", cl::desc("Display callgraph profile section")); 354 355 // -addrsig 356 cl::opt<bool> Addrsig("addrsig", 357 cl::desc("Display address-significance table")); 358 359 // -elf-output-style 360 cl::opt<OutputStyleTy> 361 Output("elf-output-style", cl::desc("Specify ELF dump style"), 362 cl::values(clEnumVal(LLVM, "LLVM default style"), 363 clEnumVal(GNU, "GNU readelf style")), 364 cl::init(LLVM)); 365 } // namespace opts 366 367 namespace llvm { 368 369 LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg) { 370 errs() << "\nError reading file: " << Msg << ".\n"; 371 errs().flush(); 372 exit(1); 373 } 374 375 void error(Error EC) { 376 if (!EC) 377 return; 378 handleAllErrors(std::move(EC), 379 [&](const ErrorInfoBase &EI) { reportError(EI.message()); }); 380 } 381 382 void error(std::error_code EC) { 383 if (!EC) 384 return; 385 reportError(EC.message()); 386 } 387 388 bool relocAddressLess(RelocationRef a, RelocationRef b) { 389 return a.getOffset() < b.getOffset(); 390 } 391 392 } // namespace llvm 393 394 static void reportError(StringRef Input, std::error_code EC) { 395 if (Input == "-") 396 Input = "<stdin>"; 397 398 reportError(Twine(Input) + ": " + EC.message()); 399 } 400 401 static void reportError(StringRef Input, Error Err) { 402 if (Input == "-") 403 Input = "<stdin>"; 404 std::string ErrMsg; 405 { 406 raw_string_ostream ErrStream(ErrMsg); 407 logAllUnhandledErrors(std::move(Err), ErrStream, Input + ": "); 408 } 409 reportError(ErrMsg); 410 } 411 412 static bool isMipsArch(unsigned Arch) { 413 switch (Arch) { 414 case llvm::Triple::mips: 415 case llvm::Triple::mipsel: 416 case llvm::Triple::mips64: 417 case llvm::Triple::mips64el: 418 return true; 419 default: 420 return false; 421 } 422 } 423 namespace { 424 struct ReadObjTypeTableBuilder { 425 ReadObjTypeTableBuilder() 426 : Allocator(), IDTable(Allocator), TypeTable(Allocator), 427 GlobalIDTable(Allocator), GlobalTypeTable(Allocator) {} 428 429 llvm::BumpPtrAllocator Allocator; 430 llvm::codeview::MergingTypeTableBuilder IDTable; 431 llvm::codeview::MergingTypeTableBuilder TypeTable; 432 llvm::codeview::GlobalTypeTableBuilder GlobalIDTable; 433 llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable; 434 std::vector<OwningBinary<Binary>> Binaries; 435 }; 436 } // namespace 437 static ReadObjTypeTableBuilder CVTypes; 438 439 /// Creates an format-specific object file dumper. 440 static std::error_code createDumper(const ObjectFile *Obj, 441 ScopedPrinter &Writer, 442 std::unique_ptr<ObjDumper> &Result) { 443 if (!Obj) 444 return readobj_error::unsupported_file_format; 445 446 if (Obj->isCOFF()) 447 return createCOFFDumper(Obj, Writer, Result); 448 if (Obj->isELF()) 449 return createELFDumper(Obj, Writer, Result); 450 if (Obj->isMachO()) 451 return createMachODumper(Obj, Writer, Result); 452 if (Obj->isWasm()) 453 return createWasmDumper(Obj, Writer, Result); 454 455 return readobj_error::unsupported_obj_file_format; 456 } 457 458 /// Dumps the specified object file. 459 static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) { 460 std::unique_ptr<ObjDumper> Dumper; 461 if (std::error_code EC = createDumper(Obj, Writer, Dumper)) 462 reportError(Obj->getFileName(), EC); 463 464 if (opts::Output == opts::LLVM) { 465 Writer.startLine() << "\n"; 466 Writer.printString("File", Obj->getFileName()); 467 Writer.printString("Format", Obj->getFileFormatName()); 468 Writer.printString("Arch", Triple::getArchTypeName( 469 (llvm::Triple::ArchType)Obj->getArch())); 470 Writer.printString("AddressSize", 471 formatv("{0}bit", 8 * Obj->getBytesInAddress())); 472 Dumper->printLoadName(); 473 } 474 475 if (opts::FileHeaders) 476 Dumper->printFileHeaders(); 477 if (opts::SectionHeaders) 478 Dumper->printSectionHeaders(); 479 if (opts::Relocations) 480 Dumper->printRelocations(); 481 if (opts::DynRelocs) 482 Dumper->printDynamicRelocations(); 483 if (opts::Symbols || opts::DynamicSymbols) 484 Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols); 485 if (opts::HashSymbols) 486 Dumper->printHashSymbols(); 487 if (opts::UnwindInfo) 488 Dumper->printUnwindInfo(); 489 if (opts::DynamicTable) 490 Dumper->printDynamicTable(); 491 if (opts::NeededLibraries) 492 Dumper->printNeededLibraries(); 493 if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE) 494 Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping); 495 if (!opts::StringDump.empty()) 496 llvm::for_each(opts::StringDump, [&Dumper, Obj](StringRef SectionName) { 497 Dumper->printSectionAsString(Obj, SectionName); 498 }); 499 if (!opts::HexDump.empty()) 500 llvm::for_each(opts::HexDump, [&Dumper, Obj](StringRef SectionName) { 501 Dumper->printSectionAsHex(Obj, SectionName); 502 }); 503 if (opts::HashTable) 504 Dumper->printHashTable(); 505 if (opts::GnuHashTable) 506 Dumper->printGnuHashTable(); 507 if (opts::VersionInfo) 508 Dumper->printVersionInfo(); 509 if (Obj->isELF()) { 510 if (opts::ELFLinkerOptions) 511 Dumper->printELFLinkerOptions(); 512 if (Obj->getArch() == llvm::Triple::arm) 513 if (opts::ARMAttributes) 514 Dumper->printAttributes(); 515 if (isMipsArch(Obj->getArch())) { 516 if (opts::MipsPLTGOT) 517 Dumper->printMipsPLTGOT(); 518 if (opts::MipsABIFlags) 519 Dumper->printMipsABIFlags(); 520 if (opts::MipsReginfo) 521 Dumper->printMipsReginfo(); 522 if (opts::MipsOptions) 523 Dumper->printMipsOptions(); 524 } 525 if (opts::SectionGroups) 526 Dumper->printGroupSections(); 527 if (opts::HashHistogram) 528 Dumper->printHashHistogram(); 529 if (opts::CGProfile) 530 Dumper->printCGProfile(); 531 if (opts::Addrsig) 532 Dumper->printAddrsig(); 533 if (opts::Notes) 534 Dumper->printNotes(); 535 } 536 if (Obj->isCOFF()) { 537 if (opts::COFFImports) 538 Dumper->printCOFFImports(); 539 if (opts::COFFExports) 540 Dumper->printCOFFExports(); 541 if (opts::COFFDirectives) 542 Dumper->printCOFFDirectives(); 543 if (opts::COFFBaseRelocs) 544 Dumper->printCOFFBaseReloc(); 545 if (opts::COFFDebugDirectory) 546 Dumper->printCOFFDebugDirectory(); 547 if (opts::COFFResources) 548 Dumper->printCOFFResources(); 549 if (opts::COFFLoadConfig) 550 Dumper->printCOFFLoadConfig(); 551 if (opts::Addrsig) 552 Dumper->printAddrsig(); 553 if (opts::CodeView) 554 Dumper->printCodeViewDebugInfo(); 555 if (opts::CodeViewMergedTypes) 556 Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable, 557 CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable, 558 opts::CodeViewEnableGHash); 559 } 560 if (Obj->isMachO()) { 561 if (opts::MachODataInCode) 562 Dumper->printMachODataInCode(); 563 if (opts::MachOIndirectSymbols) 564 Dumper->printMachOIndirectSymbols(); 565 if (opts::MachOLinkerOptions) 566 Dumper->printMachOLinkerOptions(); 567 if (opts::MachOSegment) 568 Dumper->printMachOSegment(); 569 if (opts::MachOVersionMin) 570 Dumper->printMachOVersionMin(); 571 if (opts::MachODysymtab) 572 Dumper->printMachODysymtab(); 573 } 574 if (opts::PrintStackMap) 575 Dumper->printStackMap(); 576 } 577 578 /// Dumps each object file in \a Arc; 579 static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) { 580 Error Err = Error::success(); 581 for (auto &Child : Arc->children(Err)) { 582 Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(); 583 if (!ChildOrErr) { 584 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) { 585 reportError(Arc->getFileName(), ChildOrErr.takeError()); 586 } 587 continue; 588 } 589 if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get())) 590 dumpObject(Obj, Writer); 591 else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(&*ChildOrErr.get())) 592 dumpCOFFImportFile(Imp, Writer); 593 else 594 reportError(Arc->getFileName(), readobj_error::unrecognized_file_format); 595 } 596 if (Err) 597 reportError(Arc->getFileName(), std::move(Err)); 598 } 599 600 /// Dumps each object file in \a MachO Universal Binary; 601 static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary, 602 ScopedPrinter &Writer) { 603 for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) { 604 Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile(); 605 if (ObjOrErr) 606 dumpObject(&*ObjOrErr.get(), Writer); 607 else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 608 reportError(UBinary->getFileName(), ObjOrErr.takeError()); 609 } 610 else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive()) 611 dumpArchive(&*AOrErr.get(), Writer); 612 } 613 } 614 615 /// Dumps \a WinRes, Windows Resource (.res) file; 616 static void dumpWindowsResourceFile(WindowsResource *WinRes) { 617 ScopedPrinter Printer{outs()}; 618 WindowsRes::Dumper Dumper(WinRes, Printer); 619 if (auto Err = Dumper.printData()) 620 reportError(WinRes->getFileName(), std::move(Err)); 621 } 622 623 624 /// Opens \a File and dumps it. 625 static void dumpInput(StringRef File) { 626 ScopedPrinter Writer(outs()); 627 628 // Attempt to open the binary. 629 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File); 630 if (!BinaryOrErr) 631 reportError(File, BinaryOrErr.takeError()); 632 Binary &Binary = *BinaryOrErr.get().getBinary(); 633 634 if (Archive *Arc = dyn_cast<Archive>(&Binary)) 635 dumpArchive(Arc, Writer); 636 else if (MachOUniversalBinary *UBinary = 637 dyn_cast<MachOUniversalBinary>(&Binary)) 638 dumpMachOUniversalBinary(UBinary, Writer); 639 else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary)) 640 dumpObject(Obj, Writer); 641 else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary)) 642 dumpCOFFImportFile(Import, Writer); 643 else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary)) 644 dumpWindowsResourceFile(WinRes); 645 else 646 reportError(File, readobj_error::unrecognized_file_format); 647 648 CVTypes.Binaries.push_back(std::move(*BinaryOrErr)); 649 } 650 651 /// Registers aliases that should only be allowed by readobj. 652 static void registerReadobjAliases() { 653 // -s has meant --sections for a very long time in llvm-readobj despite 654 // meaning --symbols in readelf. 655 static cl::alias SectionsShort("s", cl::desc("Alias for --section-headers"), 656 cl::aliasopt(opts::SectionHeaders), 657 cl::NotHidden); 658 659 // Only register -t in llvm-readobj, as readelf reserves it for 660 // --section-details (not implemented yet). 661 static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"), 662 cl::aliasopt(opts::Symbols), cl::NotHidden); 663 664 // The following two-letter aliases are only provided for readobj, as readelf 665 // allows single-letter args to be grouped together. 666 static cl::alias SectionRelocationsShort( 667 "sr", cl::desc("Alias for --section-relocations"), 668 cl::aliasopt(opts::SectionRelocations)); 669 static cl::alias SectionDataShort("sd", cl::desc("Alias for --section-data"), 670 cl::aliasopt(opts::SectionData)); 671 static cl::alias SectionSymbolsShort("st", 672 cl::desc("Alias for --section-symbols"), 673 cl::aliasopt(opts::SectionSymbols)); 674 static cl::alias DynamicSymbolsShort("dt", 675 cl::desc("Alias for --dyn-symbols"), 676 cl::aliasopt(opts::DynamicSymbols)); 677 } 678 679 /// Registers aliases that should only be allowed by readelf. 680 static void registerReadelfAliases() { 681 // -s is here because for readobj it means --sections. 682 static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"), 683 cl::aliasopt(opts::Symbols), cl::NotHidden, 684 cl::Grouping); 685 686 // Allow all single letter flags to be grouped together. 687 for (auto &OptEntry : cl::getRegisteredOptions()) { 688 StringRef ArgName = OptEntry.getKey(); 689 cl::Option *Option = OptEntry.getValue(); 690 if (ArgName.size() == 1) 691 Option->setFormattingFlag(cl::Grouping); 692 } 693 } 694 695 int main(int argc, const char *argv[]) { 696 InitLLVM X(argc, argv); 697 698 // Register the target printer for --version. 699 cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); 700 701 if (sys::path::stem(argv[0]).contains("readelf")) { 702 opts::Output = opts::GNU; 703 registerReadelfAliases(); 704 } else { 705 registerReadobjAliases(); 706 } 707 708 cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n"); 709 710 if (opts::All) { 711 opts::FileHeaders = true; 712 opts::ProgramHeaders = true; 713 opts::SectionHeaders = true; 714 opts::Symbols = true; 715 opts::Relocations = true; 716 opts::DynamicTable = true; 717 opts::Notes = true; 718 opts::VersionInfo = true; 719 opts::UnwindInfo = true; 720 opts::SectionGroups = true; 721 opts::HashHistogram = true; 722 } 723 724 if (opts::Headers) { 725 opts::FileHeaders = true; 726 opts::ProgramHeaders = true; 727 opts::SectionHeaders = true; 728 } 729 730 // Default to stdin if no filename is specified. 731 if (opts::InputFilenames.empty()) 732 opts::InputFilenames.push_back("-"); 733 734 llvm::for_each(opts::InputFilenames, dumpInput); 735 736 if (opts::CodeViewMergedTypes) { 737 ScopedPrinter W(outs()); 738 if (opts::CodeViewEnableGHash) 739 dumpCodeViewMergedTypes(W, CVTypes.GlobalIDTable.records(), 740 CVTypes.GlobalTypeTable.records()); 741 else 742 dumpCodeViewMergedTypes(W, CVTypes.IDTable.records(), 743 CVTypes.TypeTable.records()); 744 } 745 746 return 0; 747 } 748