aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
commitb915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch)
tree98b8f811c7aff2547cab8642daf372d6c59502fb /include/llvm/Object
parent6421cca32f69ac849537a3cff78c352195e99f1b (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.h106
-rw-r--r--include/llvm/Object/ArchiveWriter.h14
-rw-r--r--include/llvm/Object/Binary.h4
-rw-r--r--include/llvm/Object/COFF.h52
-rw-r--r--include/llvm/Object/COFFImportFile.h4
-rw-r--r--include/llvm/Object/ELF.h539
-rw-r--r--include/llvm/Object/ELFObjectFile.h160
-rw-r--r--include/llvm/Object/ELFTypes.h34
-rw-r--r--include/llvm/Object/Error.h1
-rw-r--r--include/llvm/Object/IRObjectFile.h39
-rw-r--r--include/llvm/Object/MachO.h15
-rw-r--r--include/llvm/Object/MachOUniversal.h18
-rw-r--r--include/llvm/Object/ModuleSummaryIndexObjectFile.h19
-rw-r--r--include/llvm/Object/ModuleSymbolTable.h61
-rw-r--r--include/llvm/Object/ObjectFile.h7
-rw-r--r--include/llvm/Object/RelocVisitor.h47
-rw-r--r--include/llvm/Object/StackMapParser.h35
-rw-r--r--include/llvm/Object/SymbolSize.h11
-rw-r--r--include/llvm/Object/SymbolicFile.h13
-rw-r--r--include/llvm/Object/Wasm.h99
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