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