diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp')
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp | 780 |
1 files changed, 780 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp b/contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp new file mode 100644 index 0000000000..41cd4414d0 --- /dev/null +++ b/contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp @@ -0,0 +1,780 @@ +//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a tool similar to readelf, except it works on multiple object file +// formats. The main purpose of this tool is to provide detailed output suitable +// for FileCheck. +// +// Flags should be similar to readelf where supported, but the output format +// does not need to be identical. The point is to not make users learn yet +// another set of flags. +// +// Output should be specialized for each format where appropriate. +// +//===----------------------------------------------------------------------===// + +#include "llvm-readobj.h" +#include "ObjDumper.h" +#include "WindowsResourceDumper.h" +#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/COFFImportFile.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Object/WindowsResource.h" +#include "llvm/Object/XCOFFObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/WithColor.h" + +using namespace llvm; +using namespace llvm::object; + +namespace opts { + cl::list<std::string> InputFilenames(cl::Positional, + cl::desc("<input object files>"), + cl::ZeroOrMore); + + // --all, -a + cl::opt<bool> + All("all", + cl::desc("Equivalent to setting: --file-headers, --program-headers, " + "--section-headers, --symbols, --relocations, " + "--dynamic-table, --notes, --version-info, --unwind, " + "--section-groups and --elf-hash-histogram.")); + cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All)); + + // --dependent-libraries + cl::opt<bool> + DependentLibraries("dependent-libraries", + cl::desc("Display the dependent libraries section")); + + // --headers, -e + cl::opt<bool> + Headers("headers", + cl::desc("Equivalent to setting: --file-headers, --program-headers, " + "--section-headers")); + cl::alias HeadersShort("e", cl::desc("Alias for --headers"), + cl::aliasopt(Headers)); + + // --wide, -W + cl::opt<bool> + WideOutput("wide", cl::desc("Ignored for compatibility with GNU readelf"), + cl::Hidden); + cl::alias WideOutputShort("W", + cl::desc("Alias for --wide"), + cl::aliasopt(WideOutput)); + + // --file-headers, --file-header, -h + cl::opt<bool> FileHeaders("file-headers", + cl::desc("Display file headers ")); + cl::alias FileHeadersShort("h", cl::desc("Alias for --file-headers"), + cl::aliasopt(FileHeaders), cl::NotHidden); + cl::alias FileHeadersSingular("file-header", + cl::desc("Alias for --file-headers"), + cl::aliasopt(FileHeaders)); + + // --section-headers, --sections, -S + // Also -s in llvm-readobj mode. + cl::opt<bool> SectionHeaders("section-headers", + cl::desc("Display all section headers.")); + cl::alias SectionsShortUpper("S", cl::desc("Alias for --section-headers"), + cl::aliasopt(SectionHeaders), cl::NotHidden); + cl::alias SectionHeadersAlias("sections", + cl::desc("Alias for --section-headers"), + cl::aliasopt(SectionHeaders), cl::NotHidden); + + // --section-relocations + // Also --sr in llvm-readobj mode. + cl::opt<bool> SectionRelocations("section-relocations", + cl::desc("Display relocations for each section shown.")); + + // --section-symbols + // Also --st in llvm-readobj mode. + cl::opt<bool> SectionSymbols("section-symbols", + cl::desc("Display symbols for each section shown.")); + + // --section-data + // Also --sd in llvm-readobj mode. + cl::opt<bool> SectionData("section-data", + cl::desc("Display section data for each section shown.")); + + // --section-mapping + cl::opt<cl::boolOrDefault> + SectionMapping("section-mapping", + cl::desc("Display the section to segment mapping.")); + + // --relocations, --relocs, -r + cl::opt<bool> Relocations("relocations", + cl::desc("Display the relocation entries in the file")); + cl::alias RelocationsShort("r", cl::desc("Alias for --relocations"), + cl::aliasopt(Relocations), cl::NotHidden); + cl::alias RelocationsGNU("relocs", cl::desc("Alias for --relocations"), + cl::aliasopt(Relocations)); + + // --notes, -n + cl::opt<bool> Notes("notes", cl::desc("Display the ELF notes in the file")); + cl::alias NotesShort("n", cl::desc("Alias for --notes"), cl::aliasopt(Notes)); + + // --dyn-relocations + cl::opt<bool> DynRelocs("dyn-relocations", + cl::desc("Display the dynamic relocation entries in the file")); + + // --section-details + // Also -t in llvm-readelf mode. + cl::opt<bool> SectionDetails("section-details", + cl::desc("Display the section details")); + + // --symbols + // Also -s in llvm-readelf mode, or -t in llvm-readobj mode. + cl::opt<bool> + Symbols("symbols", + cl::desc("Display the symbol table. Also display the dynamic " + "symbol table when using GNU output style for ELF")); + cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"), + cl::aliasopt(Symbols)); + + // --dyn-symbols, --dyn-syms + // Also --dt in llvm-readobj mode. + cl::opt<bool> DynamicSymbols("dyn-symbols", + cl::desc("Display the dynamic symbol table")); + cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"), + cl::aliasopt(DynamicSymbols)); + + // --hash-symbols + cl::opt<bool> HashSymbols( + "hash-symbols", + cl::desc("Display the dynamic symbols derived from the hash section")); + + // --unwind, -u + cl::opt<bool> UnwindInfo("unwind", + cl::desc("Display unwind information")); + cl::alias UnwindInfoShort("u", + cl::desc("Alias for --unwind"), + cl::aliasopt(UnwindInfo)); + + // --dynamic-table, --dynamic, -d + cl::opt<bool> DynamicTable("dynamic-table", + cl::desc("Display the ELF .dynamic section table")); + cl::alias DynamicTableShort("d", cl::desc("Alias for --dynamic-table"), + cl::aliasopt(DynamicTable), cl::NotHidden); + cl::alias DynamicTableAlias("dynamic", cl::desc("Alias for --dynamic-table"), + cl::aliasopt(DynamicTable)); + + // --needed-libs + cl::opt<bool> NeededLibraries("needed-libs", + cl::desc("Display the needed libraries")); + + // --program-headers, --segments, -l + cl::opt<bool> ProgramHeaders("program-headers", + cl::desc("Display ELF program headers")); + cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"), + cl::aliasopt(ProgramHeaders), cl::NotHidden); + cl::alias SegmentsAlias("segments", cl::desc("Alias for --program-headers"), + cl::aliasopt(ProgramHeaders)); + + // --string-dump, -p + cl::list<std::string> StringDump( + "string-dump", cl::value_desc("number|name"), + cl::desc("Display the specified section(s) as a list of strings"), + cl::ZeroOrMore); + cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"), + cl::aliasopt(StringDump), cl::Prefix); + + // --hex-dump, -x + cl::list<std::string> + HexDump("hex-dump", cl::value_desc("number|name"), + cl::desc("Display the specified section(s) as hexadecimal bytes"), + cl::ZeroOrMore); + cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"), + cl::aliasopt(HexDump), cl::Prefix); + + // --demangle, -C + cl::opt<bool> Demangle("demangle", + cl::desc("Demangle symbol names in output")); + cl::alias DemangleShort("C", cl::desc("Alias for --demangle"), + cl::aliasopt(Demangle), cl::NotHidden); + + // --hash-table + cl::opt<bool> HashTable("hash-table", + cl::desc("Display ELF hash table")); + + // --gnu-hash-table + cl::opt<bool> GnuHashTable("gnu-hash-table", + cl::desc("Display ELF .gnu.hash section")); + + // --expand-relocs + cl::opt<bool> ExpandRelocs("expand-relocs", + cl::desc("Expand each shown relocation to multiple lines")); + + // --raw-relr + cl::opt<bool> RawRelr("raw-relr", + cl::desc("Do not decode relocations in SHT_RELR section, display raw contents")); + + // --codeview + cl::opt<bool> CodeView("codeview", + cl::desc("Display CodeView debug information")); + + // --codeview-merged-types + cl::opt<bool> + CodeViewMergedTypes("codeview-merged-types", + cl::desc("Display the merged CodeView type stream")); + + // --codeview-ghash + cl::opt<bool> CodeViewEnableGHash( + "codeview-ghash", + cl::desc( + "Enable global hashing for CodeView type stream de-duplication")); + + // --codeview-subsection-bytes + cl::opt<bool> CodeViewSubsectionBytes( + "codeview-subsection-bytes", + cl::desc("Dump raw contents of codeview debug sections and records")); + + // --arch-specific + cl::opt<bool> ArchSpecificInfo("arch-specific", + cl::desc("Displays architecture-specific information, if there is any.")); + cl::alias ArchSpecifcInfoShort("A", cl::desc("Alias for --arch-specific"), + cl::aliasopt(ArchSpecificInfo), cl::NotHidden); + + // --coff-imports + cl::opt<bool> + COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); + + // --coff-exports + cl::opt<bool> + COFFExports("coff-exports", cl::desc("Display the PE/COFF export table")); + + // --coff-directives + cl::opt<bool> + COFFDirectives("coff-directives", + cl::desc("Display the PE/COFF .drectve section")); + + // --coff-basereloc + cl::opt<bool> + COFFBaseRelocs("coff-basereloc", + cl::desc("Display the PE/COFF .reloc section")); + + // --coff-debug-directory + cl::opt<bool> + COFFDebugDirectory("coff-debug-directory", + cl::desc("Display the PE/COFF debug directory")); + + // --coff-tls-directory + cl::opt<bool> COFFTLSDirectory("coff-tls-directory", + cl::desc("Display the PE/COFF TLS directory")); + + // --coff-resources + cl::opt<bool> COFFResources("coff-resources", + cl::desc("Display the PE/COFF .rsrc section")); + + // --coff-load-config + cl::opt<bool> + COFFLoadConfig("coff-load-config", + cl::desc("Display the PE/COFF load config")); + + // --elf-linker-options + cl::opt<bool> + ELFLinkerOptions("elf-linker-options", + cl::desc("Display the ELF .linker-options section")); + + // --macho-data-in-code + cl::opt<bool> + MachODataInCode("macho-data-in-code", + cl::desc("Display MachO Data in Code command")); + + // --macho-indirect-symbols + cl::opt<bool> + MachOIndirectSymbols("macho-indirect-symbols", + cl::desc("Display MachO indirect symbols")); + + // --macho-linker-options + cl::opt<bool> + MachOLinkerOptions("macho-linker-options", + cl::desc("Display MachO linker options")); + + // --macho-segment + cl::opt<bool> + MachOSegment("macho-segment", + cl::desc("Display MachO Segment command")); + + // --macho-version-min + cl::opt<bool> + MachOVersionMin("macho-version-min", + cl::desc("Display MachO version min command")); + + // --macho-dysymtab + cl::opt<bool> + MachODysymtab("macho-dysymtab", + cl::desc("Display MachO Dysymtab command")); + + // --stackmap + cl::opt<bool> + PrintStackMap("stackmap", + cl::desc("Display contents of stackmap section")); + + // --stack-sizes + cl::opt<bool> + PrintStackSizes("stack-sizes", + cl::desc("Display contents of all stack sizes sections")); + + // --version-info, -V + cl::opt<bool> + VersionInfo("version-info", + cl::desc("Display ELF version sections (if present)")); + cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"), + cl::aliasopt(VersionInfo)); + + // --elf-section-groups, --section-groups, -g + cl::opt<bool> SectionGroups("elf-section-groups", + cl::desc("Display ELF section group contents")); + cl::alias SectionGroupsAlias("section-groups", + cl::desc("Alias for -elf-sections-groups"), + cl::aliasopt(SectionGroups)); + cl::alias SectionGroupsShort("g", cl::desc("Alias for -elf-sections-groups"), + cl::aliasopt(SectionGroups)); + + // --elf-hash-histogram, --histogram, -I + cl::opt<bool> HashHistogram( + "elf-hash-histogram", + cl::desc("Display bucket list histogram for hash sections")); + cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"), + cl::aliasopt(HashHistogram)); + cl::alias HistogramAlias("histogram", + cl::desc("Alias for --elf-hash-histogram"), + cl::aliasopt(HashHistogram)); + + // --cg-profile + cl::opt<bool> CGProfile("cg-profile", + cl::desc("Display callgraph profile section")); + cl::alias ELFCGProfile("elf-cg-profile", cl::desc("Alias for --cg-profile"), + cl::aliasopt(CGProfile)); + + // -addrsig + cl::opt<bool> Addrsig("addrsig", + cl::desc("Display address-significance table")); + + // -elf-output-style + cl::opt<OutputStyleTy> + Output("elf-output-style", cl::desc("Specify ELF dump style"), + cl::values(clEnumVal(LLVM, "LLVM default style"), + clEnumVal(GNU, "GNU readelf style")), + cl::init(LLVM)); + + cl::extrahelp + HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); +} // namespace opts + +static StringRef ToolName; + +namespace llvm { + +LLVM_ATTRIBUTE_NORETURN static void error(Twine Msg) { + // Flush the standard output to print the error at a + // proper place. + fouts().flush(); + WithColor::error(errs(), ToolName) << Msg << "\n"; + exit(1); +} + +LLVM_ATTRIBUTE_NORETURN void reportError(Error Err, StringRef Input) { + assert(Err); + if (Input == "-") + Input = "<stdin>"; + handleAllErrors(createFileError(Input, std::move(Err)), + [&](const ErrorInfoBase &EI) { error(EI.message()); }); + llvm_unreachable("error() call should never return"); +} + +void reportWarning(Error Err, StringRef Input) { + assert(Err); + if (Input == "-") + Input = "<stdin>"; + + // Flush the standard output to print the warning at a + // proper place. + fouts().flush(); + handleAllErrors( + createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) { + WithColor::warning(errs(), ToolName) << EI.message() << "\n"; + }); +} + +} // namespace llvm + +namespace { +struct ReadObjTypeTableBuilder { + ReadObjTypeTableBuilder() + : Allocator(), IDTable(Allocator), TypeTable(Allocator), + GlobalIDTable(Allocator), GlobalTypeTable(Allocator) {} + + llvm::BumpPtrAllocator Allocator; + llvm::codeview::MergingTypeTableBuilder IDTable; + llvm::codeview::MergingTypeTableBuilder TypeTable; + llvm::codeview::GlobalTypeTableBuilder GlobalIDTable; + llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable; + std::vector<OwningBinary<Binary>> Binaries; +}; +} // namespace +static ReadObjTypeTableBuilder CVTypes; + +/// Creates an format-specific object file dumper. +static Expected<std::unique_ptr<ObjDumper>> +createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) { + if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) + return createCOFFDumper(*COFFObj, Writer); + + if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) + return createELFDumper(*ELFObj, Writer); + + if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj)) + return createMachODumper(*MachOObj, Writer); + + if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj)) + return createWasmDumper(*WasmObj, Writer); + + if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj)) + return createXCOFFDumper(*XObj, Writer); + + return createStringError(errc::invalid_argument, + "unsupported object file format"); +} + +/// Dumps the specified object file. +static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, + const Archive *A = nullptr) { + std::string FileStr = + A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str() + : Obj.getFileName().str(); + + std::string ContentErrString; + if (Error ContentErr = Obj.initContent()) + ContentErrString = "unable to continue dumping, the file is corrupt: " + + toString(std::move(ContentErr)); + + ObjDumper *Dumper; + Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer); + if (!DumperOrErr) + reportError(DumperOrErr.takeError(), FileStr); + Dumper = (*DumperOrErr).get(); + + if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || A) { + Writer.startLine() << "\n"; + Writer.printString("File", FileStr); + } + if (opts::Output == opts::LLVM) { + Writer.printString("Format", Obj.getFileFormatName()); + Writer.printString("Arch", Triple::getArchTypeName(Obj.getArch())); + Writer.printString( + "AddressSize", + std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); + Dumper->printLoadName(); + } + + if (opts::FileHeaders) + Dumper->printFileHeaders(); + + // This is only used for ELF currently. In some cases, when an object is + // corrupt (e.g. truncated), we can't dump anything except the file header. + if (!ContentErrString.empty()) + reportError(createError(ContentErrString), FileStr); + + if (opts::SectionDetails || opts::SectionHeaders) { + if (opts::Output == opts::GNU && opts::SectionDetails) + Dumper->printSectionDetails(); + else + Dumper->printSectionHeaders(); + } + + if (opts::HashSymbols) + Dumper->printHashSymbols(); + if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE) + Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping); + if (opts::DynamicTable) + Dumper->printDynamicTable(); + if (opts::NeededLibraries) + Dumper->printNeededLibraries(); + if (opts::Relocations) + Dumper->printRelocations(); + if (opts::DynRelocs) + Dumper->printDynamicRelocations(); + if (opts::UnwindInfo) + Dumper->printUnwindInfo(); + if (opts::Symbols || opts::DynamicSymbols) + Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols); + if (!opts::StringDump.empty()) + Dumper->printSectionsAsString(Obj, opts::StringDump); + if (!opts::HexDump.empty()) + Dumper->printSectionsAsHex(Obj, opts::HexDump); + if (opts::HashTable) + Dumper->printHashTable(); + if (opts::GnuHashTable) + Dumper->printGnuHashTable(); + if (opts::VersionInfo) + Dumper->printVersionInfo(); + if (Obj.isELF()) { + if (opts::DependentLibraries) + Dumper->printDependentLibs(); + if (opts::ELFLinkerOptions) + Dumper->printELFLinkerOptions(); + if (opts::ArchSpecificInfo) + Dumper->printArchSpecificInfo(); + if (opts::SectionGroups) + Dumper->printGroupSections(); + if (opts::HashHistogram) + Dumper->printHashHistograms(); + if (opts::CGProfile) + Dumper->printCGProfile(); + if (opts::Addrsig) + Dumper->printAddrsig(); + if (opts::Notes) + Dumper->printNotes(); + } + if (Obj.isCOFF()) { + if (opts::COFFImports) + Dumper->printCOFFImports(); + if (opts::COFFExports) + Dumper->printCOFFExports(); + if (opts::COFFDirectives) + Dumper->printCOFFDirectives(); + if (opts::COFFBaseRelocs) + Dumper->printCOFFBaseReloc(); + if (opts::COFFDebugDirectory) + Dumper->printCOFFDebugDirectory(); + if (opts::COFFTLSDirectory) + Dumper->printCOFFTLSDirectory(); + if (opts::COFFResources) + Dumper->printCOFFResources(); + if (opts::COFFLoadConfig) + Dumper->printCOFFLoadConfig(); + if (opts::CGProfile) + Dumper->printCGProfile(); + if (opts::Addrsig) + Dumper->printAddrsig(); + if (opts::CodeView) + Dumper->printCodeViewDebugInfo(); + if (opts::CodeViewMergedTypes) + Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable, + CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable, + opts::CodeViewEnableGHash); + } + if (Obj.isMachO()) { + if (opts::MachODataInCode) + Dumper->printMachODataInCode(); + if (opts::MachOIndirectSymbols) + Dumper->printMachOIndirectSymbols(); + if (opts::MachOLinkerOptions) + Dumper->printMachOLinkerOptions(); + if (opts::MachOSegment) + Dumper->printMachOSegment(); + if (opts::MachOVersionMin) + Dumper->printMachOVersionMin(); + if (opts::MachODysymtab) + Dumper->printMachODysymtab(); + } + if (opts::PrintStackMap) + Dumper->printStackMap(); + if (opts::PrintStackSizes) + Dumper->printStackSizes(); +} + +/// Dumps each object file in \a Arc; +static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) { + Error Err = Error::success(); + for (auto &Child : Arc->children(Err)) { + Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + reportError(std::move(E), Arc->getFileName()); + continue; + } + + Binary *Bin = ChildOrErr->get(); + if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin)) + dumpObject(*Obj, Writer, Arc); + else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin)) + dumpCOFFImportFile(Imp, Writer); + else + reportWarning(createStringError(errc::invalid_argument, + Bin->getFileName() + + " has an unsupported file type"), + Arc->getFileName()); + } + if (Err) + reportError(std::move(Err), Arc->getFileName()); +} + +/// Dumps each object file in \a MachO Universal Binary; +static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary, + ScopedPrinter &Writer) { + for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) { + Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile(); + if (ObjOrErr) + dumpObject(*ObjOrErr.get(), Writer); + else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) + reportError(ObjOrErr.takeError(), UBinary->getFileName()); + else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive()) + dumpArchive(&*AOrErr.get(), Writer); + } +} + +/// Dumps \a WinRes, Windows Resource (.res) file; +static void dumpWindowsResourceFile(WindowsResource *WinRes, + ScopedPrinter &Printer) { + WindowsRes::Dumper Dumper(WinRes, Printer); + if (auto Err = Dumper.printData()) + reportError(std::move(Err), WinRes->getFileName()); +} + + +/// Opens \a File and dumps it. +static void dumpInput(StringRef File, ScopedPrinter &Writer) { + // Attempt to open the binary. + Expected<OwningBinary<Binary>> BinaryOrErr = + createBinary(File, /*Context=*/nullptr, /*InitContent=*/false); + if (!BinaryOrErr) + reportError(BinaryOrErr.takeError(), File); + Binary &Binary = *BinaryOrErr.get().getBinary(); + + if (Archive *Arc = dyn_cast<Archive>(&Binary)) + dumpArchive(Arc, Writer); + else if (MachOUniversalBinary *UBinary = + dyn_cast<MachOUniversalBinary>(&Binary)) + dumpMachOUniversalBinary(UBinary, Writer); + else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary)) + dumpObject(*Obj, Writer); + else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary)) + dumpCOFFImportFile(Import, Writer); + else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary)) + dumpWindowsResourceFile(WinRes, Writer); + else + llvm_unreachable("unrecognized file type"); + + CVTypes.Binaries.push_back(std::move(*BinaryOrErr)); +} + +/// Registers aliases that should only be allowed by readobj. +static void registerReadobjAliases() { + // -s has meant --sections for a very long time in llvm-readobj despite + // meaning --symbols in readelf. + static cl::alias SectionsShort("s", cl::desc("Alias for --section-headers"), + cl::aliasopt(opts::SectionHeaders), + cl::NotHidden); + + // llvm-readelf reserves it for --section-details. + static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"), + cl::aliasopt(opts::Symbols), cl::NotHidden); + + // The following two-letter aliases are only provided for readobj, as readelf + // allows single-letter args to be grouped together. + static cl::alias SectionRelocationsShort( + "sr", cl::desc("Alias for --section-relocations"), + cl::aliasopt(opts::SectionRelocations)); + static cl::alias SectionDataShort("sd", cl::desc("Alias for --section-data"), + cl::aliasopt(opts::SectionData)); + static cl::alias SectionSymbolsShort("st", + cl::desc("Alias for --section-symbols"), + cl::aliasopt(opts::SectionSymbols)); + static cl::alias DynamicSymbolsShort("dt", + cl::desc("Alias for --dyn-symbols"), + cl::aliasopt(opts::DynamicSymbols)); +} + +/// Registers aliases that should only be allowed by readelf. +static void registerReadelfAliases() { + // -s is here because for readobj it means --sections. + static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"), + cl::aliasopt(opts::Symbols), cl::NotHidden, + cl::Grouping); + + // -t is here because for readobj it is an alias for --symbols. + static cl::alias SectionDetailsShort( + "t", cl::desc("Alias for --section-details"), + cl::aliasopt(opts::SectionDetails), cl::NotHidden); + + // Allow all single letter flags to be grouped together. + for (auto &OptEntry : cl::getRegisteredOptions()) { + StringRef ArgName = OptEntry.getKey(); + cl::Option *Option = OptEntry.getValue(); + if (ArgName.size() == 1) + apply(Option, cl::Grouping); + } +} + +int main(int argc, const char *argv[]) { + InitLLVM X(argc, argv); + ToolName = argv[0]; + + // Register the target printer for --version. + cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + + if (sys::path::stem(argv[0]).contains("readelf")) { + opts::Output = opts::GNU; + registerReadelfAliases(); + } else { + registerReadobjAliases(); + } + + cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n"); + + // Default to print error if no filename is specified. + if (opts::InputFilenames.empty()) { + error("no input files specified"); + } + + if (opts::All) { + opts::FileHeaders = true; + opts::ProgramHeaders = true; + opts::SectionHeaders = true; + opts::Symbols = true; + opts::Relocations = true; + opts::DynamicTable = true; + opts::Notes = true; + opts::VersionInfo = true; + opts::UnwindInfo = true; + opts::SectionGroups = true; + opts::HashHistogram = true; + if (opts::Output == opts::LLVM) { + opts::Addrsig = true; + opts::PrintStackSizes = true; + } + } + + if (opts::Headers) { + opts::FileHeaders = true; + opts::ProgramHeaders = true; + opts::SectionHeaders = true; + } + + ScopedPrinter Writer(fouts()); + for (const std::string &I : opts::InputFilenames) + dumpInput(I, Writer); + + if (opts::CodeViewMergedTypes) { + if (opts::CodeViewEnableGHash) + dumpCodeViewMergedTypes(Writer, CVTypes.GlobalIDTable.records(), + CVTypes.GlobalTypeTable.records()); + else + dumpCodeViewMergedTypes(Writer, CVTypes.IDTable.records(), + CVTypes.TypeTable.records()); + } + + return 0; +} |