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