aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-readobj/llvm-readobj.cpp
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-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.cpp780
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;
+}