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 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; 116 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; 130 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; 138 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; 152 153 // XCOFF specific options. 154 static bool XCOFFAuxiliaryHeader; 155 156 OutputStyleTy Output = OutputStyleTy::LLVM; 157 static std::vector<std::string> InputFilenames; 158 } // namespace opts 159 160 static StringRef ToolName; 161 162 namespace llvm { 163 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); 170 } 171 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"); 179 } 180 181 void reportWarning(Error Err, StringRef Input) { 182 assert(Err); 183 if (Input == "-") 184 Input = "<stdin>"; 185 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"; 192 }); 193 } 194 195 } // namespace llvm 196 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); 229 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 + "'"); 244 } 245 } 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); 257 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); 265 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); 279 280 // XCOFF specific options. 281 opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header); 282 283 opts::InputFilenames = Args.getAllArgValues(OPT_INPUT); 284 } 285 286 namespace { 287 struct ReadObjTypeTableBuilder { 288 ReadObjTypeTableBuilder() 289 : IDTable(Allocator), TypeTable(Allocator), GlobalIDTable(Allocator), 290 GlobalTypeTable(Allocator) {} 291 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; 298 }; 299 } // namespace 300 static ReadObjTypeTableBuilder CVTypes; 301 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); 307 308 if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) 309 return createELFDumper(*ELFObj, Writer); 310 311 if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj)) 312 return createMachODumper(*MachOObj, Writer); 313 314 if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj)) 315 return createWasmDumper(*WasmObj, Writer); 316 317 if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj)) 318 return createXCOFFDumper(*XObj, Writer); 319 320 return createStringError(errc::invalid_argument, 321 "unsupported object file format"); 322 } 323 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(); 330 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)); 335 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(); 341 342 Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A); 343 344 if (opts::FileHeaders) 345 Dumper->printFileHeaders(); 346 347 if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader) 348 Dumper->printAuxiliaryHeader(); 349 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); 354 355 if (opts::SectionDetails || opts::SectionHeaders) { 356 if (opts::Output == opts::GNU && opts::SectionDetails) 357 Dumper->printSectionDetails(); 358 else 359 Dumper->printSectionHeaders(); 360 } 361 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(); 409 } 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); 437 } 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(); 453 } 454 if (opts::PrintStackMap) 455 Dumper->printStackMap(); 456 if (opts::PrintStackSizes) 457 Dumper->printStackSizes(); 458 } 459 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; 469 } 470 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()); 481 } 482 if (Err) 483 reportError(std::move(Err), Arc->getFileName()); 484 } 485 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); 497 } 498 } 499 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()); 506 } 507 508 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); 516 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; 524 } 525 526 Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary( 527 Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false); 528 if (!BinaryOrErr) 529 reportError(BinaryOrErr.takeError(), File); 530 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"); 545 546 CVTypes.Binaries.push_back( 547 OwningBinary<Binary>(std::move(Bin), std::move(Buffer))); 548 } 549 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()); 555 } 556 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); 567 }); 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; 576 } 577 if (Args.hasArg(OPT_version)) { 578 cl::PrintVersionMessage(); 579 return 0; 580 } 581 582 if (sys::path::stem(argv[0]).contains("readelf")) 583 opts::Output = opts::GNU; 584 parseOptions(Args); 585 586 // Default to print error if no filename is specified. 587 if (opts::InputFilenames.empty()) { 588 error("no input files specified"); 589 } 590 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; 607 } 608 } 609 610 if (opts::Headers) { 611 opts::FileHeaders = true; 612 opts::XCOFFAuxiliaryHeader = true; 613 opts::ProgramHeaders = true; 614 opts::SectionHeaders = true; 615 } 616 617 std::unique_ptr<ScopedPrinter> Writer = createWriter(); 618 619 for (const std::string &I : opts::InputFilenames) 620 dumpInput(I, *Writer.get()); 621 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()); 629 } 630 631 return 0; 632 } 633