From 3992539f30335ce41fcf09a4eeb6cff80e24b4bd Mon Sep 17 00:00:00 2001 From: guzhihao4 Date: Mon, 18 Sep 2023 11:43:49 +0800 Subject: [PATCH] [tools]Support ADLT in llvm tools Add new file type ADLT in Object and support tools for reading Issue: #I8265Y Signed-off-by: guzhihao4 Change-Id: I90c940f413ae33e0122ba7e610547749002fbc27 --- llvm/include/llvm/ADT/StringRef.h | 5 + llvm/include/llvm/BinaryFormat/Magic.h | 3 + llvm/include/llvm/Object/ADLTFile.h | 170 ++++++++++++++++ llvm/include/llvm/Object/Binary.h | 8 +- llvm/include/llvm/Object/ELF.h | 13 +- llvm/include/llvm/Object/ELFObjectFile.h | 7 +- llvm/include/llvm/Object/ObjectFile.h | 5 +- llvm/include/llvm/Object/SymbolicFile.h | 3 +- llvm/lib/BinaryFormat/Magic.cpp | 32 +++ llvm/lib/Object/ADLTFile.cpp | 128 ++++++++++++ llvm/lib/Object/Binary.cpp | 10 +- llvm/lib/Object/CMakeLists.txt | 1 + llvm/lib/Object/ELFObjectFile.cpp | 14 +- llvm/lib/Object/ObjectFile.cpp | 8 +- llvm/lib/Object/SymbolicFile.cpp | 8 +- llvm/tools/llvm-nm/Opts.td | 2 + llvm/tools/llvm-nm/llvm-nm.cpp | 61 +++++- llvm/tools/llvm-objdump/ObjdumpOpts.td | 6 + llvm/tools/llvm-objdump/llvm-objdump.cpp | 145 +++++++++++++- llvm/tools/llvm-objdump/llvm-objdump.h | 3 + llvm/tools/llvm-readobj/ADLTDumper.cpp | 13 ++ llvm/tools/llvm-readobj/ADLTDumper.h | 26 +++ llvm/tools/llvm-readobj/CMakeLists.txt | 1 + llvm/tools/llvm-readobj/ELFDumper.cpp | 32 +++ llvm/tools/llvm-readobj/ObjDumper.cpp | 14 ++ llvm/tools/llvm-readobj/ObjDumper.h | 4 + llvm/tools/llvm-readobj/Opts.td | 2 + llvm/tools/llvm-readobj/llvm-readobj.cpp | 238 ++++++++++++++++++++++- 28 files changed, 929 insertions(+), 33 deletions(-) create mode 100644 llvm/include/llvm/Object/ADLTFile.h create mode 100644 llvm/lib/Object/ADLTFile.cpp create mode 100644 llvm/tools/llvm-readobj/ADLTDumper.cpp create mode 100644 llvm/tools/llvm-readobj/ADLTDumper.h diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h index 80ba47dd619c..36480596dec9 100644 --- a/llvm/include/llvm/ADT/StringRef.h +++ b/llvm/include/llvm/ADT/StringRef.h @@ -292,6 +292,11 @@ namespace llvm { compareMemory(Data, Prefix.Data, Prefix.Length) == 0; } + bool offsetstartswith(StringRef Prefix, uint64_t Offset) const { + return Length >= Prefix.Length && + compareMemory(Data + Offset, Prefix.Data, Prefix.Length) == 0; + } + /// Check if this string starts with the given \p Prefix, ignoring case. LLVM_NODISCARD bool startswith_insensitive(StringRef Prefix) const; diff --git a/llvm/include/llvm/BinaryFormat/Magic.h b/llvm/include/llvm/BinaryFormat/Magic.h index c8e0dad42b0b..bd4a82172f4f 100644 --- a/llvm/include/llvm/BinaryFormat/Magic.h +++ b/llvm/include/llvm/BinaryFormat/Magic.h @@ -9,6 +9,7 @@ #ifndef LLVM_BINARYFORMAT_MAGIC_H #define LLVM_BINARYFORMAT_MAGIC_H +#include #include namespace llvm { @@ -54,6 +55,7 @@ struct file_magic { cuda_fatbinary, ///< CUDA Fatbinary object file offload_binary, ///< LLVM offload object file dxcontainer_object, ///< DirectX container file + adlt, ///< ADLT file }; bool is_object() const { return V != unknown; } @@ -68,6 +70,7 @@ private: /// Identify the type of a binary file based on how magical it is. file_magic identify_magic(StringRef magic); +file_magic identify_magic_offset(StringRef magic, uint64_t Offset); /// Get and identify \a path's type based on its content. /// diff --git a/llvm/include/llvm/Object/ADLTFile.h b/llvm/include/llvm/Object/ADLTFile.h new file mode 100644 index 000000000000..39fcfa6414da --- /dev/null +++ b/llvm/include/llvm/Object/ADLTFile.h @@ -0,0 +1,170 @@ +#ifndef LLVM_OBJECT_ADLTFILE_H +#define LLVM_OBJECT_ADLTFILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/fallible_iterator.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ELFTypes.h" +#include +#include + +namespace llvm { +namespace object { + +class ADLTFile : public Binary { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELF64LE) + class Child { + friend ADLTFile; + const ADLTFile *Parent; + StringRef Data; + uint64_t StartOfFile; + size_t Index = 0; + + public: + Child(const ADLTFile *Parent, StringRef Data, uint64_t StartOfFile, size_t Index) : Parent(Parent), Data(Data), StartOfFile(StartOfFile), Index(Index) {} + + Child(const Child &C) : Parent(C.Parent), Data(C.Data), StartOfFile(C.StartOfFile), Index(C.Index) {} + + Child(Child &&C) { + Parent = std::move(C.Parent); + Data = C.Data; + StartOfFile = C.StartOfFile; + Index = C.Index; + } + + Child &operator=(Child &&C) noexcept { + if (&C == this) + return *this; + Parent = std::move(C.Parent); + Data = C.Data; + StartOfFile = C.StartOfFile; + Index = C.Index; + return *this; + } + + Child &operator=(const Child &C) { + if (&C == this) + return *this; + Parent = C.Parent; + Data = C.Data; + StartOfFile = C.StartOfFile; + Index = C.Index; + + return *this; + } + + bool operator==(const Child &Other) const { + assert(!Parent || !Other.Parent || Parent == Other.Parent); + return Data.begin() == Other.Data.begin() && StartOfFile == Other.StartOfFile; + } + + const ADLTFile *getParent() const { return Parent; } + Expected getNext() const; + Expected getBuffer() const; + Expected getMemoryBufferRef() const; + Expected getName() const; + + Expected> + getAsBinary(LLVMContext *Context = nullptr) const; + }; + + class ChildFallibleIterator { + Child C; + public: + ChildFallibleIterator() : C(Child(nullptr, "", 0, 0)) {} + ChildFallibleIterator(const Child &C) : C(C) {} + + const Child *operator->() const { return &C; } + const Child &operator*() const { return C; } + bool operator==(const ChildFallibleIterator &Other) const { + return C == Other.C; + } + + bool operator!=(const ChildFallibleIterator &Other) const { + return !(*this == Other); + } + + Error inc() { + auto NextChild = C.getNext(); + if (!NextChild) + return NextChild.takeError(); + C = std::move(*NextChild); + return Error::success(); + } + }; + + using child_iterator = fallible_iterator; + + class ADLTLibInfo { + uint32_t NameIndex; + uint32_t Padding; + uint64_t Offset; + + public: + ADLTLibInfo(uint32_t NameIndex, uint64_t Offset) : NameIndex(NameIndex), Offset(Offset) {} + + bool operator==(const ADLTLibInfo &Other) const { + return (NameIndex == Other.NameIndex) && (Offset == Other.Offset); + } + + uint32_t getNameIndex() const { + return NameIndex; + } + + uint64_t getOffset() const { + return Offset; + } + ADLTLibInfo getNext() const; + }; + + + const Elf_Ehdr *Header; + const ADLTLibInfo *LibInfo; + const char *LibInfoNameTable; + size_t LibInfoNameTableSize; + size_t LibInfoNum; + std::vector LibInfoNameList; + static const uint64_t MaxMemberSize = 9999999999; + + const Elf_Ehdr &getHeader() const { + return *Header; + } + + Expected sections() const; + + ADLTFile(MemoryBufferRef Source, Error &Err); + static Expected> create(MemoryBufferRef Source); + + child_iterator childBegin(Error &Err) const; + child_iterator childEnd() const; + iterator_range children(Error &Err) const { + return make_range(childBegin(Err), childEnd()); + } + static bool classof(Binary const *V) { return V->isADLT(); } + + // TODO + // Expected> findSym(StringRef name) const; + + uint64_t getFirstChildOffset() const { + return LibInfo->getOffset(); + } + + const Elf_Ehdr * + createADLTHeader(const char *RawHeaderPtr, Error *Err); + + const ADLTLibInfo * + createADLTLibInfo(const char *RawHeaderPtr, Error *Err); + + bool isEmpty() const; + +protected: + StringRef SectionHeaderTable; + StringRef ProgrameHeaderTable; +}; + + +} // namespace object +} // namespace llvm + +#endif // LLVM_OBJECT_ADLTFILE_H diff --git a/llvm/include/llvm/Object/Binary.h b/llvm/include/llvm/Object/Binary.h index 53b299ae8612..f730b18d58fd 100644 --- a/llvm/include/llvm/Object/Binary.h +++ b/llvm/include/llvm/Object/Binary.h @@ -70,6 +70,7 @@ protected: ID_MachO64B, // MachO 64-bit, big endian ID_Wasm, + ID_ADLT, ID_EndObjects }; @@ -145,6 +146,10 @@ public: return TypeID == ID_IR; } + bool isADLT() const { + return TypeID == ID_ADLT; + } + bool isMinidump() const { return TypeID == ID_Minidump; } bool isTapiFile() const { return TypeID == ID_TapiFile; } @@ -186,7 +191,8 @@ DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef) /// @param Source The data to create the Binary from. Expected> createBinary(MemoryBufferRef Source, LLVMContext *Context = nullptr, - bool InitContent = true); + bool InitContent = true, + uint64_t Offset = 0); template class OwningBinary { std::unique_ptr Bin; diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index 5eb43777a951..d61a20e1feeb 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -181,13 +181,14 @@ public: private: StringRef Buf; + uint64_t Offset; std::vector FakeSections; - ELFFile(StringRef Object); + ELFFile(StringRef Object, uint64_t Offset = 0); public: const Elf_Ehdr &getHeader() const { - return *reinterpret_cast(base()); + return *reinterpret_cast(base() + Offset); } template @@ -234,7 +235,7 @@ public: Expected, 0>> loadVersionMap(const Elf_Shdr *VerNeedSec, const Elf_Shdr *VerDefSec) const; - static Expected create(StringRef Object); + static Expected create(StringRef Object, uint64_t Offset = 0); bool isLE() const { return getHeader().getDataEncoding() == ELF::ELFDATA2LSB; @@ -749,15 +750,15 @@ Expected ELFFile::getDynSymtabSize() const { return 0; } -template ELFFile::ELFFile(StringRef Object) : Buf(Object) {} +template ELFFile::ELFFile(StringRef Object, uint64_t Offset) : Buf(Object), Offset(Offset) {} template -Expected> ELFFile::create(StringRef Object) { +Expected> ELFFile::create(StringRef Object, uint64_t Offset) { if (sizeof(Elf_Ehdr) > Object.size()) return createError("invalid buffer: the size (" + Twine(Object.size()) + ") is smaller than an ELF header (" + Twine(sizeof(Elf_Ehdr)) + ")"); - return ELFFile(Object); + return ELFFile(Object, Offset); } /// Used by llvm-objdump -d (which needs sections for disassembly) to diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index ed2f70b0da25..e6fbf97bb6bf 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -406,7 +406,8 @@ protected: public: ELFObjectFile(ELFObjectFile &&Other); static Expected> create(MemoryBufferRef Object, - bool InitContent = true); + bool InitContent = true, + uint64_t Offset = 0); const Elf_Rel *getRel(DataRefImpl Rel) const; const Elf_Rela *getRela(DataRefImpl Rela) const; @@ -1088,8 +1089,8 @@ ELFObjectFile::getRela(DataRefImpl Rela) const { template Expected> -ELFObjectFile::create(MemoryBufferRef Object, bool InitContent) { - auto EFOrErr = ELFFile::create(Object.getBuffer()); +ELFObjectFile::create(MemoryBufferRef Object, bool InitContent, uint64_t Offset) { + auto EFOrErr = ELFFile::create(Object.getBuffer(), Offset); if (Error E = EFOrErr.takeError()) return std::move(E); diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h index 8754c229bd4b..19ddcb31bad7 100644 --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -364,7 +364,8 @@ public: static Expected> createObjectFile(MemoryBufferRef Object, llvm::file_magic Type, - bool InitContent = true); + bool InitContent = true, + uint64_t Offset = 0); static Expected> createObjectFile(MemoryBufferRef Object) { return createObjectFile(Object, llvm::file_magic::unknown); @@ -381,7 +382,7 @@ public: createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); static Expected> - createELFObjectFile(MemoryBufferRef Object, bool InitContent = true); + createELFObjectFile(MemoryBufferRef Object, bool InitContent = true, uint64_t Offset = 0); static Expected> createMachOObjectFile(MemoryBufferRef Object, diff --git a/llvm/include/llvm/Object/SymbolicFile.h b/llvm/include/llvm/Object/SymbolicFile.h index ea51afce5d2a..c273dba4f754 100644 --- a/llvm/include/llvm/Object/SymbolicFile.h +++ b/llvm/include/llvm/Object/SymbolicFile.h @@ -167,7 +167,8 @@ public: // construction aux. static Expected> createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, - LLVMContext *Context, bool InitContent = true); + LLVMContext *Context, bool InitContent = true, + uint64_t Offset = 0); static Expected> createSymbolicFile(MemoryBufferRef Object) { diff --git a/llvm/lib/BinaryFormat/Magic.cpp b/llvm/lib/BinaryFormat/Magic.cpp index d45195fb95c5..be473b6776d4 100644 --- a/llvm/lib/BinaryFormat/Magic.cpp +++ b/llvm/lib/BinaryFormat/Magic.cpp @@ -29,7 +29,37 @@ static bool startswith(StringRef Magic, const char (&S)[N]) { return Magic.startswith(StringRef(S, N - 1)); } +template +static bool offsetstartswith(StringRef Magic, uint64_t Offset, const char (&S)[N]) { + return Magic.offsetstartswith(StringRef(S, N - 1), Offset); +} + /// Identify the magic in magic. +file_magic llvm::identify_magic_offset(StringRef Magic, uint64_t Offset) { + if (Offset && offsetstartswith(Magic, Offset, "\177ELF") && Magic.size() >= 18) { + bool Data2MSB = Magic[Offset + 5] == 2; + unsigned high = Data2MSB ? 16 : 17; + unsigned low = Data2MSB ? 17 : 16; + if (Magic[Offset + high] == 0) { + switch (Magic[Offset + low]) { + default: + return file_magic::elf; + case 1: + return file_magic::elf_relocatable; + case 2: + return file_magic::elf_executable; + case 3: + return file_magic::elf_shared_object; + case 4: + return file_magic::elf_core; + } + } + // It's still some type of ELF file. + return file_magic::elf; + } + return identify_magic(Magic); +} + file_magic llvm::identify_magic(StringRef Magic) { if (Magic.size() < 4) return file_magic::unknown; @@ -113,6 +143,8 @@ file_magic llvm::identify_magic(StringRef Magic) { case 4: return file_magic::elf_core; } + } else if (Magic[high] == char(0xFE) && Magic[low] == char(0x01)) { + return file_magic::adlt; } // It's still some type of ELF file. return file_magic::elf; diff --git a/llvm/lib/Object/ADLTFile.cpp b/llvm/lib/Object/ADLTFile.cpp new file mode 100644 index 000000000000..5fa676fdda64 --- /dev/null +++ b/llvm/lib/Object/ADLTFile.cpp @@ -0,0 +1,128 @@ +#include "llvm/Object/ADLTFile.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MemoryBufferRef.h" +#include +#include + +using namespace llvm; +using namespace object; + +Expected ADLTFile::Child::getName() const { + return Parent->LibInfoNameList[Index]; +} + +Expected ADLTFile::Child::getNext() const { + size_t NextIndex = Index + 1; + if (NextIndex >= Parent->LibInfoNum) { + return Child(nullptr, "", 0, 0); + } + const ADLTLibInfo *SoTable = Parent->LibInfo + NextIndex; + uint64_t Start = SoTable->getOffset(); + + Child Ret(Parent, Data, Start, NextIndex); + return Ret; +} + +Expected ADLTFile::Child::getMemoryBufferRef() const { + const ADLTLibInfo *SoTable = Parent->LibInfo + Index; + StringRef Name = reinterpret_cast(Parent->LibInfoNameTable + SoTable->getNameIndex()); + return MemoryBufferRef(Data, Name); +} + +Expected> +ADLTFile::Child::getAsBinary(LLVMContext *Context) const { + Expected BuffOrErr = getMemoryBufferRef(); + if (!BuffOrErr) + return BuffOrErr.takeError(); + auto BinaryOrErr = createBinary(BuffOrErr.get(), Context, true, StartOfFile); + if (BinaryOrErr) + return std::move(*BinaryOrErr); + return BinaryOrErr.takeError(); +} + +ADLTFile::child_iterator ADLTFile::childBegin(Error &Err) const { + if (isEmpty()) { + return childEnd(); + } + + Child C(this, Data.getBuffer(), getFirstChildOffset(), 0); + if (Err) + return childEnd(); + return child_iterator::itr(C, Err); +} + +ADLTFile::child_iterator ADLTFile::childEnd() const { + return child_iterator::end(Child(nullptr, "", 0, 0)); +} + +bool ADLTFile::isEmpty() const { + return LibInfoNum == 0; +} + +const ELF64LE::Ehdr *ADLTFile::createADLTHeader(const char *RawHeaderPtr, Error *Err) { + return reinterpret_cast(RawHeaderPtr); +} + +const llvm::object::ADLTFile::ADLTLibInfo *ADLTFile::createADLTLibInfo(const char *RawHeaderPtr, Error *Err) { + const uint64_t Offset = Header->e_entry; + return reinterpret_cast(RawHeaderPtr + Offset); +} + +ADLTFile::ADLTFile(MemoryBufferRef Source, Error &Err) : Binary(Binary::ID_ADLT, Source) { + Header = createADLTHeader(Source.getBuffer().begin(), &Err); + LibInfo = createADLTLibInfo(Source.getBuffer().begin(), &Err); + + LibInfoNum = (Header->e_phoff - Header->e_entry) / sizeof(ADLTLibInfo); + if (!LibInfoNum) { + LibInfoNum = 0; + } + + LibInfoNameTable = reinterpret_cast(Header) + Header->e_ehsize; + LibInfoNameTableSize = reinterpret_cast(LibInfo) - reinterpret_cast(LibInfoNameTable); + + const char *LibInfoName = LibInfoNameTable; + while (LibInfoName < LibInfoNameTable + LibInfoNameTableSize) { + StringRef Name = reinterpret_cast(LibInfoName); + if (Name.size() == 0) { + LibInfoName++; + continue; + } + LibInfoNameList.push_back(Name); + LibInfoName += Name.size(); + } + assert(LibInfoNum == LibInfoNameList.size()); +} + +Expected> ADLTFile::create(MemoryBufferRef Source) { + Error Err = Error::success(); + + std::unique_ptr Ret = std::make_unique(Source, Err); + if (Err) + return std::move(Err); + return std::move(Ret); +} + +Expected ADLTFile::sections() const { + const uint64_t SectionTableOffset = getHeader().e_shoff; + if (SectionTableOffset == 0) + return ArrayRef(); + + if (getHeader().e_shentsize != sizeof(Elf_Shdr)) + return createError("invalid e_shentsize in ELF header: " + + Twine(getHeader().e_shentsize)); + + const uint64_t FileSize = Data.getBuffer().size(); + if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize || + SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset) + return createError( + "section header table goes past the end of the file: e_shoff = 0x" + + Twine::utohexstr(SectionTableOffset)); + + const Elf_Shdr *First = + reinterpret_cast(Header + SectionTableOffset); + uintX_t NumSections = getHeader().e_shnum; + return makeArrayRef(First, NumSections); +} diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp index 8065e3eb1d85..1457b56896fc 100644 --- a/llvm/lib/Object/Binary.cpp +++ b/llvm/lib/Object/Binary.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Magic.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Object/Error.h" #include "llvm/Object/MachOUniversal.h" @@ -44,10 +45,13 @@ MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; } Expected> object::createBinary(MemoryBufferRef Buffer, LLVMContext *Context, - bool InitContent) { - file_magic Type = identify_magic(Buffer.getBuffer()); + bool InitContent, + uint64_t Offset) { + file_magic Type = identify_magic_offset(Buffer.getBuffer(), Offset); switch (Type) { + case file_magic::adlt: + return ADLTFile::create(Buffer); case file_magic::archive: return Archive::create(Buffer); case file_magic::elf: @@ -74,7 +78,7 @@ Expected> object::createBinary(MemoryBufferRef Buffer, case file_magic::xcoff_object_32: case file_magic::xcoff_object_64: case file_magic::wasm_object: - return ObjectFile::createSymbolicFile(Buffer, Type, Context, InitContent); + return ObjectFile::createSymbolicFile(Buffer, Type, Context, InitContent, Offset); case file_magic::macho_universal_binary: return MachOUniversalBinary::create(Buffer); case file_magic::windows_resource: diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt index ba612e3d95e9..67e4a730d0f2 100644 --- a/llvm/lib/Object/CMakeLists.txt +++ b/llvm/lib/Object/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_component_library(LLVMObject + ADLTFile.cpp Archive.cpp ArchiveWriter.cpp Binary.cpp diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 1f342e55e77f..040eb106e0f3 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -59,15 +59,15 @@ ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) template static Expected>> -createPtr(MemoryBufferRef Object, bool InitContent) { - auto Ret = ELFObjectFile::create(Object, InitContent); +createPtr(MemoryBufferRef Object, bool InitContent, uint64_t Offset) { + auto Ret = ELFObjectFile::create(Object, InitContent, Offset); if (Error E = Ret.takeError()) return std::move(E); return std::make_unique>(std::move(*Ret)); } Expected> -ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) { +ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent, uint64_t Offset) { std::pair Ident = getElfArchType(Obj.getBuffer()); std::size_t MaxAlignment = @@ -79,16 +79,16 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) { if (Ident.first == ELF::ELFCLASS32) { if (Ident.second == ELF::ELFDATA2LSB) - return createPtr(Obj, InitContent); + return createPtr(Obj, InitContent, Offset); else if (Ident.second == ELF::ELFDATA2MSB) - return createPtr(Obj, InitContent); + return createPtr(Obj, InitContent, Offset); else return createError("Invalid ELF data"); } else if (Ident.first == ELF::ELFCLASS64) { if (Ident.second == ELF::ELFDATA2LSB) - return createPtr(Obj, InitContent); + return createPtr(Obj, InitContent, Offset); else if (Ident.second == ELF::ELFDATA2MSB) - return createPtr(Obj, InitContent); + return createPtr(Obj, InitContent, Offset); else return createError("Invalid ELF data"); } diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp index 1be8f11751be..6d3a5c663e87 100644 --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -131,13 +131,15 @@ Triple ObjectFile::makeTriple() const { Expected> ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type, - bool InitContent) { + bool InitContent, + uint64_t Offset) { StringRef Data = Object.getBuffer(); if (Type == file_magic::unknown) - Type = identify_magic(Data); + Type = identify_magic_offset(Data, Offset); switch (Type) { case file_magic::unknown: + case file_magic::adlt: case file_magic::bitcode: case file_magic::coff_cl_gl_object: case file_magic::archive: @@ -157,7 +159,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type, case file_magic::elf_executable: case file_magic::elf_shared_object: case file_magic::elf_core: - return createELFObjectFile(Object, InitContent); + return createELFObjectFile(Object, InitContent, Offset); case file_magic::macho_object: case file_magic::macho_executable: case file_magic::macho_fixed_virtual_memory_shared_lib: diff --git a/llvm/lib/Object/SymbolicFile.cpp b/llvm/lib/Object/SymbolicFile.cpp index 05f47cfbf2ff..acc8ca833b04 100644 --- a/llvm/lib/Object/SymbolicFile.cpp +++ b/llvm/lib/Object/SymbolicFile.cpp @@ -35,10 +35,11 @@ SymbolicFile::~SymbolicFile() = default; Expected> SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type, - LLVMContext *Context, bool InitContent) { + LLVMContext *Context, bool InitContent, + uint64_t Offset) { StringRef Data = Object.getBuffer(); if (Type == file_magic::unknown) - Type = identify_magic(Data); + Type = identify_magic_offset(Data, Offset); if (!isSymbolicFile(Type, Context)) return errorCodeToError(object_error::invalid_file_type); @@ -67,7 +68,7 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type, case file_magic::xcoff_object_32: case file_magic::xcoff_object_64: case file_magic::wasm_object: - return ObjectFile::createObjectFile(Object, Type, InitContent); + return ObjectFile::createObjectFile(Object, Type, InitContent, Offset); case file_magic::coff_import_library: return std::unique_ptr(new COFFImportFile(Object)); case file_magic::elf_relocatable: @@ -98,6 +99,7 @@ bool SymbolicFile::isSymbolicFile(file_magic Type, const LLVMContext *Context) { switch (Type) { case file_magic::bitcode: return Context != nullptr; + case file_magic::adlt: case file_magic::elf: case file_magic::elf_executable: case file_magic::elf_shared_object: diff --git a/llvm/tools/llvm-nm/Opts.td b/llvm/tools/llvm-nm/Opts.td index 60ac134269b3..ca1b990e425a 100644 --- a/llvm/tools/llvm-nm/Opts.td +++ b/llvm/tools/llvm-nm/Opts.td @@ -37,6 +37,8 @@ def special_syms : FF<"special-syms", "Do not filter special symbols from the ou def undefined_only : FF<"undefined-only", "Show only undefined symbols">; def version : FF<"version", "Display the version">; def without_aliases : FF<"without-aliases", "Exclude aliases from output">, Flags<[HelpHidden]>; +def adlt_list : FF<"adlt-list", "Display the file table in ADLT">; +defm adlt_show : Eq<"adlt-show", "Sepcify the file to read in ADLT">; // Mach-O specific options. def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-nm Mach-O Specific Options">; diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index f0def8b74e60..7afb9b420af3 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -21,6 +21,7 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" @@ -46,6 +47,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" +#include #include using namespace llvm; @@ -133,6 +135,9 @@ static bool PrintAddress = true; static bool MultipleFiles = false; static bool HadError = false; +static bool ADLTList = false; +static std::vector ADLTShow; + static StringRef ToolName; static void warn(Error Err, Twine FileName, Twine Context = Twine(), @@ -1954,6 +1959,55 @@ static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) { return true; } +static void dumpADLTList(ADLTFile *A) { + for (size_t I = 0; I < A->LibInfoNum; I++) { + outs() << "\n"; + outs() << std::to_string(I) << ": " << A->LibInfoNameList[I]; + } + outs() << "\n"; +} + +static void dumpADLT(ADLTFile *A, std::vector &SymbolList, + StringRef Filename, LLVMContext *ContextPtr) { + if (ADLTList) { + dumpADLTList(A); + return ; + } + + size_t Index = 0; + Error Err = Error::success(); + for (auto &C : A->children(Err)) { + bool ShouldDump = false; + for (StringRef ELFIndex : ADLTShow) { + unsigned InputIndex; + if (ELFIndex.getAsInteger(10, InputIndex) && ELFIndex != "A") { + error("Invalid value for --adlt-show\n"); + return ; + } + if (InputIndex >= A->LibInfoNum) { + error("The Index specified by --adlt-show is out of range\n"); + return ; + } + if (ELFIndex == "A" || InputIndex == Index) { + ShouldDump = true; + break; + } + } + Index++; + if (!ShouldDump) + continue; + Expected> ChildOrErr = C.getAsBinary(ContextPtr); + if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { + dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false, + !PrintFileName, Filename, + /*ArchitectureName=*/{}, O->getFileName(), + /*PrintArchiveName=*/false); + } + } + if (Err) + error(std::move(Err), A->getFileName()); +} + static void dumpArchiveMap(Archive *A, StringRef Filename) { Archive::symbol_iterator I = A->symbol_begin(); Archive::symbol_iterator E = A->symbol_end(); @@ -2267,7 +2321,9 @@ static std::vector dumpSymbolNamesFromFile(StringRef Filename) { return SymbolList; } Binary &Bin = *BinaryOrErr.get(); - if (Archive *A = dyn_cast(&Bin)) + if (ADLTFile *ADLT = dyn_cast(&Bin)) + dumpADLT(ADLT, SymbolList, Filename, ContextPtr); + else if (Archive *A = dyn_cast(&Bin)) dumpArchive(A, SymbolList, Filename, ContextPtr); else if (MachOUniversalBinary *UB = dyn_cast(&Bin)) dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr); @@ -2395,6 +2451,9 @@ int main(int argc, char **argv) { // XCOFF specific options. NoRsrc = Args.hasArg(OPT_no_rsrc); + ADLTList = Args.hasArg(OPT_adlt_list); + ADLTShow = Args.getAllArgValues(OPT_adlt_show_EQ); + // llvm-nm only reads binary files. if (error(sys::ChangeStdinToBinary())) return 1; diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td index 00d7d8ccff17..9610ede34114 100644 --- a/llvm/tools/llvm-objdump/ObjdumpOpts.td +++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td @@ -221,6 +221,12 @@ def x86_asm_syntax_att : Flag<["--"], "x86-asm-syntax=att">, def x86_asm_syntax_intel : Flag<["--"], "x86-asm-syntax=intel">, HelpText<"Emit Intel-style disassembly">; +def adlt_list : Flag<["--"], "adlt-list">, + HelpText<"Display all the file in ADLT">; + +def adlt_show_EQ : Joined<["--"], "adlt-show=">, + MetaVarName<"index">, + HelpText<"Specify the file to read in ADLT">; def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-objdump MachO Specific Options">; diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index fd83dc197fe9..643e03920f05 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -50,6 +50,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" @@ -232,6 +233,9 @@ static StringSet<> DisasmSymbolSet; StringSet<> objdump::FoundSectionSet; static StringRef ToolName; +static bool ADLTList; +static std::vector ADLTShow; + namespace { struct FilterResult { // True if the section should not be skipped. @@ -294,6 +298,17 @@ std::string objdump::getFileNameForError(const object::Archive::Child &C, return ""; } +std::string objdump::getADLTFileNameForError(const object::ADLTFile::Child &C, + unsigned Index) { + Expected NameOrErr = C.getName(); + if (NameOrErr) + return std::string(NameOrErr.get()); + // If we have an error getting the name then we print the index of the archive + // member. Since we are already in an error state, we just ignore this error. + consumeError(NameOrErr.takeError()); + return ""; +} + void objdump::reportWarning(const Twine &Message, StringRef File) { // Output order between errs() and outs() matters especially for archive // files where the output is per member object. @@ -2642,6 +2657,127 @@ static void dumpObject(const COFFImportFile *I, const Archive *A, printCOFFSymbolTable(*I); } +static void dumpADLTELFObject(ObjectFile *O, const ADLTFile *A = nullptr, + const ADLTFile::Child *C = nullptr) { + // Avoid other output when using a raw option. + if (!RawClangAST) { + outs() << '\n'; + if (A) + outs() << A->getFileName() << "(" << O->getFileName() << ")"; + else + outs() << O->getFileName(); + outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n"; + } + + if (HasStartAddressFlag || HasStopAddressFlag) + checkForInvalidStartStopAddress(O, StartAddress, StopAddress); + + // Note: the order here matches GNU objdump for compatability. + StringRef ArchiveName = A ? A->getFileName() : ""; + // if (ArchiveHeaders && !MachOOpt && C) + // printArchiveChild(ArchiveName, *C); + if (FileHeaders) + printFileHeaders(O); + if (PrivateHeaders || FirstPrivateHeader) + printPrivateFileHeaders(O, FirstPrivateHeader); + if (SectionHeaders) + printSectionHeaders(*O); + if (SymbolTable) + printSymbolTable(*O, ArchiveName); + if (DynamicSymbolTable) + printSymbolTable(*O, ArchiveName, /*ArchitectureName=*/"", + /*DumpDynamic=*/true); + if (DwarfDumpType != DIDT_Null) { + std::unique_ptr DICtx = DWARFContext::create(*O); + // Dump the complete DWARF structure. + DIDumpOptions DumpOpts; + DumpOpts.DumpType = DwarfDumpType; + DICtx->dump(outs(), DumpOpts); + } + if (Relocations && !Disassemble) + printRelocations(O); + if (DynamicRelocations) + printDynamicRelocations(O); + if (SectionContents) + printSectionContents(O); + if (Disassemble) + disassembleObject(O, Relocations); + if (UnwindInfo) + printUnwindInfo(O); + + // Mach-O specific options: + if (ExportsTrie) + printExportsTrie(O); + if (Rebase) + printRebaseTable(O); + if (Bind) + printBindTable(O); + if (LazyBind) + printLazyBindTable(O); + if (WeakBind) + printWeakBindTable(O); + + // Other special sections: + if (RawClangAST) + printRawClangAST(O); + if (FaultMapSection) + printFaultMaps(O); + if (Offloading) + dumpOffloadBinary(*O); +} + +static void dumpADLTList(const ADLTFile *A) { + for (size_t I = 0; I < A->LibInfoNum; I++) { + outs() << "\n"; + outs() << std::to_string(I) << ": " << A->LibInfoNameList[I]; + } + outs() << "\n"; +} + +/// Dump each object file in \a a; +static void dumpADLT(const ADLTFile *A) { + Error Err = Error::success(); + if (ADLTList) { + dumpADLTList(A); + return ; + } + unsigned I = -1; + for (auto &C : A->children(Err)) { + ++I; + bool ShouldDump = false; + for (StringRef ELFIndex : ADLTShow) { + unsigned InputIndex; + if (ELFIndex.getAsInteger(10, InputIndex) && ELFIndex != "A") { + reportCmdLineError("Invalid value for --adlt-show\n"); + return ; + } + if (InputIndex >= A->LibInfoNum) { + reportCmdLineError("The Index specified by --adlt-show is out of range\n"); + return ; + } + if (ELFIndex == "A" || InputIndex == I) { + ShouldDump = true; + break; + } + } + if (!ShouldDump) + continue; + Expected> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + reportError(std::move(E), getADLTFileNameForError(C, I), A->getFileName()); + continue; + } + if (ObjectFile *O = dyn_cast(&*ChildOrErr.get())) + dumpADLTELFObject(O, A, &C); + else + reportError(errorCodeToError(object_error::invalid_file_type), + A->getFileName()); + } + if (Err) + reportError(std::move(Err), A->getFileName()); +} + /// Dump each object file in \a a; static void dumpArchive(const Archive *A) { Error Err = Error::success(); @@ -2680,7 +2816,9 @@ static void dumpInput(StringRef file) { OwningBinary OBinary = unwrapOrError(createBinary(file), file); Binary &Binary = *OBinary.getBinary(); - if (Archive *A = dyn_cast(&Binary)) + if (ADLTFile *ADLT = dyn_cast(&Binary)) + dumpADLT(ADLT); + else if (Archive *A = dyn_cast(&Binary)) dumpArchive(A); else if (ObjectFile *O = dyn_cast(&Binary)) dumpObject(O); @@ -2830,6 +2968,9 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) { if (DbgVariables == DVInvalid) invalidArgValue(A); } + ADLTList = InputArgs.hasArg(OBJDUMP_adlt_list); + ADLTShow = InputArgs.getAllArgValues(OBJDUMP_adlt_show_EQ); + parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent); parseMachOOptions(InputArgs); @@ -2956,7 +3097,7 @@ int main(int argc, char **argv) { !DisassembleSymbols.empty()) Disassemble = true; - if (!ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null && + if (!ADLTList && !ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null && !DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST && !Relocations && !SectionHeaders && !SectionContents && !SymbolTable && !DynamicSymbolTable && !UnwindInfo && !FaultMapSection && !Offloading && diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index c64c042d513e..87e1bb5c8cdd 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -148,6 +149,8 @@ T unwrapOrError(Expected EO, Ts &&... Args) { std::string getFileNameForError(const object::Archive::Child &C, unsigned Index); +std::string getADLTFileNameForError(const object::ADLTFile::Child &C, + unsigned Index); SymbolInfoTy createSymbolInfo(const object::ObjectFile &Obj, const object::SymbolRef &Symbol); diff --git a/llvm/tools/llvm-readobj/ADLTDumper.cpp b/llvm/tools/llvm-readobj/ADLTDumper.cpp new file mode 100644 index 000000000000..601e81a8d08d --- /dev/null +++ b/llvm/tools/llvm-readobj/ADLTDumper.cpp @@ -0,0 +1,13 @@ +#include "ADLTDumper.h" +#include + +Expected> ADLTDumper::createADLTDumper(const ADLTFile &ADLTObject, ScopedPrinter &Writer) { + return std::make_unique(ADLTObject, Writer); +} + +void ADLTDumper::printADLTList() { + for (size_t I = 0; I < A.LibInfoNum; I++) { + W.startLine() << "\n"; + W.printString(std::to_string(I), A.LibInfoNameList[I]); + } +} \ No newline at end of file diff --git a/llvm/tools/llvm-readobj/ADLTDumper.h b/llvm/tools/llvm-readobj/ADLTDumper.h new file mode 100644 index 000000000000..a6ec03136473 --- /dev/null +++ b/llvm/tools/llvm-readobj/ADLTDumper.h @@ -0,0 +1,26 @@ +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/ADLTFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ScopedPrinter.h" +#include + +using namespace llvm; +using namespace llvm::object; +using namespace ELF; + +class ADLTDumper { + LLVM_ELF_IMPORT_TYPES_ELFT(ELF64LE) + +public: + const ADLTFile &A; + ScopedPrinter &W; + + ADLTDumper(const ADLTFile &ADLTObject, ScopedPrinter &Writer) : A(ADLTObject), W(Writer) {} + static Expected> createADLTDumper(const ADLTFile &ADLTObject, ScopedPrinter &Writer); + + void printADLTList(); + void printADLTProgramHeaders(); + void printADLTSectionHeaders(); +}; diff --git a/llvm/tools/llvm-readobj/CMakeLists.txt b/llvm/tools/llvm-readobj/CMakeLists.txt index 9d2d8882ee83..143d03fd16a4 100644 --- a/llvm/tools/llvm-readobj/CMakeLists.txt +++ b/llvm/tools/llvm-readobj/CMakeLists.txt @@ -16,6 +16,7 @@ tablegen(LLVM Opts.inc -gen-opt-parser-defs) add_public_tablegen_target(ReadobjOptsTableGen) add_llvm_tool(llvm-readobj + ADLTDumper.cpp ARMWinEHPrinter.cpp COFFDumper.cpp COFFImportDumper.cpp diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index c9a239f785d2..c75dd3f74712 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -33,6 +33,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MsgPackDocument.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" @@ -554,6 +555,9 @@ public: void printFileSummary(StringRef FileStr, ObjectFile &Obj, ArrayRef InputFilenames, const Archive *A) override; + void printFileSummary(StringRef FileStr, ObjectFile &Obj, + ArrayRef InputFilenames, + const ADLTFile *A) override; void printFileHeaders() override; void printGroupSections() override; void printRelocations() override; @@ -719,6 +723,9 @@ public: void printFileSummary(StringRef FileStr, ObjectFile &Obj, ArrayRef InputFilenames, const Archive *A) override; + void printFileSummary(StringRef FileStr, ObjectFile &Obj, + ArrayRef InputFilenames, + const ADLTFile *A) override; private: std::unique_ptr FileScope; @@ -3311,6 +3318,16 @@ void GNUELFDumper::printFileSummary(StringRef FileStr, ObjectFile &Obj, } } +template +void GNUELFDumper::printFileSummary(StringRef FileStr, ObjectFile &Obj, + ArrayRef InputFilenames, + const ADLTFile *A) { + if (InputFilenames.size() > 1 || A) { + this->W.startLine() << "\n"; + this->W.printString("File", FileStr); + } +} + template void GNUELFDumper::printFileHeaders() { const Elf_Ehdr &e = this->Obj.getHeader(); OS << "ELF Header:\n"; @@ -7494,3 +7511,18 @@ void JSONELFDumper::printFileSummary(StringRef FileStr, ObjectFile &Obj, std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); this->printLoadName(); } + +template +void JSONELFDumper::printFileSummary(StringRef FileStr, ObjectFile &Obj, + ArrayRef InputFilenames, + const ADLTFile *A) { + FileScope = std::make_unique(this->W, FileStr); + DictScope D(this->W, "FileSummary"); + this->W.printString("File", FileStr); + this->W.printString("Format", Obj.getFileFormatName()); + this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch())); + this->W.printString( + "AddressSize", + std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); + this->printLoadName(); +} diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp index 6dde3725b4d6..6c18209f8954 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.cpp +++ b/llvm/tools/llvm-readobj/ObjDumper.cpp @@ -13,6 +13,7 @@ #include "ObjDumper.h" #include "llvm-readobj.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" @@ -20,6 +21,7 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" #include +#include namespace llvm { @@ -98,6 +100,18 @@ void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj, this->printLoadName(); } +void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj, + ArrayRef InputFilenames, + const object::ADLTFile *A) { + W.startLine() << "\n"; + W.printString("File", FileStr); + W.printString("Format", Obj.getFileFormatName()); + W.printString("Arch", Triple::getArchTypeName(Obj.getArch())); + W.printString("AddressSize", + std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); + this->printLoadName(); +} + static std::vector getSectionRefsByNameOrIndex(const object::ObjectFile &Obj, ArrayRef Sections) { diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 292efd2ae350..931dfd99217d 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" @@ -75,6 +76,9 @@ public: virtual void printFileSummary(StringRef FileStr, object::ObjectFile &Obj, ArrayRef InputFilenames, const object::Archive *A); + virtual void printFileSummary(StringRef FileStr, object::ObjectFile &Obj, + ArrayRef InputFilenames, + const object::ADLTFile *A); virtual void printFileHeaders() = 0; virtual void printSectionHeaders() = 0; virtual void printRelocations() = 0; diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index 4687fc71245f..f95b39eb1788 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -44,6 +44,8 @@ defm string_dump : Eq<"string-dump", "Display the specified section(s) as a list def string_table : FF<"string-table", "Display the string table (only for XCOFF now)">; def symbols : FF<"symbols", "Display the symbol table. Also display the dynamic symbol table when using GNU output style for ELF">; def unwind : FF<"unwind", "Display unwind information">; +def adlt_list : FF<"adlt-list", "Display the file table in ADLT">; +defm adlt_show : Eq<"adlt-show", "Specify the file to read in ADLT">; // ELF specific options. def grp_elf : OptionGroup<"kind">, HelpText<"OPTIONS (ELF specific)">; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index e1ebbeb41f28..45af0c9589ca 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -18,6 +18,7 @@ // //===----------------------------------------------------------------------===// +#include "ADLTDumper.h" #include "llvm-readobj.h" #include "ObjDumper.h" #include "WindowsResourceDumper.h" @@ -25,6 +26,7 @@ #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Object/ADLTFile.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ELFObjectFile.h" @@ -47,6 +49,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/WithColor.h" +#include using namespace llvm; using namespace llvm::object; @@ -163,6 +166,9 @@ static bool COFFTLSDirectory; // XCOFF specific options. static bool XCOFFAuxiliaryHeader; +static bool ADLTList; +static std::vector ADLTShow; + OutputStyleTy Output = OutputStyleTy::LLVM; static std::vector InputFilenames; } // namespace opts @@ -303,6 +309,9 @@ static void parseOptions(const opt::InputArgList &Args) { // XCOFF specific options. opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header); + opts::ADLTList = Args.hasArg(OPT_adlt_list); + opts::ADLTShow = Args.getAllArgValues(OPT_adlt_show_EQ); + opts::InputFilenames = Args.getAllArgValues(OPT_INPUT); } @@ -344,6 +353,231 @@ createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) { "unsupported object file format"); } +static void dumpADLTObject(const ADLTFile &Obj, ScopedPrinter &Writer) { + ADLTDumper *Dumper; + Expected> DumperOrErr = ADLTDumper::createADLTDumper(Obj, Writer); + if (!DumperOrErr) + reportError(DumperOrErr.takeError(), Obj.getFileName()); + Dumper = (*DumperOrErr).get(); + + if (opts::ADLTList) + Dumper->printADLTList(); +} + +/// Dumps the specified object file. +static void dumpADLTELFObject(ObjectFile &Obj, ScopedPrinter &Writer, + const ADLTFile *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; + Optional SymComp; + Expected> DumperOrErr = createDumper(Obj, Writer); + if (!DumperOrErr) + reportError(DumperOrErr.takeError(), FileStr); + Dumper = (*DumperOrErr).get(); + + if (!opts::SortKeys.empty()) { + if (Dumper->canCompareSymbols()) { + SymComp = SymbolComparator(); + for (SortSymbolKeyTy Key : opts::SortKeys) { + switch (Key) { + case NAME: + SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) { + return Dumper->compareSymbolsByName(LHS, RHS); + }); + break; + case TYPE: + SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) { + return Dumper->compareSymbolsByType(LHS, RHS); + }); + break; + case UNKNOWN: + llvm_unreachable("Unsupported sort key"); + } + } + + } else { + reportWarning(createStringError( + errc::invalid_argument, + "--sort-symbols is not supported yet for this format"), + FileStr); + } + } + Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A); + + if (opts::FileHeaders) + Dumper->printFileHeaders(); + + if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader) + Dumper->printAuxiliaryHeader(); + + // 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, SymComp); + 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 (opts::StringTable) + Dumper->printStringTable(); + 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::BBAddrMap) + Dumper->printBBAddrMaps(); + 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::CGProfile) + Dumper->printCGProfile(); + } + if (opts::PrintStackMap) + Dumper->printStackMap(); + if (opts::PrintStackSizes) + Dumper->printStackSizes(); +} + +/// Dumps each object file in \a Arc; +static void dumpADLT(const ADLTFile *Arc, ScopedPrinter &Writer) { + Error Err = Error::success(); + if (opts::ADLTList) { + dumpADLTObject(*Arc, Writer); + return ; + } + size_t Index = 0; + for (auto &Child : Arc->children(Err)) { + bool ShouldDump = false; + for (StringRef ELFIndex : opts::ADLTShow) { + unsigned InputIndex; + if (ELFIndex.getAsInteger(10, InputIndex) && ELFIndex != "A") { + error("Invalid value for --adlt-show\n"); + return ; + } + if (InputIndex >= Arc->LibInfoNum) { + error("The Index specified by --adlt-show is out of range\n"); + return ; + } + if (ELFIndex == "A" || InputIndex == Index) { + ShouldDump = true; + break; + } + } + Index++; + if (!ShouldDump) + continue; + Expected> 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(Bin)) + dumpADLTELFObject(*Obj, Writer, Arc); + else if (COFFImportFile *Imp = dyn_cast(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 the specified object file. static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, const Archive *A = nullptr) { @@ -580,7 +814,9 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) { reportError(BinaryOrErr.takeError(), File); std::unique_ptr Bin = std::move(*BinaryOrErr); - if (Archive *Arc = dyn_cast(Bin.get())) + if (ADLTFile *ADLT = dyn_cast(Bin.get())) + dumpADLT(ADLT, Writer); + else if (Archive *Arc = dyn_cast(Bin.get())) dumpArchive(Arc, Writer); else if (MachOUniversalBinary *UBinary = dyn_cast(Bin.get())) -- Gitee