summaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /include/llvm/Object
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h2
-rw-r--r--include/llvm/Object/ArchiveWriter.h9
-rw-r--r--include/llvm/Object/Binary.h15
-rw-r--r--include/llvm/Object/COFF.h55
-rw-r--r--include/llvm/Object/COFFImportFile.h8
-rw-r--r--include/llvm/Object/ELF.h26
-rw-r--r--include/llvm/Object/ELFObjectFile.h111
-rw-r--r--include/llvm/Object/ELFTypes.h8
-rw-r--r--include/llvm/Object/IRObjectFile.h4
-rw-r--r--include/llvm/Object/IRSymtab.h13
-rw-r--r--include/llvm/Object/MachO.h41
-rw-r--r--include/llvm/Object/ObjectFile.h17
-rw-r--r--include/llvm/Object/RelocVisitor.h15
-rw-r--r--include/llvm/Object/StackMapParser.h2
-rw-r--r--include/llvm/Object/Wasm.h87
-rw-r--r--include/llvm/Object/WindowsResource.h16
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 {