diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /include/llvm/Object | |
parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) |
Notes
Diffstat (limited to 'include/llvm/Object')
-rw-r--r-- | include/llvm/Object/Archive.h | 2 | ||||
-rw-r--r-- | include/llvm/Object/ArchiveWriter.h | 9 | ||||
-rw-r--r-- | include/llvm/Object/Binary.h | 15 | ||||
-rw-r--r-- | include/llvm/Object/COFF.h | 55 | ||||
-rw-r--r-- | include/llvm/Object/COFFImportFile.h | 8 | ||||
-rw-r--r-- | include/llvm/Object/ELF.h | 26 | ||||
-rw-r--r-- | include/llvm/Object/ELFObjectFile.h | 111 | ||||
-rw-r--r-- | include/llvm/Object/ELFTypes.h | 8 | ||||
-rw-r--r-- | include/llvm/Object/IRObjectFile.h | 4 | ||||
-rw-r--r-- | include/llvm/Object/IRSymtab.h | 13 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 41 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 17 | ||||
-rw-r--r-- | include/llvm/Object/RelocVisitor.h | 15 | ||||
-rw-r--r-- | include/llvm/Object/StackMapParser.h | 2 | ||||
-rw-r--r-- | include/llvm/Object/Wasm.h | 87 | ||||
-rw-r--r-- | include/llvm/Object/WindowsResource.h | 16 |
16 files changed, 290 insertions, 139 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index e56e8e464de3f..5a1512bb9d363 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -229,7 +229,7 @@ public: enum Kind { K_GNU, - K_MIPS64, + K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 1ed758d40df2e..495b943d04c00 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/Archive.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" namespace llvm { @@ -37,10 +38,10 @@ struct NewArchiveMember { bool Deterministic); }; -std::pair<StringRef, std::error_code> -writeArchive(StringRef ArcName, std::vector<NewArchiveMember> &NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, - bool Thin, std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr); +Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, + bool WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin, + std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr); } #endif diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 3f5a233c1ee18..5e93691d1fd2b 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_BINARY_H #include "llvm/ADT/Triple.h" +#include "llvm/Object/Error.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include <algorithm> @@ -43,6 +44,8 @@ protected: ID_COFFImportFile, ID_IR, // LLVM IR + ID_WinRes, // Windows resource (.res) file. + // Object and children. ID_StartObjects, ID_COFF, @@ -57,8 +60,6 @@ protected: ID_MachO64L, // MachO 64-bit, little endian ID_MachO64B, // MachO 64-bit, big endian - ID_WinRes, // Windows resource (.res) file. - ID_Wasm, ID_EndObjects @@ -143,6 +144,16 @@ public: return Triple::ELF; return Triple::UnknownObjectFormat; } + + static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, + const uint64_t Size) { + if (Addr + Size < Addr || Addr + Size < Size || + Addr + Size > uintptr_t(M.getBufferEnd()) || + Addr < uintptr_t(M.getBufferStart())) { + return object_error::unexpected_eof; + } + return std::error_code(); + } }; /// @brief Create a Binary from Source, autodetecting the file type. diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 89c1ba6be35f0..b072dd5ba7d91 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -25,7 +25,6 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ErrorOr.h" #include <cassert> #include <cstddef> #include <cstdint> @@ -276,6 +275,8 @@ struct coff_symbol_generic { support::ulittle32_t Value; }; +struct coff_aux_section_definition; + class COFFSymbolRef { public: COFFSymbolRef() = default; @@ -347,6 +348,18 @@ public: return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; } + template <typename T> const T *getAux() const { + return CS16 ? reinterpret_cast<const T *>(CS16 + 1) + : reinterpret_cast<const T *>(CS32 + 1); + } + + const coff_aux_section_definition *getSectionDefinition() const { + if (!getNumberOfAuxSymbols() || + getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC) + return nullptr; + return getAux<coff_aux_section_definition>(); + } + bool isAbsolute() const { return getSectionNumber() == -1; } @@ -730,6 +743,12 @@ struct coff_resource_dir_table { support::ulittle16_t NumberOfIDEntries; }; +struct debug_h_header { + support::ulittle32_t Magic; + support::ulittle16_t Version; + support::ulittle16_t HashAlgorithm; +}; + class COFFObjectFile : public ObjectFile { private: friend class ImportDirectoryEntryRef; @@ -753,7 +772,7 @@ private: const debug_directory *DebugDirectoryBegin; const debug_directory *DebugDirectoryEnd; // Either coff_load_configuration32 or coff_load_configuration64. - const void *LoadConfig; + const void *LoadConfig = nullptr; std::error_code getString(uint32_t offset, StringRef &Res) const; @@ -907,7 +926,7 @@ public: uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; - unsigned getArch() const override; + Triple::ArchType getArch() const override; SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } import_directory_iterator import_directory_begin() const; @@ -954,28 +973,28 @@ public: Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; return std::error_code(); } - ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const { + Expected<COFFSymbolRef> getSymbol(uint32_t index) const { if (SymbolTable16) { const coff_symbol16 *Symb = nullptr; if (std::error_code EC = getSymbol(index, Symb)) - return EC; + return errorCodeToError(EC); return COFFSymbolRef(Symb); } if (SymbolTable32) { const coff_symbol32 *Symb = nullptr; if (std::error_code EC = getSymbol(index, Symb)) - return EC; + return errorCodeToError(EC); return COFFSymbolRef(Symb); } - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); } template <typename T> std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { - ErrorOr<COFFSymbolRef> s = getSymbol(index); - if (std::error_code EC = s.getError()) - return EC; - Res = reinterpret_cast<const T *>(s->getRawPtr()); + Expected<COFFSymbolRef> S = getSymbol(index); + if (Error E = S.takeError()) + return errorToErrorCode(std::move(E)); + Res = reinterpret_cast<const T *>(S->getRawPtr()); return std::error_code(); } @@ -1145,7 +1164,7 @@ public: BaseRelocRef() = default; BaseRelocRef(const coff_base_reloc_block_header *Header, const COFFObjectFile *Owner) - : Header(Header), Index(0), OwningObject(Owner) {} + : Header(Header), Index(0) {} bool operator==(const BaseRelocRef &Other) const; void moveNext(); @@ -1156,7 +1175,6 @@ public: private: const coff_base_reloc_block_header *Header; uint32_t Index; - const COFFObjectFile *OwningObject = nullptr; }; class ResourceSectionRef { @@ -1164,16 +1182,17 @@ public: ResourceSectionRef() = default; explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} - ErrorOr<ArrayRef<UTF16>> getEntryNameString(const coff_resource_dir_entry &Entry); - ErrorOr<const coff_resource_dir_table &> + Expected<ArrayRef<UTF16>> + getEntryNameString(const coff_resource_dir_entry &Entry); + Expected<const coff_resource_dir_table &> getEntrySubDir(const coff_resource_dir_entry &Entry); - ErrorOr<const coff_resource_dir_table &> getBaseTable(); + Expected<const coff_resource_dir_table &> getBaseTable(); private: BinaryByteStream BBS; - ErrorOr<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); - ErrorOr<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); + Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); + Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); }; // Corresponds to `_FPO_DATA` structure in the PE/COFF spec. diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h index cf9c80a06f49a..4b284de679b3d 100644 --- a/include/llvm/Object/COFFImportFile.h +++ b/include/llvm/Object/COFFImportFile.h @@ -96,11 +96,9 @@ struct COFFShortExport { } }; -std::error_code writeImportLibrary(StringRef ImportName, - StringRef Path, - ArrayRef<COFFShortExport> Exports, - COFF::MachineTypes Machine, - bool MakeWeakAliases); +Error writeImportLibrary(StringRef ImportName, StringRef Path, + ArrayRef<COFFShortExport> Exports, + COFF::MachineTypes Machine, bool MakeWeakAliases); } // namespace object } // namespace llvm diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 670c0bbce3ac6..45c98233dec0f 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -83,6 +83,8 @@ public: private: StringRef Buf; + ELFFile(StringRef Object); + public: const Elf_Ehdr *getHeader() const { return reinterpret_cast<const Elf_Ehdr *>(base()); @@ -102,8 +104,6 @@ public: Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, Elf_Shdr_Range Sections) const; - void VerifyStrTab(const Elf_Shdr *sh) const; - StringRef getRelocationTypeName(uint32_t Type) const; void getRelocationTypeName(uint32_t Type, SmallVectorImpl<char> &Result) const; @@ -112,7 +112,7 @@ public: Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, const Elf_Shdr *SymTab) const; - ELFFile(StringRef Object); + static Expected<ELFFile> create(StringRef Object); bool isMipsELF64() const { return getHeader()->e_machine == ELF::EM_MIPS && @@ -140,10 +140,16 @@ public: return getSectionContentsAsArray<Elf_Rel>(Sec); } + Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const; + /// \brief Iterate over program header table. Expected<Elf_Phdr_Range> program_headers() const { if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) return createError("invalid e_phentsize"); + if (getHeader()->e_phoff + + (getHeader()->e_phnum * getHeader()->e_phentsize) > + getBufSize()) + return createError("program headers longer than binary"); auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff); return makeArrayRef(Begin, Begin + getHeader()->e_phnum); @@ -271,6 +277,9 @@ ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { Offset + Size > Buf.size()) return createError("invalid section offset"); + if (Offset % alignof(T)) + return createError("unaligned data"); + const T *Start = reinterpret_cast<const T *>(base() + Offset); return makeArrayRef(Start, Size / sizeof(T)); } @@ -341,14 +350,13 @@ ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const { return getStringTable(&Sections[Index]); } -template <class ELFT> -ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) { - assert(sizeof(Elf_Ehdr) <= Buf.size() && "Invalid buffer"); -} +template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} template <class ELFT> -bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { - return VAddr < Phdr->p_vaddr; +Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { + if (sizeof(Elf_Ehdr) > Object.size()) + return createError("Invalid buffer"); + return ELFFile(Object); } template <class ELFT> diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 73011f6f9fe1a..40503cb6bb9da 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -33,7 +33,6 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include <cassert> #include <cstdint> @@ -61,7 +60,7 @@ protected: 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; + virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; public: using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>; @@ -167,7 +166,7 @@ public: return cast<ELFObjectFileBase>(RelocationRef::getObject()); } - ErrorOr<int64_t> getAddend() const { + Expected<int64_t> getAddend() const { return getObject()->getRelocationAddend(getRawDataRefImpl()); } }; @@ -210,6 +209,11 @@ public: using Elf_Rela = typename ELFFile<ELFT>::Elf_Rela; using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn; +private: + ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, + const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, + ArrayRef<Elf_Word> ShndxTable); + protected: ELFFile<ELFT> EF; @@ -328,7 +332,8 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBufferRef Object, std::error_code &EC); + ELFObjectFile(ELFObjectFile<ELFT> &&Other); + static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object); const Elf_Rel *getRel(DataRefImpl Rel) const; const Elf_Rela *getRela(DataRefImpl Rela) const; @@ -353,11 +358,11 @@ public: section_iterator section_begin() const override; section_iterator section_end() const override; - ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const override; + Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; - unsigned getArch() const override; + Triple::ArchType getArch() const override; std::error_code getPlatformFlags(unsigned &Result) const override { Result = EF.getHeader()->e_flags; @@ -667,6 +672,10 @@ std::error_code ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, StringRef &Result) const { const Elf_Shdr *EShdr = getSection(Sec); + if (std::error_code EC = + checkOffset(getMemoryBufferRef(), + (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size)) + return EC; Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); return std::error_code(); } @@ -812,10 +821,10 @@ void ELFObjectFile<ELFT>::getRelocationTypeName( } template <class ELFT> -ErrorOr<int64_t> +Expected<int64_t> ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const { if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) - return object_error::parse_failed; + return createError("Section is not SHT_RELA"); return (int64_t)getRela(Rel)->r_addend; } @@ -840,50 +849,64 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { } template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), - Object), - EF(Data.getBuffer()) { +Expected<ELFObjectFile<ELFT>> +ELFObjectFile<ELFT>::create(MemoryBufferRef Object) { + auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer()); + if (Error E = EFOrErr.takeError()) + return std::move(E); + auto EF = std::move(*EFOrErr); + auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) { - EC = errorToErrorCode(SectionsOrErr.takeError()); - return; - } + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + + const Elf_Shdr *DotDynSymSec = nullptr; + const Elf_Shdr *DotSymtabSec = nullptr; + ArrayRef<Elf_Word> ShndxTable; for (const Elf_Shdr &Sec : *SectionsOrErr) { switch (Sec.sh_type) { case ELF::SHT_DYNSYM: { - if (DotDynSymSec) { - // More than one .dynsym! - EC = object_error::parse_failed; - return; - } + if (DotDynSymSec) + return createError("More than one dynamic symbol table!"); DotDynSymSec = &Sec; break; } case ELF::SHT_SYMTAB: { - if (DotSymtabSec) { - // More than one .dynsym! - EC = object_error::parse_failed; - return; - } + if (DotSymtabSec) + return createError("More than one static symbol table!"); DotSymtabSec = &Sec; break; } case ELF::SHT_SYMTAB_SHNDX: { auto TableOrErr = EF.getSHNDXTable(Sec); - if (!TableOrErr) { - EC = errorToErrorCode(TableOrErr.takeError()); - return; - } + if (!TableOrErr) + return TableOrErr.takeError(); ShndxTable = *TableOrErr; break; } } } + return ELFObjectFile<ELFT>(Object, EF, DotDynSymSec, DotSymtabSec, + ShndxTable); } template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, + const Elf_Shdr *DotDynSymSec, + const Elf_Shdr *DotSymtabSec, + ArrayRef<Elf_Word> ShndxTable) + : ELFObjectFileBase( + getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), + Object), + EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), + ShndxTable(ShndxTable) {} + +template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other) + : ELFObjectFile(Other.Data, Other.EF, Other.DotDynSymSec, + Other.DotSymtabSec, Other.ShndxTable) {} + +template <class ELFT> basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { DataRefImpl Sym = toDRI(DotSymtabSec, 0); return basic_symbol_iterator(SymbolRef(Sym, this)); @@ -991,9 +1014,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { case ELF::EM_WEBASSEMBLY: return "ELF64-wasm"; case ELF::EM_AMDGPU: - return (EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA - && IsLittleEndian) ? - "ELF64-amdgpu-hsacobj" : "ELF64-amdgpu"; + return "ELF64-amdgpu"; case ELF::EM_BPF: return "ELF64-BPF"; default: @@ -1005,8 +1026,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { } } -template <class ELFT> -unsigned ELFObjectFile<ELFT>::getArch() const { +template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_machine) { case ELF::EM_386: @@ -1061,11 +1081,20 @@ unsigned ELFObjectFile<ELFT>::getArch() const { default: return Triple::UnknownArch; } - case ELF::EM_AMDGPU: - return (EF.getHeader()->e_ident[ELF::EI_CLASS] == ELF::ELFCLASS64 - && EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA - && IsLittleEndian) ? - Triple::amdgcn : Triple::UnknownArch; + case ELF::EM_AMDGPU: { + if (!IsLittleEndian) + return Triple::UnknownArch; + + unsigned EFlags = EF.getHeader()->e_flags; + switch (EFlags & ELF::EF_AMDGPU_ARCH) { + case ELF::EF_AMDGPU_ARCH_R600: + return Triple::r600; + case ELF::EF_AMDGPU_ARCH_GCN: + return Triple::amdgcn; + default: + return Triple::UnknownArch; + } + } case ELF::EM_BPF: return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 808144694acb8..83b688548fdc1 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -406,10 +406,10 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); } void setSymbol(uint32_t s, bool IsMips64EL) { - setSymbolAndType(s, getType(), IsMips64EL); + setSymbolAndType(s, getType(IsMips64EL), IsMips64EL); } void setType(unsigned char t, bool IsMips64EL) { - setSymbolAndType(getSymbol(), t, IsMips64EL); + setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL); } void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { this->setRInfo((s << 8) + t, IsMips64EL); @@ -459,10 +459,10 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); } void setSymbol(uint32_t s, bool IsMips64EL) { - setSymbolAndType(s, getType(), IsMips64EL); + setSymbolAndType(s, getType(IsMips64EL), IsMips64EL); } void setType(uint32_t t, bool IsMips64EL) { - setSymbolAndType(getSymbol(), t, IsMips64EL); + setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL); } void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 9a696bffd1f0b..6c271b1a1f44c 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -52,12 +52,12 @@ public: /// \brief Finds and returns bitcode embedded in the given object file, or an /// error code if not found. - static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); + static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); /// \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> + static Expected<MemoryBufferRef> findBitcodeInMemBuffer(MemoryBufferRef Object); static Expected<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object, diff --git a/include/llvm/Object/IRSymtab.h b/include/llvm/Object/IRSymtab.h index 824a67a672faf..5f6a024cd1329 100644 --- a/include/llvm/Object/IRSymtab.h +++ b/include/llvm/Object/IRSymtab.h @@ -121,6 +121,9 @@ struct Uncommon { /// COFF-specific: the name of the symbol that a weak external resolves to /// if not defined. Str COFFWeakExternFallbackName; + + /// Specified section name, if any. + Str SectionName; }; struct Header { @@ -128,7 +131,7 @@ struct Header { /// when the format changes, but it does not need to be incremented if a /// change to LLVM would cause it to create a different symbol table. Word Version; - enum { kCurrentVersion = 0 }; + enum { kCurrentVersion = 1 }; /// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION). /// Consumers should rebuild the symbol table from IR if the producer's @@ -165,6 +168,7 @@ struct Symbol { // Copied from storage::Uncommon. uint32_t CommonSize, CommonAlign; StringRef COFFWeakExternFallbackName; + StringRef SectionName; /// Returns the mangled symbol name. StringRef getName() const { return Name; } @@ -215,6 +219,8 @@ struct Symbol { assert(isWeak() && isIndirect()); return COFFWeakExternFallbackName; } + + StringRef getSectionName() const { return SectionName; } }; /// This class can be used to read a Symtab and Strtab produced by @@ -300,7 +306,10 @@ class Reader::SymbolRef : public Symbol { CommonSize = UncI->CommonSize; CommonAlign = UncI->CommonAlign; COFFWeakExternFallbackName = R->str(UncI->COFFWeakExternFallbackName); - } + SectionName = R->str(UncI->SectionName); + } else + // Reset this field so it can be queried unconditionally for all symbols. + SectionName = ""; } public: diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 2c3c89d10546f..d0cc40da42934 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -66,11 +66,13 @@ using dice_iterator = content_iterator<DiceRef>; /// ExportEntry encapsulates the current-state-of-the-walk used when doing a /// non-recursive walk of the trie data structure. This allows you to iterate /// across all exported symbols using: -/// for (const llvm::object::ExportEntry &AnExport : Obj->exports()) { +/// Error Err; +/// for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) { /// } +/// if (Err) { report error ... class ExportEntry { public: - ExportEntry(ArrayRef<uint8_t> Trie); + ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef<uint8_t> Trie); StringRef name() const; uint64_t flags() const; @@ -88,7 +90,7 @@ private: void moveToFirst(); void moveToEnd(); - uint64_t readULEB128(const uint8_t *&p); + uint64_t readULEB128(const uint8_t *&p, const char **error); void pushDownUntilBottom(); void pushNode(uint64_t Offset); @@ -107,12 +109,19 @@ private: unsigned ParentStringLength = 0; bool IsExportNode = false; }; + using NodeList = SmallVector<NodeState, 16>; + using node_iterator = NodeList::const_iterator; + Error *E; + const MachOObjectFile *O; ArrayRef<uint8_t> Trie; SmallString<256> CumulativeString; - SmallVector<NodeState, 16> Stack; - bool Malformed = false; + NodeList Stack; bool Done = false; + + iterator_range<node_iterator> nodes() const { + return make_range(Stack.begin(), Stack.end()); + } }; using export_iterator = content_iterator<ExportEntry>; @@ -301,6 +310,16 @@ public: bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; bool isSectionBitcode(DataRefImpl Sec) const override; + + /// When dsymutil generates the companion file, it strips all unnecessary + /// sections (e.g. everything in the _TEXT segment) by omitting their body + /// and setting the offset in their corresponding load command to zero. + /// + /// While the load command itself is valid, reading the section corresponds + /// to reading the number of bytes specified in the load command, starting + /// from offset 0 (i.e. the Mach-O header at the beginning of the file). + bool isSectionStripped(DataRefImpl Sec) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -310,6 +329,9 @@ public: return make_range(extrel_begin(), extrel_end()); } + relocation_iterator locrel_begin() const; + relocation_iterator locrel_end() const; + void moveRelocationNext(DataRefImpl &Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; @@ -341,7 +363,7 @@ public: uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; - unsigned getArch() const override; + Triple::ArchType getArch() const override; SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } Triple getArchTriple(const char **McpuDefault = nullptr) const; @@ -356,10 +378,13 @@ public: iterator_range<load_command_iterator> load_commands() const; /// For use iterating over all exported symbols. - iterator_range<export_iterator> exports() const; + iterator_range<export_iterator> exports(Error &Err) const; /// For use examining a trie not in a MachOObjectFile. - static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie); + static iterator_range<export_iterator> exports(Error &Err, + ArrayRef<uint8_t> Trie, + const MachOObjectFile *O = + nullptr); /// For use iterating over all rebase table entries. iterator_range<rebase_iterator> rebaseTable(Error &Err); diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index afcad3090703b..079a59468156d 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_OBJECTFILE_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/MC/SubtargetFeature.h" @@ -23,7 +24,6 @@ #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" -#include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include <cassert> @@ -109,6 +109,7 @@ public: bool isBSS() const; bool isVirtual() const; bool isBitcode() const; + bool isStripped() const; bool containsSymbol(SymbolRef S) const; @@ -236,6 +237,7 @@ protected: // A section is 'virtual' if its contents aren't present in the object image. virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; virtual bool isSectionBitcode(DataRefImpl Sec) const; + virtual bool isSectionStripped(DataRefImpl Sec) const; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; @@ -278,10 +280,13 @@ public: virtual uint8_t getBytesInAddress() const = 0; virtual StringRef getFileFormatName() const = 0; - virtual /* Triple::ArchType */ unsigned getArch() const = 0; + virtual Triple::ArchType getArch() const = 0; virtual SubtargetFeatures getFeatures() const = 0; virtual void setARMSubArch(Triple &TheTriple) const { } + /// @brief Create a triple from the data in this object file. + Triple makeTriple() const; + /// Returns platform-specific object flags, if any. virtual std::error_code getPlatformFlags(unsigned &Result) const { Result = 0; @@ -317,10 +322,10 @@ public: return v->isObject(); } - static ErrorOr<std::unique_ptr<COFFObjectFile>> + static Expected<std::unique_ptr<COFFObjectFile>> createCOFFObjectFile(MemoryBufferRef Object); - static ErrorOr<std::unique_ptr<ObjectFile>> + static Expected<std::unique_ptr<ObjectFile>> createELFObjectFile(MemoryBufferRef Object); static Expected<std::unique_ptr<MachOObjectFile>> @@ -439,6 +444,10 @@ inline bool SectionRef::isBitcode() const { return OwningObject->isSectionBitcode(SectionPimpl); } +inline bool SectionRef::isStripped() const { + return OwningObject->isSectionStripped(SectionPimpl); +} + inline relocation_iterator SectionRef::relocation_begin() const { return OwningObject->section_rel_begin(SectionPimpl); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index c358d39964352..2d0e938f06fdc 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -25,7 +25,6 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ErrorOr.h" #include <cstdint> #include <system_error> @@ -115,9 +114,10 @@ private: } int64_t getELFAddend(RelocationRef R) { - ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); - if (std::error_code EC = AddendOrErr.getError()) - report_fatal_error(EC.message()); + Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); + handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { + report_fatal_error(EI.message()); + }); return *AddendOrErr; } @@ -169,6 +169,8 @@ private: return (Value + getELFAddend(R)) & 0xFFFFFFFF; case ELF::R_MIPS_64: return Value + getELFAddend(R); + case ELF::R_MIPS_TLS_DTPREL64: + return Value + getELFAddend(R) - 0x8000; } HasError = true; return 0; @@ -260,8 +262,11 @@ private: } uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) { + // FIXME: Take in account implicit addends to get correct results. if (Rel == ELF::R_MIPS_32) return Value & 0xFFFFFFFF; + if (Rel == ELF::R_MIPS_TLS_DTPREL32) + return Value & 0xFFFFFFFF; HasError = true; return 0; } @@ -297,6 +302,8 @@ private: return Value; } break; + default: + break; } HasError = true; return 0; diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h index 0c5e1e38cbaa4..557db5afa8256 100644 --- a/include/llvm/Object/StackMapParser.h +++ b/include/llvm/Object/StackMapParser.h @@ -62,7 +62,7 @@ public: 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))); diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h index 07ee4a4d6c4da..5bb1a3fca3d17 100644 --- a/include/llvm/Object/Wasm.h +++ b/include/llvm/Object/Wasm.h @@ -43,25 +43,56 @@ public: }; WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section, - uint32_t ElementIndex) - : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex) {} + uint32_t ElementIndex, uint32_t ImportIndex = 0) + : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex), + ImportIndex(ImportIndex) {} StringRef Name; SymbolType Type; uint32_t Section; uint32_t Flags = 0; - // Index into the imports, exports or functions array of the object depending - // on the type + // Index into either the function or global index space. uint32_t ElementIndex; + // For imports, the index into the import table + uint32_t ImportIndex; + + bool isFunction() const { + return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT || + Type == WasmSymbol::SymbolType::FUNCTION_EXPORT || + Type == WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME; + } + + bool isWeak() const { - return Flags & wasm::WASM_SYMBOL_FLAG_WEAK; + return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK; + } + + bool isGlobal() const { + return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL; + } + + bool isLocal() const { + return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL; + } + + unsigned getBinding() const { + return Flags & wasm::WASM_SYMBOL_BINDING_MASK; + } + + bool isHidden() const { + return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN; + } + + unsigned getVisibility() const { + return Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK; } void print(raw_ostream &Out) const { Out << "Name=" << Name << ", Type=" << static_cast<int>(Type) - << ", Flags=" << Flags << " ElemIndex=" << ElementIndex; + << ", Flags=" << Flags << " ElemIndex=" << ElementIndex + << ", ImportIndex=" << ImportIndex; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) @@ -97,29 +128,18 @@ public: static bool classof(const Binary *v) { return v->isWasm(); } - const std::vector<wasm::WasmSignature>& types() const { return Signatures; } - const std::vector<uint32_t>& functionTypes() const { return FunctionTypes; } - const std::vector<wasm::WasmImport>& imports() const { return Imports; } - const std::vector<wasm::WasmTable>& tables() const { return Tables; } - const std::vector<wasm::WasmLimits>& memories() const { return Memories; } - const std::vector<wasm::WasmGlobal>& globals() const { return Globals; } - const std::vector<wasm::WasmExport>& exports() const { return Exports; } + ArrayRef<wasm::WasmSignature> types() const { return Signatures; } + ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; } + ArrayRef<wasm::WasmImport> imports() const { return Imports; } + ArrayRef<wasm::WasmTable> tables() const { return Tables; } + ArrayRef<wasm::WasmLimits> memories() const { return Memories; } + ArrayRef<wasm::WasmGlobal> globals() const { return Globals; } + ArrayRef<wasm::WasmExport> exports() const { return Exports; } const wasm::WasmLinkingData& linkingData() const { return LinkingData; } - - uint32_t getNumberOfSymbols() const { - return Symbols.size(); - } - - const std::vector<wasm::WasmElemSegment>& elements() const { - return ElemSegments; - } - - const std::vector<WasmSegment>& dataSegments() const { - return DataSegments; - } - - const std::vector<wasm::WasmFunction>& functions() const { return Functions; } - const ArrayRef<uint8_t>& code() const { return CodeSection; } + uint32_t getNumberOfSymbols() const { return Symbols.size(); } + ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; } + ArrayRef<WasmSegment> dataSegments() const { return DataSegments; } + ArrayRef<wasm::WasmFunction> functions() const { return Functions; } uint32_t startFunction() const { return StartFunction; } void moveSymbolNext(DataRefImpl &Symb) const override; @@ -132,6 +152,7 @@ public: Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; @@ -169,11 +190,12 @@ public: section_iterator section_end() const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; - unsigned getArch() const override; + Triple::ArchType getArch() const override; SubtargetFeatures getFeatures() const override; bool isRelocatableObject() const override; private: + bool isValidFunctionIndex(uint32_t Index) const; const WasmSection &getWasmSection(DataRefImpl Ref) const; const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; @@ -204,6 +226,8 @@ private: Error parseRelocSection(StringRef Name, const uint8_t *Ptr, const uint8_t *End); + void populateSymbolTable(); + wasm::WasmObjectHeader Header; std::vector<WasmSection> Sections; std::vector<wasm::WasmSignature> Signatures; @@ -217,10 +241,13 @@ private: std::vector<WasmSegment> DataSegments; std::vector<wasm::WasmFunction> Functions; std::vector<WasmSymbol> Symbols; - ArrayRef<uint8_t> CodeSection; uint32_t StartFunction = -1; bool HasLinkingSection = false; wasm::WasmLinkingData LinkingData; + uint32_t NumImportedGlobals = 0; + uint32_t NumImportedFunctions = 0; + uint32_t ImportSection = 0; + uint32_t ExportSection = 0; StringMap<uint32_t> SymbolMap; }; diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h index 3d32409fd4aca..a077c82871bfc 100644 --- a/include/llvm/Object/WindowsResource.h +++ b/include/llvm/Object/WindowsResource.h @@ -85,6 +85,12 @@ struct WinResHeaderSuffix { support::ulittle32_t Characteristics; }; +class EmptyResError : public GenericBinaryError { +public: + EmptyResError(Twine Msg, object_error ECOverride) + : GenericBinaryError(Msg, ECOverride) {} +}; + class ResourceEntryRef { public: Error moveNext(bool &End); @@ -94,7 +100,9 @@ public: bool checkNameString() const { return IsStringName; } ArrayRef<UTF16> getNameString() const { return Name; } uint16_t getNameID() const { return NameID; } + uint16_t getDataVersion() const { return Suffix->DataVersion; } uint16_t getLanguage() const { return Suffix->Language; } + uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; } uint16_t getMajorVersion() const { return Suffix->Version >> 16; } uint16_t getMinorVersion() const { return Suffix->Version; } uint32_t getCharacteristics() const { return Suffix->Characteristics; } @@ -103,11 +111,12 @@ public: private: friend class WindowsResource; - ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner, - Error &Err); - + ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner); Error loadNext(); + static Expected<ResourceEntryRef> create(BinaryStreamRef Ref, + const WindowsResource *Owner); + BinaryStreamReader Reader; bool IsStringType; ArrayRef<UTF16> Type; @@ -117,7 +126,6 @@ private: uint16_t NameID; const WinResHeaderSuffix *Suffix = nullptr; ArrayRef<uint8_t> Data; - const WindowsResource *OwningRes = nullptr; }; class WindowsResource : public Binary { |