diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:17:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:17:04 +0000 |
commit | b915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch) | |
tree | 98b8f811c7aff2547cab8642daf372d6c59502fb /include/llvm/Object | |
parent | 6421cca32f69ac849537a3cff78c352195e99f1b (diff) |
Vendor import of llvm trunk r290819:vendor/llvm/llvm-trunk-r290819
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=311116
svn path=/vendor/llvm/llvm-trunk-r290819/; revision=311117; tag=vendor/llvm/llvm-trunk-r290819
Diffstat (limited to 'include/llvm/Object')
-rw-r--r-- | include/llvm/Object/Archive.h | 106 | ||||
-rw-r--r-- | include/llvm/Object/ArchiveWriter.h | 14 | ||||
-rw-r--r-- | include/llvm/Object/Binary.h | 4 | ||||
-rw-r--r-- | include/llvm/Object/COFF.h | 52 | ||||
-rw-r--r-- | include/llvm/Object/COFFImportFile.h | 4 | ||||
-rw-r--r-- | include/llvm/Object/ELF.h | 539 | ||||
-rw-r--r-- | include/llvm/Object/ELFObjectFile.h | 160 | ||||
-rw-r--r-- | include/llvm/Object/ELFTypes.h | 34 | ||||
-rw-r--r-- | include/llvm/Object/Error.h | 1 | ||||
-rw-r--r-- | include/llvm/Object/IRObjectFile.h | 39 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 15 | ||||
-rw-r--r-- | include/llvm/Object/MachOUniversal.h | 18 | ||||
-rw-r--r-- | include/llvm/Object/ModuleSummaryIndexObjectFile.h | 19 | ||||
-rw-r--r-- | include/llvm/Object/ModuleSymbolTable.h | 61 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 7 | ||||
-rw-r--r-- | include/llvm/Object/RelocVisitor.h | 47 | ||||
-rw-r--r-- | include/llvm/Object/StackMapParser.h | 35 | ||||
-rw-r--r-- | include/llvm/Object/SymbolSize.h | 11 | ||||
-rw-r--r-- | include/llvm/Object/SymbolicFile.h | 13 | ||||
-rw-r--r-- | include/llvm/Object/Wasm.h | 99 |
20 files changed, 798 insertions, 480 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index cfba2567371a..08128b0c2515 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -18,35 +18,59 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" +#include "llvm/Support/Chrono.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" namespace llvm { namespace object { -struct ArchiveMemberHeader { - char Name[16]; - char LastModified[12]; - char UID[6]; - char GID[6]; - char AccessMode[8]; - char Size[10]; ///< Size of data, not including header or padding. - char Terminator[2]; + +class Archive; + +class ArchiveMemberHeader { +public: + friend class Archive; + ArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr, + uint64_t Size, Error *Err); + // ArchiveMemberHeader() = default; /// Get the name without looking up long names. - llvm::StringRef getName() const; + Expected<llvm::StringRef> getRawName() const; + + /// Get the name looking up long names. + Expected<llvm::StringRef> getName(uint64_t Size) const; /// Members are not larger than 4GB. - ErrorOr<uint32_t> getSize() const; + Expected<uint32_t> getSize() const; - sys::fs::perms getAccessMode() const; - sys::TimeValue getLastModified() const; + Expected<sys::fs::perms> getAccessMode() const; + Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const; llvm::StringRef getRawLastModified() const { - return StringRef(LastModified, sizeof(LastModified)).rtrim(' '); + return StringRef(ArMemHdr->LastModified, + sizeof(ArMemHdr->LastModified)).rtrim(' '); + } + Expected<unsigned> getUID() const; + Expected<unsigned> getGID() const; + + // This returns the size of the private struct ArMemHdrType + uint64_t getSizeOf() const { + return sizeof(ArMemHdrType); } - unsigned getUID() const; - unsigned getGID() const; + +private: + struct ArMemHdrType { + char Name[16]; + char LastModified[12]; + char UID[6]; + char GID[6]; + char AccessMode[8]; + char Size[10]; ///< Size of data, not including header or padding. + char Terminator[2]; + }; + Archive const *Parent; + ArMemHdrType const *ArMemHdr; }; class Archive : public Binary { @@ -55,52 +79,50 @@ public: class Child { friend Archive; const Archive *Parent; + friend ArchiveMemberHeader; + ArchiveMemberHeader Header; /// \brief Includes header but not padding byte. StringRef Data; /// \brief Offset from Data to the start of the file. uint16_t StartOfFile; - const ArchiveMemberHeader *getHeader() const { - return reinterpret_cast<const ArchiveMemberHeader *>(Data.data()); - } - - bool isThinMember() const; + Expected<bool> isThinMember() const; public: - Child(const Archive *Parent, const char *Start, std::error_code *EC); + Child(const Archive *Parent, const char *Start, Error *Err); Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile); bool operator ==(const Child &other) const { - assert(Parent == other.Parent); + assert(!Parent || !other.Parent || Parent == other.Parent); return Data.begin() == other.Data.begin(); } const Archive *getParent() const { return Parent; } - ErrorOr<Child> getNext() const; + Expected<Child> getNext() const; - ErrorOr<StringRef> getName() const; - ErrorOr<std::string> getFullName() const; - StringRef getRawName() const { return getHeader()->getName(); } - sys::TimeValue getLastModified() const { - return getHeader()->getLastModified(); + Expected<StringRef> getName() const; + Expected<std::string> getFullName() const; + Expected<StringRef> getRawName() const { return Header.getRawName(); } + Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const { + return Header.getLastModified(); } StringRef getRawLastModified() const { - return getHeader()->getRawLastModified(); + return Header.getRawLastModified(); } - unsigned getUID() const { return getHeader()->getUID(); } - unsigned getGID() const { return getHeader()->getGID(); } - sys::fs::perms getAccessMode() const { - return getHeader()->getAccessMode(); + Expected<unsigned> getUID() const { return Header.getUID(); } + Expected<unsigned> getGID() const { return Header.getGID(); } + Expected<sys::fs::perms> getAccessMode() const { + return Header.getAccessMode(); } /// \return the size of the archive member without the header or padding. - ErrorOr<uint64_t> getSize() const; + Expected<uint64_t> getSize() const; /// \return the size in the archive header for this member. - ErrorOr<uint64_t> getRawSize() const; + Expected<uint64_t> getRawSize() const; - ErrorOr<StringRef> getBuffer() const; + Expected<StringRef> getBuffer() const; uint64_t getChildOffset() const; - ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; + Expected<MemoryBufferRef> getMemoryBufferRef() const; Expected<std::unique_ptr<Binary>> getAsBinary(LLVMContext *Context = nullptr) const; @@ -131,12 +153,12 @@ public: // iteration. And if there is an error break out of the loop. child_iterator &operator++() { // Preincrement assert(E && "Can't increment iterator with no Error attached"); + ErrorAsOutParameter ErrAsOutParam(E); if (auto ChildOrErr = C.getNext()) C = *ChildOrErr; else { - ErrorAsOutParameter ErrAsOutParam(*E); C = C.getParent()->child_end().C; - *E = errorCodeToError(ChildOrErr.getError()); + *E = ChildOrErr.takeError(); E = nullptr; } return *this; @@ -158,7 +180,7 @@ public: , SymbolIndex(symi) , StringIndex(stri) {} StringRef getName() const; - ErrorOr<Child> getMember() const; + Expected<Child> getMember() const; Symbol getNext() const; }; @@ -218,8 +240,10 @@ public: // check if a symbol is in the archive Expected<Optional<Child>> findSym(StringRef name) const; + bool isEmpty() const; bool hasSymbolTable() const; StringRef getSymbolTable() const { return SymbolTable; } + StringRef getStringTable() const { return StringTable; } uint32_t getNumberOfSymbols() const; std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() { diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 55b58fac4f66..3e84a5814d79 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -22,21 +22,11 @@ namespace llvm { struct NewArchiveMember { std::unique_ptr<MemoryBuffer> Buf; - sys::TimeValue ModTime = sys::TimeValue::PosixZeroTime(); + sys::TimePoint<std::chrono::seconds> ModTime; unsigned UID = 0, GID = 0, Perms = 0644; + bool IsNew = false; NewArchiveMember() = default; - NewArchiveMember(NewArchiveMember &&Other) - : Buf(std::move(Other.Buf)), ModTime(Other.ModTime), UID(Other.UID), - GID(Other.GID), Perms(Other.Perms) {} - NewArchiveMember &operator=(NewArchiveMember &&Other) { - Buf = std::move(Other.Buf); - ModTime = Other.ModTime; - UID = Other.UID; - GID = Other.GID; - Perms = Other.Perms; - return *this; - } NewArchiveMember(MemoryBufferRef BufRef); static Expected<NewArchiveMember> diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 5dff5406fcdd..00d06e3c7437 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -59,6 +59,8 @@ protected: ID_MachO64L, // MachO 64-bit, little endian ID_MachO64B, // MachO 64-bit, big endian + ID_Wasm, + ID_EndObjects }; @@ -115,6 +117,8 @@ public: return TypeID == ID_COFF; } + bool isWasm() const { return TypeID == ID_Wasm; } + bool isCOFFImportFile() const { return TypeID == ID_COFFImportFile; } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index dcc58b06e228..696042d29dab 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_COFF_H #include "llvm/ADT/PointerUnion.h" +#include "llvm/DebugInfo/CodeView/CVDebugRecord.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" @@ -161,14 +162,6 @@ struct data_directory { support::ulittle32_t Size; }; -struct import_directory_table_entry { - support::ulittle32_t ImportLookupTableRVA; - support::ulittle32_t TimeDateStamp; - support::ulittle32_t ForwarderChain; - support::ulittle32_t NameRVA; - support::ulittle32_t ImportAddressTableRVA; -}; - struct debug_directory { support::ulittle32_t Characteristics; support::ulittle32_t TimeDateStamp; @@ -180,15 +173,6 @@ struct debug_directory { support::ulittle32_t PointerToRawData; }; -/// Information that is resent in debug_directory::AddressOfRawData if Type is -/// IMAGE_DEBUG_TYPE_CODEVIEW. -struct debug_pdb_info { - support::ulittle32_t Signature; - uint8_t Guid[16]; - support::ulittle32_t Age; - // PDBFileName: The null-terminated PDB file name follows. -}; - template <typename IntTy> struct import_lookup_table_entry { IntTy Data; @@ -534,6 +518,10 @@ struct coff_import_directory_table_entry { support::ulittle32_t ForwarderChain; support::ulittle32_t NameRVA; support::ulittle32_t ImportAddressTableRVA; + bool isNull() const { + return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && + ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0; + } }; template <typename IntTy> @@ -633,7 +621,7 @@ private: const coff_symbol32 *SymbolTable32; const char *StringTable; uint32_t StringTableSize; - const import_directory_table_entry *ImportDirectory; + const coff_import_directory_table_entry *ImportDirectory; const delay_import_directory_table_entry *DelayImportDirectory; uint32_t NumberOfDelayImportDirectory; const export_directory_table_entry *ExportDirectory; @@ -711,17 +699,23 @@ public: return COFFBigObjHeader->PointerToSymbolTable; llvm_unreachable("no COFF header!"); } - uint32_t getNumberOfSymbols() const { + uint32_t getRawNumberOfSymbols() const { if (COFFHeader) return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; if (COFFBigObjHeader) return COFFBigObjHeader->NumberOfSymbols; llvm_unreachable("no COFF header!"); } + uint32_t getNumberOfSymbols() const { + if (!SymbolTable16 && !SymbolTable32) + return 0; + return getRawNumberOfSymbols(); + } protected: void moveSymbolNext(DataRefImpl &Symb) const override; Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; @@ -752,8 +746,8 @@ protected: public: COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); - basic_symbol_iterator symbol_begin_impl() const override; - basic_symbol_iterator symbol_end_impl() const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; section_iterator section_begin() const override; section_iterator section_end() const override; @@ -872,14 +866,14 @@ public: /// Get PDB information out of a codeview debug directory entry. std::error_code getDebugPDBInfo(const debug_directory *DebugDir, - const debug_pdb_info *&Info, + const codeview::DebugInfo *&Info, StringRef &PDBFileName) const; /// Get PDB information from an executable. If the information is not present, /// Info will be set to nullptr and PDBFileName will be empty. An error is /// returned only on corrupt object files. Convenience accessor that can be /// used if the debug directory is not already handy. - std::error_code getDebugPDBInfo(const debug_pdb_info *&Info, + std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info, StringRef &PDBFileName) const; bool isRelocatableObject() const override; @@ -892,8 +886,8 @@ public: class ImportDirectoryEntryRef { public: ImportDirectoryEntryRef() : OwningObject(nullptr) {} - ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I, - const COFFObjectFile *Owner) + ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, + uint32_t I, const COFFObjectFile *Owner) : ImportTable(Table), Index(I), OwningObject(Owner) {} bool operator==(const ImportDirectoryEntryRef &Other) const; @@ -903,15 +897,19 @@ public: imported_symbol_iterator imported_symbol_end() const; iterator_range<imported_symbol_iterator> imported_symbols() const; + imported_symbol_iterator lookup_table_begin() const; + imported_symbol_iterator lookup_table_end() const; + iterator_range<imported_symbol_iterator> lookup_table_symbols() const; + std::error_code getName(StringRef &Result) const; std::error_code getImportLookupTableRVA(uint32_t &Result) const; std::error_code getImportAddressTableRVA(uint32_t &Result) const; std::error_code - getImportTableEntry(const import_directory_table_entry *&Result) const; + getImportTableEntry(const coff_import_directory_table_entry *&Result) const; private: - const import_directory_table_entry *ImportTable; + const coff_import_directory_table_entry *ImportTable; uint32_t Index; const COFFObjectFile *OwningObject; }; diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h index b04a44ea60d2..4192fe7e5c90 100644 --- a/include/llvm/Object/COFFImportFile.h +++ b/include/llvm/Object/COFFImportFile.h @@ -47,11 +47,11 @@ public: return SymbolRef::SF_Global; } - basic_symbol_iterator symbol_begin_impl() const override { + basic_symbol_iterator symbol_begin() const override { return BasicSymbolRef(DataRefImpl(), this); } - basic_symbol_iterator symbol_end_impl() const override { + basic_symbol_iterator symbol_end() const override { DataRefImpl Symb; Symb.p = isCode() ? 2 : 1; return BasicSymbolRef(Symb, this); diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 80b8be03810c..aaa79ae70f01 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -33,27 +33,29 @@ getElfArchType(StringRef Object) { (uint8_t)Object[ELF::EI_DATA]); } +static inline Error createError(StringRef Err) { + return make_error<StringError>(Err, object_error::parse_failed); +} + template <class ELFT> class ELFFile { public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef typename std::conditional<ELFT::Is64Bits, - uint64_t, uint32_t>::type uintX_t; - - typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; - typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; - typedef Elf_Sym_Impl<ELFT> Elf_Sym; - typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; - typedef Elf_Phdr_Impl<ELFT> Elf_Phdr; - typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; - typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; - typedef Elf_Verdef_Impl<ELFT> Elf_Verdef; - typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; - typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; - typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; - typedef Elf_Versym_Impl<ELFT> Elf_Versym; - typedef Elf_Hash_Impl<ELFT> Elf_Hash; - typedef Elf_GnuHash_Impl<ELFT> Elf_GnuHash; + typedef typename ELFT::uint uintX_t; + typedef typename ELFT::Ehdr Elf_Ehdr; + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::Sym Elf_Sym; + typedef typename ELFT::Dyn Elf_Dyn; + typedef typename ELFT::Phdr Elf_Phdr; + typedef typename ELFT::Rel Elf_Rel; + typedef typename ELFT::Rela Elf_Rela; + typedef typename ELFT::Verdef Elf_Verdef; + typedef typename ELFT::Verdaux Elf_Verdaux; + typedef typename ELFT::Verneed Elf_Verneed; + typedef typename ELFT::Vernaux Elf_Vernaux; + typedef typename ELFT::Versym Elf_Versym; + typedef typename ELFT::Hash Elf_Hash; + typedef typename ELFT::GnuHash Elf_GnuHash; typedef typename ELFT::DynRange Elf_Dyn_Range; typedef typename ELFT::ShdrRange Elf_Shdr_Range; typedef typename ELFT::SymRange Elf_Sym_Range; @@ -71,20 +73,24 @@ private: StringRef Buf; - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable = nullptr; - StringRef DotShstrtab; // Section header string table. - public: - template<typename T> - const T *getEntry(uint32_t Section, uint32_t Entry) const; + const Elf_Ehdr *getHeader() const { + return reinterpret_cast<const Elf_Ehdr *>(base()); + } + template <typename T> - const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; + Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; + template <typename T> + Expected<const T *> getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const; - ErrorOr<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; + Expected<StringRef> getStringTable(const Elf_Shdr *Section) const; + Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; + Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, + Elf_Shdr_Range Sections) const; - ErrorOr<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; + Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; + Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, + Elf_Shdr_Range Sections) const; void VerifyStrTab(const Elf_Shdr *sh) const; @@ -93,118 +99,66 @@ public: SmallVectorImpl<char> &Result) const; /// \brief Get the symbol for a given relocation. - const Elf_Sym *getRelocationSymbol(const Elf_Rel *Rel, - const Elf_Shdr *SymTab) const; + Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, + const Elf_Shdr *SymTab) const; - ELFFile(StringRef Object, std::error_code &EC); + ELFFile(StringRef Object); bool isMipsELF64() const { - return Header->e_machine == ELF::EM_MIPS && - Header->getFileClass() == ELF::ELFCLASS64; + return getHeader()->e_machine == ELF::EM_MIPS && + getHeader()->getFileClass() == ELF::ELFCLASS64; } bool isMips64EL() const { - return Header->e_machine == ELF::EM_MIPS && - Header->getFileClass() == ELF::ELFCLASS64 && - Header->getDataEncoding() == ELF::ELFDATA2LSB; + return isMipsELF64() && + getHeader()->getDataEncoding() == ELF::ELFDATA2LSB; } - const Elf_Shdr *section_begin() const; - const Elf_Shdr *section_end() const; - Elf_Shdr_Range sections() const { - return makeArrayRef(section_begin(), section_end()); - } + Expected<Elf_Shdr_Range> sections() const; - const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const { + Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { if (!Sec) - return nullptr; - if (Sec->sh_entsize != sizeof(Elf_Sym)) - report_fatal_error("Invalid symbol size"); - return reinterpret_cast<const Elf_Sym *>(base() + Sec->sh_offset); - } - const Elf_Sym *symbol_end(const Elf_Shdr *Sec) const { - if (!Sec) - return nullptr; - uint64_t Size = Sec->sh_size; - if (Size % sizeof(Elf_Sym)) - report_fatal_error("Invalid symbol table size"); - return symbol_begin(Sec) + Size / sizeof(Elf_Sym); - } - Elf_Sym_Range symbols(const Elf_Shdr *Sec) const { - return makeArrayRef(symbol_begin(Sec), symbol_end(Sec)); + return makeArrayRef<Elf_Sym>(nullptr, nullptr); + return getSectionContentsAsArray<Elf_Sym>(Sec); } - const Elf_Rela *rela_begin(const Elf_Shdr *sec) const { - if (sec->sh_entsize != sizeof(Elf_Rela)) - report_fatal_error("Invalid relocation entry size"); - return reinterpret_cast<const Elf_Rela *>(base() + sec->sh_offset); + Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const { + return getSectionContentsAsArray<Elf_Rela>(Sec); } - const Elf_Rela *rela_end(const Elf_Shdr *sec) const { - uint64_t Size = sec->sh_size; - if (Size % sizeof(Elf_Rela)) - report_fatal_error("Invalid relocation table size"); - return rela_begin(sec) + Size / sizeof(Elf_Rela); - } - - Elf_Rela_Range relas(const Elf_Shdr *Sec) const { - return makeArrayRef(rela_begin(Sec), rela_end(Sec)); - } - - const Elf_Rel *rel_begin(const Elf_Shdr *sec) const { - if (sec->sh_entsize != sizeof(Elf_Rel)) - report_fatal_error("Invalid relocation entry size"); - return reinterpret_cast<const Elf_Rel *>(base() + sec->sh_offset); - } - - const Elf_Rel *rel_end(const Elf_Shdr *sec) const { - uint64_t Size = sec->sh_size; - if (Size % sizeof(Elf_Rel)) - report_fatal_error("Invalid relocation table size"); - return rel_begin(sec) + Size / sizeof(Elf_Rel); - } - - Elf_Rel_Range rels(const Elf_Shdr *Sec) const { - return makeArrayRef(rel_begin(Sec), rel_end(Sec)); + Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const { + return getSectionContentsAsArray<Elf_Rel>(Sec); } /// \brief Iterate over program header table. - const Elf_Phdr *program_header_begin() const { - if (Header->e_phnum && Header->e_phentsize != sizeof(Elf_Phdr)) - report_fatal_error("Invalid program header size"); - return reinterpret_cast<const Elf_Phdr *>(base() + Header->e_phoff); - } - - const Elf_Phdr *program_header_end() const { - return program_header_begin() + Header->e_phnum; + Expected<Elf_Phdr_Range> program_headers() const { + if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) + return createError("invalid e_phentsize"); + auto *Begin = + reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff); + return makeArrayRef(Begin, Begin + getHeader()->e_phnum); } - const Elf_Phdr_Range program_headers() const { - return makeArrayRef(program_header_begin(), program_header_end()); - } - - uint64_t getNumSections() const; - uintX_t getStringTableIndex() const; - uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, - const Elf_Shdr *SymTab, - ArrayRef<Elf_Word> ShndxTable) const; - uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, - const Elf_Sym *FirstSym, - ArrayRef<Elf_Word> ShndxTable) const; - const Elf_Ehdr *getHeader() const { return Header; } - ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym, - const Elf_Shdr *SymTab, - ArrayRef<Elf_Word> ShndxTable) const; - ErrorOr<const Elf_Shdr *> getSection(uint32_t Index) const; - - const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { - return &*(symbol_begin(Sec) + Index); - } - - ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const; + Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const; + Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, + ArrayRef<Elf_Word> ShndxTable) const; + Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, + const Elf_Shdr *SymTab, + ArrayRef<Elf_Word> ShndxTable) const; + Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, + Elf_Sym_Range Symtab, + ArrayRef<Elf_Word> ShndxTable) const; + Expected<const Elf_Shdr *> getSection(uint32_t Index) const; + + Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, + uint32_t Index) const; + + Expected<StringRef> getSectionName(const Elf_Shdr *Section) const; + Expected<StringRef> getSectionName(const Elf_Shdr *Section, + StringRef DotShstrtab) const; template <typename T> - ErrorOr<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const; - ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const; + Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const; + Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const; }; typedef ELFFile<ELFType<support::little, false>> ELF32LEFile; @@ -213,61 +167,116 @@ typedef ELFFile<ELFType<support::big, false>> ELF32BEFile; typedef ELFFile<ELFType<support::big, true>> ELF64BEFile; template <class ELFT> -uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( - const Elf_Sym *Sym, const Elf_Shdr *SymTab, - ArrayRef<Elf_Word> ShndxTable) const { - return getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable); +inline Expected<const typename ELFT::Shdr *> +getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { + if (Index >= Sections.size()) + return createError("invalid section index"); + return &Sections[Index]; } template <class ELFT> -uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( - const Elf_Sym *Sym, const Elf_Sym *FirstSym, - ArrayRef<Elf_Word> ShndxTable) const { +inline Expected<uint32_t> +getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym, + const typename ELFT::Sym *FirstSym, + ArrayRef<typename ELFT::Word> ShndxTable) { assert(Sym->st_shndx == ELF::SHN_XINDEX); unsigned Index = Sym - FirstSym; + if (Index >= ShndxTable.size()) + return createError("index past the end of the symbol table"); // The size of the table was checked in getSHNDXTable. return ShndxTable[Index]; } template <class ELFT> -ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *> +Expected<uint32_t> +ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, + ArrayRef<Elf_Word> ShndxTable) const { + uint32_t Index = Sym->st_shndx; + if (Index == ELF::SHN_XINDEX) { + auto ErrorOrIndex = object::getExtendedSymbolTableIndex<ELFT>( + Sym, Syms.begin(), ShndxTable); + if (!ErrorOrIndex) + return ErrorOrIndex.takeError(); + return *ErrorOrIndex; + } + if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) + return 0; + return Index; +} + +template <class ELFT> +Expected<const typename ELFT::Shdr *> ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef<Elf_Word> ShndxTable) const { - uint32_t Index = Sym->st_shndx; - if (Index == ELF::SHN_XINDEX) - return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable)); + auto SymsOrErr = symbols(SymTab); + if (!SymsOrErr) + return SymsOrErr.takeError(); + return getSection(Sym, *SymsOrErr, ShndxTable); +} - if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) +template <class ELFT> +Expected<const typename ELFT::Shdr *> +ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols, + ArrayRef<Elf_Word> ShndxTable) const { + auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable); + if (!IndexOrErr) + return IndexOrErr.takeError(); + uint32_t Index = *IndexOrErr; + if (Index == 0) return nullptr; - return getSection(Sym->st_shndx); + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + return object::getSection<ELFT>(*SectionsOrErr, Index); +} + +template <class ELFT> +inline Expected<const typename ELFT::Sym *> +getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) { + if (Index >= Symbols.size()) + return createError("invalid symbol index"); + return &Symbols[Index]; +} + +template <class ELFT> +Expected<const typename ELFT::Sym *> +ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { + auto SymtabOrErr = symbols(Sec); + if (!SymtabOrErr) + return SymtabOrErr.takeError(); + return object::getSymbol<ELFT>(*SymtabOrErr, Index); } template <class ELFT> template <typename T> -ErrorOr<ArrayRef<T>> +Expected<ArrayRef<T>> ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { + if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1) + return createError("invalid sh_entsize"); + uintX_t Offset = Sec->sh_offset; uintX_t Size = Sec->sh_size; if (Size % sizeof(T)) - return object_error::parse_failed; - if (Offset + Size > Buf.size()) - return object_error::parse_failed; + return createError("size is not a multiple of sh_entsize"); + if ((std::numeric_limits<uintX_t>::max() - Offset < Size) || + Offset + Size > Buf.size()) + return createError("invalid section offset"); const T *Start = reinterpret_cast<const T *>(base() + Offset); return makeArrayRef(Start, Size / sizeof(T)); } template <class ELFT> -ErrorOr<ArrayRef<uint8_t>> +Expected<ArrayRef<uint8_t>> ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { return getSectionContentsAsArray<uint8_t>(Sec); } template <class ELFT> StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { - return getELFRelocationTypeName(Header->e_machine, Type); + return getELFRelocationTypeName(getHeader()->e_machine, Type); } template <class ELFT> @@ -302,7 +311,7 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, } template <class ELFT> -const typename ELFFile<ELFT>::Elf_Sym * +Expected<const typename ELFT::Sym *> ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, const Elf_Shdr *SymTab) const { uint32_t Index = Rel->getSymbol(isMips64EL()); @@ -312,193 +321,197 @@ ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, } template <class ELFT> -uint64_t ELFFile<ELFT>::getNumSections() const { - assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF && Header->e_shoff > 0) { - assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); - return SectionHeaderTable->sh_size; - } - return Header->e_shnum; +Expected<StringRef> +ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const { + uint32_t Index = getHeader()->e_shstrndx; + if (Index == ELF::SHN_XINDEX) + Index = Sections[0].sh_link; + + if (!Index) // no section string table. + return ""; + if (Index >= Sections.size()) + return createError("invalid section index"); + return getStringTable(&Sections[Index]); } template <class ELFT> -typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const { - if (Header->e_shnum == ELF::SHN_UNDEF) { - if (Header->e_shstrndx == ELF::SHN_HIRESERVE) - return SectionHeaderTable->sh_link; - if (Header->e_shstrndx >= getNumSections()) - return 0; - } - return Header->e_shstrndx; +ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) { + assert(sizeof(Elf_Ehdr) <= Buf.size() && "Invalid buffer"); } template <class ELFT> -ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) - : Buf(Object) { - const uint64_t FileSize = Buf.size(); +static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { + return VAddr < Phdr->p_vaddr; +} - if (sizeof(Elf_Ehdr) > FileSize) { - // File too short! - EC = object_error::parse_failed; - return; - } +template <class ELFT> +Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { + const uintX_t SectionTableOffset = getHeader()->e_shoff; + if (SectionTableOffset == 0) + return ArrayRef<Elf_Shdr>(); - Header = reinterpret_cast<const Elf_Ehdr *>(base()); + if (getHeader()->e_shentsize != sizeof(Elf_Shdr)) + return createError( + "invalid section header entry size (e_shentsize) in ELF header"); - if (Header->e_shoff == 0) - return; + const uint64_t FileSize = Buf.size(); - const uint64_t SectionTableOffset = Header->e_shoff; + if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) + return createError("section header table goes past the end of the file"); - if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) { - // Section header table goes past end of file! - EC = object_error::parse_failed; - return; - } + // Invalid address alignment of section headers + if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) + return createError("invalid alignment of section headers"); - // The getNumSections() call below depends on SectionHeaderTable being set. - SectionHeaderTable = - reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); - const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; + const Elf_Shdr *First = + reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); - if (SectionTableOffset + SectionTableSize > FileSize) { - // Section table goes past end of file! - EC = object_error::parse_failed; - return; - } + uintX_t NumSections = getHeader()->e_shnum; + if (NumSections == 0) + NumSections = First->sh_size; - // Get string table sections. - uintX_t StringTableIndex = getStringTableIndex(); - if (StringTableIndex) { - ErrorOr<const Elf_Shdr *> StrTabSecOrErr = getSection(StringTableIndex); - if ((EC = StrTabSecOrErr.getError())) - return; - - ErrorOr<StringRef> StringTableOrErr = getStringTable(*StrTabSecOrErr); - if ((EC = StringTableOrErr.getError())) - return; - DotShstrtab = *StringTableOrErr; - } + if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) + return createError("section table goes past the end of file"); - EC = std::error_code(); -} + const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); -template <class ELFT> -static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { - return VAddr < Phdr->p_vaddr; -} - -template <class ELFT> -const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_begin() const { - if (Header->e_shentsize != sizeof(Elf_Shdr)) - report_fatal_error( - "Invalid section header entry size (e_shentsize) in ELF header"); - return reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); -} + // Section table goes past end of file! + if (SectionTableOffset + SectionTableSize > FileSize) + return createError("section table goes past the end of file"); -template <class ELFT> -const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_end() const { - return section_begin() + getNumSections(); + return makeArrayRef(First, NumSections); } template <class ELFT> template <typename T> -const T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { - ErrorOr<const Elf_Shdr *> Sec = getSection(Section); - if (std::error_code EC = Sec.getError()) - report_fatal_error(EC.message()); - return getEntry<T>(*Sec, Entry); +Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, + uint32_t Entry) const { + auto SecOrErr = getSection(Section); + if (!SecOrErr) + return SecOrErr.takeError(); + return getEntry<T>(*SecOrErr, Entry); } template <class ELFT> template <typename T> -const T *ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, - uint32_t Entry) const { - return reinterpret_cast<const T *>(base() + Section->sh_offset + - (Entry * Section->sh_entsize)); +Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, + uint32_t Entry) const { + if (sizeof(T) != Section->sh_entsize) + return createError("invalid sh_entsize"); + size_t Pos = Section->sh_offset + Entry * sizeof(T); + if (Pos + sizeof(T) > Buf.size()) + return createError("invalid section offset"); + return reinterpret_cast<const T *>(base() + Pos); } template <class ELFT> -ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *> +Expected<const typename ELFT::Shdr *> ELFFile<ELFT>::getSection(uint32_t Index) const { - assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); - if (Index >= getNumSections()) - return object_error::invalid_section_index; - - return reinterpret_cast<const Elf_Shdr *>( - reinterpret_cast<const char *>(SectionHeaderTable) + - (Index * Header->e_shentsize)); + auto TableOrErr = sections(); + if (!TableOrErr) + return TableOrErr.takeError(); + return object::getSection<ELFT>(*TableOrErr, Index); } template <class ELFT> -ErrorOr<StringRef> +Expected<StringRef> ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { if (Section->sh_type != ELF::SHT_STRTAB) - return object_error::parse_failed; - uint64_t Offset = Section->sh_offset; - uint64_t Size = Section->sh_size; - if (Offset + Size > Buf.size()) - return object_error::parse_failed; - StringRef Data((const char *)base() + Section->sh_offset, Size); - if (Data[Size - 1] != '\0') - return object_error::string_table_non_null_end; - return Data; + return createError("invalid sh_type for string table, expected SHT_STRTAB"); + auto V = getSectionContentsAsArray<char>(Section); + if (!V) + return V.takeError(); + ArrayRef<char> Data = *V; + if (Data.empty()) + return createError("empty string table"); + if (Data.back() != '\0') + return createError("string table non-null terminated"); + return StringRef(Data.begin(), Data.size()); } template <class ELFT> -ErrorOr<ArrayRef<typename ELFFile<ELFT>::Elf_Word>> +Expected<ArrayRef<typename ELFT::Word>> ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + return getSHNDXTable(Section, *SectionsOrErr); +} + +template <class ELFT> +Expected<ArrayRef<typename ELFT::Word>> +ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, + Elf_Shdr_Range Sections) const { assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); - const Elf_Word *ShndxTableBegin = - reinterpret_cast<const Elf_Word *>(base() + Section.sh_offset); - uintX_t Size = Section.sh_size; - if (Size % sizeof(uint32_t)) - return object_error::parse_failed; - uintX_t NumSymbols = Size / sizeof(uint32_t); - const Elf_Word *ShndxTableEnd = ShndxTableBegin + NumSymbols; - if (reinterpret_cast<const char *>(ShndxTableEnd) > Buf.end()) - return object_error::parse_failed; - ErrorOr<const Elf_Shdr *> SymTableOrErr = getSection(Section.sh_link); - if (std::error_code EC = SymTableOrErr.getError()) - return EC; + auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section); + if (!VOrErr) + return VOrErr.takeError(); + ArrayRef<Elf_Word> V = *VOrErr; + auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); + if (!SymTableOrErr) + return SymTableOrErr.takeError(); const Elf_Shdr &SymTable = **SymTableOrErr; if (SymTable.sh_type != ELF::SHT_SYMTAB && SymTable.sh_type != ELF::SHT_DYNSYM) - return object_error::parse_failed; - if (NumSymbols != (SymTable.sh_size / sizeof(Elf_Sym))) - return object_error::parse_failed; - return makeArrayRef(ShndxTableBegin, ShndxTableEnd); + return createError("invalid sh_type"); + if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym))) + return createError("invalid section contents size"); + return V; } template <class ELFT> -ErrorOr<StringRef> +Expected<StringRef> ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + return getStringTableForSymtab(Sec, *SectionsOrErr); +} + +template <class ELFT> +Expected<StringRef> +ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, + Elf_Shdr_Range Sections) const { + if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) - return object_error::parse_failed; - ErrorOr<const Elf_Shdr *> SectionOrErr = getSection(Sec.sh_link); - if (std::error_code EC = SectionOrErr.getError()) - return EC; + return createError( + "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); + auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link); + if (!SectionOrErr) + return SectionOrErr.takeError(); return getStringTable(*SectionOrErr); } template <class ELFT> -ErrorOr<StringRef> +Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + auto Table = getSectionStringTable(*SectionsOrErr); + if (!Table) + return Table.takeError(); + return getSectionName(Section, *Table); +} + +template <class ELFT> +Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section, + StringRef DotShstrtab) const { uint32_t Offset = Section->sh_name; if (Offset == 0) return StringRef(); if (Offset >= DotShstrtab.size()) - return object_error::parse_failed; + return createError("invalid string offset"); return StringRef(DotShstrtab.data() + Offset); } /// This function returns the hash value for a symbol in the .dynsym section /// Name of the API remains consistent as specified in the libelf /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash -static inline unsigned elf_hash(StringRef &symbolName) { +inline unsigned hashSysV(StringRef SymbolName) { unsigned h = 0, g; - for (unsigned i = 0, j = symbolName.size(); i < j; i++) { - h = (h << 4) + symbolName[i]; + for (char C : SymbolName) { + h = (h << 4) + C; g = h & 0xf0000000L; if (g != 0) h ^= g >> 24; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 07c6364a6894..69987d433e2d 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -59,6 +59,7 @@ protected: virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0; virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; @@ -90,6 +91,10 @@ public: uint64_t getFlags() const { return getObject()->getSectionFlags(getRawDataRefImpl()); } + + uint64_t getOffset() const { + return getObject()->getSectionOffset(getRawDataRefImpl()); + } }; class elf_section_iterator : public section_iterator { @@ -245,11 +250,15 @@ protected: uint32_t getSectionType(DataRefImpl Sec) const override; uint64_t getSectionFlags(DataRefImpl Sec) const override; + uint64_t getSectionOffset(DataRefImpl Sec) const override; StringRef getRelocationTypeName(uint32_t Type) const; /// \brief Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return *EF.getSection(Rel.d.a); + auto RelSecOrErr = EF.getSection(Rel.d.a); + if (!RelSecOrErr) + report_fatal_error(errorToErrorCode(RelSecOrErr.takeError()).message()); + return *RelSecOrErr; } DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { @@ -262,7 +271,13 @@ protected: assert(SymTable->sh_type == ELF::SHT_SYMTAB || SymTable->sh_type == ELF::SHT_DYNSYM); - uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin()); + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) { + DRI.d.a = 0; + DRI.d.b = 0; + return DRI; + } + uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); unsigned SymTableIndex = (reinterpret_cast<uintptr_t>(SymTable) - SHT) / sizeof(Elf_Shdr); @@ -311,15 +326,18 @@ public: const Elf_Rela *getRela(DataRefImpl Rela) const; const Elf_Sym *getSymbol(DataRefImpl Sym) const { - return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b); + auto Ret = EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; } const Elf_Shdr *getSection(DataRefImpl Sec) const { return reinterpret_cast<const Elf_Shdr *>(Sec.p); } - basic_symbol_iterator symbol_begin_impl() const override; - basic_symbol_iterator symbol_end_impl() const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; elf_symbol_iterator dynamic_symbol_begin() const; elf_symbol_iterator dynamic_symbol_end() const; @@ -364,10 +382,18 @@ void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { template <class ELFT> Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { const Elf_Sym *ESym = getSymbol(Sym); - const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a); - const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link); - StringRef SymTable = *EF.getStringTable(StringTableSec); - return ESym->getName(SymTable); + auto SymTabOrErr = EF.getSection(Sym.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + const Elf_Shdr *SymTableSec = *SymTabOrErr; + auto StrTabOrErr = EF.getSection(SymTableSec->sh_link); + if (!StrTabOrErr) + return StrTabOrErr.takeError(); + const Elf_Shdr *StringTableSec = *StrTabOrErr; + auto SymStrTabOrErr = EF.getStringTable(StringTableSec); + if (!SymStrTabOrErr) + return SymStrTabOrErr.takeError(); + return ESym->getName(*SymStrTabOrErr); } template <class ELFT> @@ -381,6 +407,11 @@ uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const { } template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionOffset(DataRefImpl Sec) const { + return getSection(Sec)->sh_offset; +} + +template <class ELFT> uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); uint64_t Ret = ESym->st_value; @@ -409,13 +440,15 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { } const Elf_Ehdr *Header = EF.getHeader(); - const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a); + auto SymTabOrErr = EF.getSection(Symb.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + const Elf_Shdr *SymTab = *SymTabOrErr; if (Header->e_type == ELF::ET_REL) { - ErrorOr<const Elf_Shdr *> SectionOrErr = - EF.getSection(ESym, SymTab, ShndxTable); - if (std::error_code EC = SectionOrErr.getError()) - return errorCodeToError(EC); + auto SectionOrErr = EF.getSection(ESym, SymTab, ShndxTable); + if (!SectionOrErr) + return SectionOrErr.takeError(); const Elf_Shdr *Section = *SectionOrErr; if (Section) Result += Section->sh_addr; @@ -495,9 +528,14 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { if (ESym->st_shndx == ELF::SHN_ABS) Result |= SymbolRef::SF_Absolute; - if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || - ESym == EF.symbol_begin(DotSymtabSec) || - ESym == EF.symbol_begin(DotDynSymSec)) + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) + Result |= SymbolRef::SF_FormatSpecific; + + auto DotSymtabSecSyms = EF.symbols(DotSymtabSec); + if (DotSymtabSecSyms && ESym == (*DotSymtabSecSyms).begin()) + Result |= SymbolRef::SF_FormatSpecific; + auto DotDynSymSecSyms = EF.symbols(DotDynSymSec); + if (DotDynSymSecSyms && ESym == (*DotDynSymSecSyms).begin()) Result |= SymbolRef::SF_FormatSpecific; if (EF.getHeader()->e_machine == ELF::EM_ARM) { @@ -533,9 +571,9 @@ template <class ELFT> Expected<section_iterator> ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, const Elf_Shdr *SymTab) const { - ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable); - if (std::error_code EC = ESecOrErr.getError()) - return errorCodeToError(EC); + auto ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable); + if (!ESecOrErr) + return ESecOrErr.takeError(); const Elf_Shdr *ESec = *ESecOrErr; if (!ESec) @@ -550,7 +588,10 @@ template <class ELFT> Expected<section_iterator> ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { const Elf_Sym *Sym = getSymbol(Symb); - const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a); + auto SymTabOrErr = EF.getSection(Symb.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + const Elf_Shdr *SymTab = *SymTabOrErr; return getSymbolSection(Sym, SymTab); } @@ -563,9 +604,9 @@ void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { template <class ELFT> std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, StringRef &Result) const { - ErrorOr<StringRef> Name = EF.getSectionName(&*getSection(Sec)); + auto Name = EF.getSectionName(&*getSection(Sec)); if (!Name) - return Name.getError(); + return errorToErrorCode(Name.takeError()); Result = *Name; return std::error_code(); } @@ -627,7 +668,10 @@ template <class ELFT> relocation_iterator ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { DataRefImpl RelData; - uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin()); + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return relocation_iterator(RelocationRef()); + uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; RelData.d.b = 0; return relocation_iterator(RelocationRef(RelData, this)); @@ -644,9 +688,9 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { const Elf_Shdr *RelSec = getRelSection(RelData); // Error check sh_link here so that getRelocationSymbol can just use it. - ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link); - if (std::error_code EC = SymSecOrErr.getError()) - report_fatal_error(EC.message()); + auto SymSecOrErr = EF.getSection(RelSec->sh_link); + if (!SymSecOrErr) + report_fatal_error(errorToErrorCode(SymSecOrErr.takeError()).message()); RelData.d.b += S->sh_size / S->sh_entsize; return relocation_iterator(RelocationRef(RelData, this)); @@ -663,9 +707,9 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) return section_end(); - ErrorOr<const Elf_Shdr *> R = EF.getSection(EShdr->sh_info); - if (std::error_code EC = R.getError()) - report_fatal_error(EC.message()); + auto R = EF.getSection(EShdr->sh_info); + if (!R) + report_fatal_error(errorToErrorCode(R.takeError()).message()); return section_iterator(SectionRef(toDRI(*R), this)); } @@ -738,14 +782,20 @@ template <class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rel * ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); - return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); + auto Ret = EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; } template <class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rela * ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); - return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); + auto Ret = EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; } template <class ELFT> @@ -753,10 +803,13 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) : ELFObjectFileBase( getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), Object), - EF(Data.getBuffer(), EC) { - if (EC) + EF(Data.getBuffer()) { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) { + EC = errorToErrorCode(SectionsOrErr.takeError()); return; - for (const Elf_Shdr &Sec : EF.sections()) { + } + for (const Elf_Shdr &Sec : *SectionsOrErr) { switch (Sec.sh_type) { case ELF::SHT_DYNSYM: { if (DotDynSymSec) { @@ -777,9 +830,11 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) break; } case ELF::SHT_SYMTAB_SHNDX: { - ErrorOr<ArrayRef<Elf_Word>> TableOrErr = EF.getSHNDXTable(Sec); - if ((EC = TableOrErr.getError())) + auto TableOrErr = EF.getSHNDXTable(Sec); + if (!TableOrErr) { + EC = errorToErrorCode(TableOrErr.takeError()); return; + } ShndxTable = *TableOrErr; break; } @@ -788,16 +843,16 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) } template <class ELFT> -basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const { +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { DataRefImpl Sym = toDRI(DotSymtabSec, 0); return basic_symbol_iterator(SymbolRef(Sym, this)); } template <class ELFT> -basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end_impl() const { +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end() const { const Elf_Shdr *SymTab = DotSymtabSec; if (!SymTab) - return symbol_begin_impl(); + return symbol_begin(); DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); return basic_symbol_iterator(SymbolRef(Sym, this)); } @@ -817,12 +872,18 @@ elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { template <class ELFT> section_iterator ELFObjectFile<ELFT>::section_begin() const { - return section_iterator(SectionRef(toDRI(EF.section_begin()), this)); + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return section_iterator(SectionRef()); + return section_iterator(SectionRef(toDRI((*SectionsOrErr).begin()), this)); } template <class ELFT> section_iterator ELFObjectFile<ELFT>::section_end() const { - return section_iterator(SectionRef(toDRI(EF.section_end()), this)); + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return section_iterator(SectionRef()); + return section_iterator(SectionRef(toDRI((*SectionsOrErr).end()), this)); } template <class ELFT> @@ -854,6 +915,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-mips"; case ELF::EM_PPC: return "ELF32-ppc"; + case ELF::EM_RISCV: + return "ELF32-riscv"; case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return "ELF32-sparc"; @@ -874,6 +937,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big"); case ELF::EM_PPC64: return "ELF64-ppc64"; + case ELF::EM_RISCV: + return "ELF64-riscv"; case ELF::EM_S390: return "ELF64-s390"; case ELF::EM_SPARCV9: @@ -907,7 +972,7 @@ unsigned ELFObjectFile<ELFT>::getArch() const { case ELF::EM_X86_64: return Triple::x86_64; case ELF::EM_AARCH64: - return Triple::aarch64; + return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; case ELF::EM_ARM: return Triple::arm; case ELF::EM_AVR: @@ -929,6 +994,15 @@ unsigned ELFObjectFile<ELFT>::getArch() const { return Triple::ppc; case ELF::EM_PPC64: return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; + case ELF::EM_RISCV: + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + return Triple::riscv32; + case ELF::ELFCLASS64: + return Triple::riscv64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } case ELF::EM_S390: return Triple::systemz; diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 55028f360dbf..3e03fd8b980e 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -124,20 +124,19 @@ struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>> }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(E, W) \ - typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Addr Elf_Addr; \ - typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Off Elf_Off; \ - typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Half Elf_Half; \ - typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Word Elf_Word; \ - typedef \ - typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sword Elf_Sword; \ - typedef \ - typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Xword Elf_Xword; \ - typedef \ - typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sxword Elf_Sxword; #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::Is64Bits) + typedef typename ELFT::Addr Elf_Addr; \ + typedef typename ELFT::Off Elf_Off; \ + typedef typename ELFT::Half Elf_Half; \ + typedef typename ELFT::Word Elf_Word; \ + typedef typename ELFT::Sword Elf_Sword; \ + typedef typename ELFT::Xword Elf_Xword; \ + typedef typename ELFT::Sxword Elf_Sxword; + +#define LLD_ELF_COMMA , +#define LLVM_ELF_IMPORT_TYPES(E, W) \ + LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLD_ELF_COMMA W>) // Section header. template <class ELFT> struct Elf_Shdr_Base; @@ -519,7 +518,7 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> { Elf_Xword p_align; // Segment alignment constraint }; -// ELFT needed for endianess. +// ELFT needed for endianness. template <class ELFT> struct Elf_Hash_Impl { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -609,10 +608,13 @@ template <class ELFT> struct Elf_Mips_Options { // or 0 for global options Elf_Word info; // Kind-specific information - const Elf_Mips_RegInfo<ELFT> &getRegInfo() const { + Elf_Mips_RegInfo<ELFT> &getRegInfo() { assert(kind == llvm::ELF::ODK_REGINFO); - return *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>( - (const uint8_t *)this + sizeof(Elf_Mips_Options)); + return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>( + (uint8_t *)this + sizeof(Elf_Mips_Options)); + } + const Elf_Mips_RegInfo<ELFT> &getRegInfo() const { + return const_cast<Elf_Mips_Options *>(this)->getRegInfo(); } }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index cd55e5dc26d7..eb938338715d 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -34,6 +34,7 @@ enum class object_error { string_table_non_null_end, invalid_section_index, bitcode_section_not_found, + invalid_symbol_index, }; inline std::error_code make_error_code(object_error e) { diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 9fe011e17d62..0ea89011e883 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -14,6 +14,8 @@ #ifndef LLVM_OBJECT_IROBJECTFILE_H #define LLVM_OBJECT_IROBJECTFILE_H +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Object/SymbolicFile.h" namespace llvm { @@ -26,31 +28,21 @@ namespace object { class ObjectFile; class IRObjectFile : public SymbolicFile { - std::unique_ptr<Module> M; - std::unique_ptr<Mangler> Mang; - std::vector<std::pair<std::string, uint32_t>> AsmSymbols; + std::vector<std::unique_ptr<Module>> Mods; + ModuleSymbolTable SymTab; + IRObjectFile(MemoryBufferRef Object, + std::vector<std::unique_ptr<Module>> Mods); public: - IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> M); ~IRObjectFile() override; void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - GlobalValue *getSymbolGV(DataRefImpl Symb); - const GlobalValue *getSymbolGV(DataRefImpl Symb) const { - return const_cast<IRObjectFile *>(this)->getSymbolGV(Symb); - } - basic_symbol_iterator symbol_begin_impl() const override; - basic_symbol_iterator symbol_end_impl() const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; - const Module &getModule() const { - return const_cast<IRObjectFile*>(this)->getModule(); - } - Module &getModule() { - return *M; - } - std::unique_ptr<Module> takeModule(); + StringRef getTargetTriple() const; static inline bool classof(const Binary *v) { return v->isIR(); @@ -60,23 +52,14 @@ public: /// error code if not found. static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); - /// Parse inline ASM and collect the symbols that are not defined in - /// the current module. - /// - /// For each found symbol, call \p AsmUndefinedRefs with the name of the - /// symbol found and the associated flags. - static void CollectAsmUndefinedRefs( - const Triple &TheTriple, StringRef InlineAsm, - function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs); - /// \brief Finds and returns bitcode in the given memory buffer (which may /// be either a bitcode file or a native object file with embedded bitcode), /// or an error code if not found. static ErrorOr<MemoryBufferRef> findBitcodeInMemBuffer(MemoryBufferRef Object); - static ErrorOr<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object, - LLVMContext &Context); + static Expected<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object, + LLVMContext &Context); }; } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 7906db1e8a77..8c33ec8fd603 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -194,7 +194,8 @@ public: typedef LoadCommandList::const_iterator load_command_iterator; static Expected<std::unique_ptr<MachOObjectFile>> - create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits); + create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0); void moveSymbolNext(DataRefImpl &Symb) const override; @@ -202,6 +203,8 @@ public: Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; // MachO specific. + Error checkSymbolTable() const; + std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; unsigned getSectionType(SectionRef Sec) const; @@ -248,8 +251,8 @@ public: // TODO: Would be useful to have an iterator based version // of the load command interface too. - basic_symbol_iterator symbol_begin_impl() const override; - basic_symbol_iterator symbol_end_impl() const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; // MachO specific. basic_symbol_iterator getSymbolByIndex(unsigned Index) const; @@ -410,7 +413,8 @@ public: static Triple::ArchType getArch(uint32_t CPUType); static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault = nullptr); + const char **McpuDefault = nullptr, + const char **ArchFlag = nullptr); static bool isValidArch(StringRef ArchFlag); static Triple getHostArch(); @@ -443,7 +447,8 @@ public: private: MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, - Error &Err); + Error &Err, uint32_t UniversalCputype = 0, + uint32_t UniversalIndex = 0); uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 7eb2af944f3d..a14c4ca01223 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -89,16 +89,24 @@ public: else // Parent->getMagic() == MachO::FAT_MAGIC_64 return Header64.reserved; } - std::string getArchTypeName() const { + std::string getArchFlagName() const { + const char *McpuDefault, *ArchFlag; if (Parent->getMagic() == MachO::FAT_MAGIC) { Triple T = - MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype); - return T.getArchName(); + MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype, + &McpuDefault, &ArchFlag); } else { // Parent->getMagic() == MachO::FAT_MAGIC_64 Triple T = MachOObjectFile::getArchTriple(Header64.cputype, - Header64.cpusubtype); - return T.getArchName(); + Header64.cpusubtype, + &McpuDefault, &ArchFlag); + } + if (ArchFlag) { + std::string ArchFlagName(ArchFlag); + return ArchFlagName; + } else { + std::string ArchFlagName(""); + return ArchFlagName; } } diff --git a/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/include/llvm/Object/ModuleSummaryIndexObjectFile.h index d021fb29427f..6205927039dc 100644 --- a/include/llvm/Object/ModuleSummaryIndexObjectFile.h +++ b/include/llvm/Object/ModuleSummaryIndexObjectFile.h @@ -50,11 +50,11 @@ public: llvm_unreachable("not implemented"); return 0; } - basic_symbol_iterator symbol_begin_impl() const override { + basic_symbol_iterator symbol_begin() const override { llvm_unreachable("not implemented"); return basic_symbol_iterator(BasicSymbolRef()); } - basic_symbol_iterator symbol_end_impl() const override { + basic_symbol_iterator symbol_end() const override { llvm_unreachable("not implemented"); return basic_symbol_iterator(BasicSymbolRef()); } @@ -79,25 +79,18 @@ public: static ErrorOr<MemoryBufferRef> findBitcodeInMemBuffer(MemoryBufferRef Object); - /// \brief Looks for summary sections in the given memory buffer, - /// returns true if found, else false. - static bool hasGlobalValueSummaryInMemBuffer( - MemoryBufferRef Object, - const DiagnosticHandlerFunction &DiagnosticHandler); - /// \brief Parse module summary index in the given memory buffer. /// Return new ModuleSummaryIndexObjectFile instance containing parsed module /// summary/index. - static ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>> - create(MemoryBufferRef Object, - const DiagnosticHandlerFunction &DiagnosticHandler); + static Expected<std::unique_ptr<ModuleSummaryIndexObjectFile>> + create(MemoryBufferRef Object); }; } /// Parse the module summary index out of an IR file and return the module /// summary index object if found, or nullptr if not. -ErrorOr<std::unique_ptr<ModuleSummaryIndex>> getModuleSummaryIndexForFile( - StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler); +Expected<std::unique_ptr<ModuleSummaryIndex>> +getModuleSummaryIndexForFile(StringRef Path); } #endif diff --git a/include/llvm/Object/ModuleSymbolTable.h b/include/llvm/Object/ModuleSymbolTable.h new file mode 100644 index 000000000000..70775352d977 --- /dev/null +++ b/include/llvm/Object/ModuleSymbolTable.h @@ -0,0 +1,61 @@ +//===- ModuleSymbolTable.h - symbol table for in-memory IR ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents a symbol table built from in-memory IR. It provides +// access to GlobalValues and should only be used if such access is required +// (e.g. in the LTO implementation). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MODULESYMBOLTABLE_H +#define LLVM_OBJECT_MODULESYMBOLTABLE_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Object/SymbolicFile.h" +#include <string> +#include <utility> + +namespace llvm { + +class GlobalValue; + +class ModuleSymbolTable { +public: + typedef std::pair<std::string, uint32_t> AsmSymbol; + typedef PointerUnion<GlobalValue *, AsmSymbol *> Symbol; + +private: + Module *FirstMod = nullptr; + + SpecificBumpPtrAllocator<AsmSymbol> AsmSymbols; + std::vector<Symbol> SymTab; + Mangler Mang; + +public: + ArrayRef<Symbol> symbols() const { return SymTab; } + void addModule(Module *M); + + void printSymbolName(raw_ostream &OS, Symbol S) const; + uint32_t getSymbolFlags(Symbol S) const; + + /// Parse inline ASM and collect the symbols that are defined or referenced in + /// the current module. + /// + /// For each found symbol, call \p AsmSymbol with the name of the symbol found + /// and the associated flags. + static void CollectAsmSymbols( + const Triple &TheTriple, StringRef InlineAsm, + function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol); +}; + +} + +#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 6272a5f056eb..13d5845c3a71 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -29,6 +29,7 @@ namespace object { class ObjectFile; class COFFObjectFile; class MachOObjectFile; +class WasmObjectFile; class SymbolRef; class symbol_iterator; @@ -300,8 +301,12 @@ public: createELFObjectFile(MemoryBufferRef Object); static Expected<std::unique_ptr<MachOObjectFile>> - createMachOObjectFile(MemoryBufferRef Object); + createMachOObjectFile(MemoryBufferRef Object, + uint32_t UniversalCputype = 0, + uint32_t UniversalIndex = 0); + static Expected<std::unique_ptr<WasmObjectFile>> + createWasmObjectFile(MemoryBufferRef Object); }; // Inline function definitions. diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 5e0df98d8627..3510d293d73d 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -86,6 +86,7 @@ private: return RelocToApply(); } case Triple::aarch64: + case Triple::aarch64_be: switch (RelocType) { case llvm::ELF::R_AARCH64_ABS32: return visitELF_AARCH64_ABS32(R, Value); @@ -95,6 +96,17 @@ private: HasError = true; return RelocToApply(); } + case Triple::bpfel: + case Triple::bpfeb: + switch (RelocType) { + case llvm::ELF::R_BPF_64_64: + return visitELF_BPF_64_64(R, Value); + case llvm::ELF::R_BPF_64_32: + return visitELF_BPF_64_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } case Triple::mips64el: case Triple::mips64: switch (RelocType) { @@ -139,6 +151,14 @@ private: HasError = true; return RelocToApply(); } + case Triple::amdgcn: + switch (RelocType) { + case llvm::ELF::R_AMDGPU_ABS32: + return visitELF_AMDGPU_ABS32(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); @@ -200,6 +220,14 @@ private: HasError = true; return RelocToApply(); } + case Triple::hexagon: + switch (RelocType) { + case llvm::ELF::R_HEX_32: + return visitELF_HEX_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); @@ -300,6 +328,15 @@ private: return RelocToApply(Res, 4); } + /// BPF ELF + RelocToApply visitELF_BPF_64_32(RelocationRef R, uint64_t Value) { + uint32_t Res = Value & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + RelocToApply visitELF_BPF_64_64(RelocationRef R, uint64_t Value) { + return RelocToApply(Value, 8); + } + /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { int64_t Addend = getELFAddend(R); @@ -403,6 +440,16 @@ private: return RelocToApply(static_cast<uint32_t>(Res), 4); } + RelocToApply visitELF_HEX_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); + return RelocToApply(Value + Addend, 4); + } + /// I386 COFF RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) { return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h index e58162de1501..efea62bb3cb3 100644 --- a/include/llvm/Object/StackMapParser.h +++ b/include/llvm/Object/StackMapParser.h @@ -17,7 +17,7 @@ namespace llvm { template <support::endianness Endianness> -class StackMapV1Parser { +class StackMapV2Parser { public: template <typename AccessorT> @@ -47,7 +47,7 @@ public: /// Accessor for function records. class FunctionAccessor { - friend class StackMapV1Parser; + friend class StackMapV2Parser; public: /// Get the function address. @@ -56,14 +56,19 @@ public: } /// Get the function's stack size. - uint32_t getStackSize() const { + uint64_t getStackSize() const { return read<uint64_t>(P + sizeof(uint64_t)); } + + /// Get the number of callsite records. + uint64_t getRecordCount() const { + return read<uint64_t>(P + (2 * sizeof(uint64_t))); + } private: FunctionAccessor(const uint8_t *P) : P(P) {} - const static int FunctionAccessorSize = 2 * sizeof(uint64_t); + const static int FunctionAccessorSize = 3 * sizeof(uint64_t); FunctionAccessor next() const { return FunctionAccessor(P + FunctionAccessorSize); @@ -74,7 +79,7 @@ public: /// Accessor for constants. class ConstantAccessor { - friend class StackMapV1Parser; + friend class StackMapV2Parser; public: /// Return the value of this constant. @@ -103,7 +108,7 @@ public: /// Accessor for location records. class LocationAccessor { - friend class StackMapV1Parser; + friend class StackMapV2Parser; friend class RecordAccessor; public: @@ -156,7 +161,7 @@ public: /// Accessor for stackmap live-out fields. class LiveOutAccessor { - friend class StackMapV1Parser; + friend class StackMapV2Parser; friend class RecordAccessor; public: @@ -188,7 +193,7 @@ public: /// Accessor for stackmap records. class RecordAccessor { - friend class StackMapV1Parser; + friend class StackMapV2Parser; public: typedef AccessorIterator<LocationAccessor> location_iterator; @@ -292,14 +297,14 @@ public: const uint8_t *P; }; - /// Construct a parser for a version-1 stackmap. StackMap data will be read + /// Construct a parser for a version-2 stackmap. StackMap data will be read /// from the given array. - StackMapV1Parser(ArrayRef<uint8_t> StackMapSection) + StackMapV2Parser(ArrayRef<uint8_t> StackMapSection) : StackMapSection(StackMapSection) { ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; - assert(StackMapSection[0] == 1 && - "StackMapV1Parser can only parse version 1 stackmaps"); + assert(StackMapSection[0] == 2 && + "StackMapV2Parser can only parse version 2 stackmaps"); unsigned CurrentRecordOffset = ConstantsListOffset + getNumConstants() * ConstantSize; @@ -315,8 +320,8 @@ public: typedef AccessorIterator<ConstantAccessor> constant_iterator; typedef AccessorIterator<RecordAccessor> record_iterator; - /// Get the version number of this stackmap. (Always returns 1). - unsigned getVersion() const { return 1; } + /// Get the version number of this stackmap. (Always returns 2). + unsigned getVersion() const { return 2; } /// Get the number of functions in the stack map. uint32_t getNumFunctions() const { @@ -420,7 +425,7 @@ private: static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t); static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t); - static const unsigned FunctionSize = 2 * sizeof(uint64_t); + static const unsigned FunctionSize = 3 * sizeof(uint64_t); static const unsigned ConstantSize = sizeof(uint64_t); std::size_t getFunctionOffset(unsigned FunctionIndex) const { diff --git a/include/llvm/Object/SymbolSize.h b/include/llvm/Object/SymbolSize.h index f2ce70f4208d..1a1dc8752943 100644 --- a/include/llvm/Object/SymbolSize.h +++ b/include/llvm/Object/SymbolSize.h @@ -15,8 +15,19 @@ namespace llvm { namespace object { + +struct SymEntry { + symbol_iterator I; + uint64_t Address; + unsigned Number; + unsigned SectionID; +}; + +int compareAddress(const SymEntry *A, const SymEntry *B); + std::vector<std::pair<SymbolRef, uint64_t>> computeSymbolSizes(const ObjectFile &O); + } } // namespace llvm diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 894c2670f265..af62e62c51d8 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -88,7 +88,6 @@ class BasicSymbolRef { const SymbolicFile *OwningObject; public: - // FIXME: should we add a SF_Text? enum Flags : unsigned { SF_None = 0, SF_Undefined = 1U << 0, // Symbol is defined in another object file @@ -103,6 +102,8 @@ public: SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary SF_Hidden = 1U << 9, // Symbol has hidden visibility SF_Const = 1U << 10, // Symbol value is constant + SF_Executable = 1U << 11, // Symbol points to an executable section + // (IR only) }; BasicSymbolRef() : OwningObject(nullptr) { } @@ -137,17 +138,11 @@ public: virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; - virtual basic_symbol_iterator symbol_begin_impl() const = 0; + virtual basic_symbol_iterator symbol_begin() const = 0; - virtual basic_symbol_iterator symbol_end_impl() const = 0; + virtual basic_symbol_iterator symbol_end() const = 0; // convenience wrappers. - basic_symbol_iterator symbol_begin() const { - return symbol_begin_impl(); - } - basic_symbol_iterator symbol_end() const { - return symbol_end_impl(); - } typedef iterator_range<basic_symbol_iterator> basic_symbol_iterator_range; basic_symbol_iterator_range symbols() const { return basic_symbol_iterator_range(symbol_begin(), symbol_end()); diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h new file mode 100644 index 000000000000..2ece6a6c3770 --- /dev/null +++ b/include/llvm/Object/Wasm.h @@ -0,0 +1,99 @@ +//===- WasmObjectFile.h - Wasm object file implementation -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the WasmObjectFile class, which implements the ObjectFile +// interface for Wasm files. +// +// See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_WASM_H +#define LLVM_OBJECT_WASM_H + +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Wasm.h" + +namespace llvm { +namespace object { + +class WasmObjectFile : public ObjectFile { +public: + WasmObjectFile(MemoryBufferRef Object, Error &Err); + const wasm::WasmObjectHeader &getHeader() const; + const wasm::WasmSection *getWasmSection(const SectionRef &Section) const; + static bool classof(const Binary *v) { return v->isWasm(); } + +protected: + void moveSymbolNext(DataRefImpl &Symb) const override; + + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; + + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + + basic_symbol_iterator symbol_begin() const override; + + basic_symbol_iterator symbol_end() const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + + // Overrides from SectionRef. + void moveSectionNext(DataRefImpl &Sec) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isSectionBitcode(DataRefImpl Sec) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + section_iterator getRelocatedSection(DataRefImpl Sec) const override; + + // Overrides from RelocationRef. + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + unsigned getArch() const override; + SubtargetFeatures getFeatures() const override; + bool isRelocatableObject() const override; + +private: + const uint8_t *getPtr(size_t Offset) const; + Error parseUserSection(wasm::WasmSection &Sec, const uint8_t *Ptr, + size_t Length); + + wasm::WasmObjectHeader Header; + std::vector<wasm::WasmSection> Sections; +}; +} +} + +#endif |