summaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h4
-rw-r--r--include/llvm/Object/Binary.h2
-rw-r--r--include/llvm/Object/COFF.h21
-rw-r--r--include/llvm/Object/COFFImportFile.h7
-rw-r--r--include/llvm/Object/CVDebugRecord.h55
-rw-r--r--include/llvm/Object/Decompressor.h16
-rw-r--r--include/llvm/Object/ELF.h121
-rw-r--r--include/llvm/Object/ELFObjectFile.h109
-rw-r--r--include/llvm/Object/ELFTypes.h185
-rw-r--r--include/llvm/Object/IRObjectFile.h15
-rw-r--r--include/llvm/Object/MachO.h4
-rw-r--r--include/llvm/Object/MachOUniversal.h4
-rw-r--r--include/llvm/Object/ModuleSymbolTable.h9
-rw-r--r--include/llvm/Object/ObjectFile.h27
-rw-r--r--include/llvm/Object/RelocVisitor.h26
-rw-r--r--include/llvm/Object/Wasm.h137
-rw-r--r--include/llvm/Object/WasmTraits.h63
17 files changed, 611 insertions, 194 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 5a1512bb9d36..9ef1e4875191 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -91,9 +91,9 @@ public:
const Archive *Parent;
ArchiveMemberHeader Header;
- /// \brief Includes header but not padding byte.
+ /// Includes header but not padding byte.
StringRef Data;
- /// \brief Offset from Data to the start of the file.
+ /// Offset from Data to the start of the file.
uint16_t StartOfFile;
Expected<bool> isThinMember() const;
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 5e93691d1fd2..99745e24b8c8 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -156,7 +156,7 @@ public:
}
};
-/// @brief Create a Binary from Source, autodetecting the file type.
+/// Create a Binary from Source, autodetecting the file type.
///
/// @param Source The data to create the Binary from.
Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index b072dd5ba7d9..6caadea0175b 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -16,9 +16,9 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/Binary.h"
+#include "llvm/Object/CVDebugRecord.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/BinaryByteStream.h"
@@ -276,6 +276,7 @@ struct coff_symbol_generic {
};
struct coff_aux_section_definition;
+struct coff_aux_weak_external;
class COFFSymbolRef {
public:
@@ -360,6 +361,13 @@ public:
return getAux<coff_aux_section_definition>();
}
+ const coff_aux_weak_external *getWeakExternal() const {
+ if (!getNumberOfAuxSymbols() ||
+ getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
+ return nullptr;
+ return getAux<coff_aux_weak_external>();
+ }
+
bool isAbsolute() const {
return getSectionNumber() == -1;
}
@@ -452,11 +460,12 @@ struct coff_section {
if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
return 1;
- // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
+ // Bit [20:24] contains section alignment. 0 means use a default alignment
+ // of 16.
uint32_t Shift = (Characteristics >> 20) & 0xF;
if (Shift > 0)
return 1U << (Shift - 1);
- return 1;
+ return 16;
}
};
@@ -927,6 +936,7 @@ public:
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
Triple::ArchType getArch() const override;
+ Expected<uint64_t> getStartAddress() const override;
SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
import_directory_iterator import_directory_begin() const;
@@ -963,6 +973,8 @@ public:
std::error_code getDataDirectory(uint32_t index,
const data_directory *&Res) const;
std::error_code getSection(int32_t index, const coff_section *&Res) const;
+ std::error_code getSection(StringRef SectionName,
+ const coff_section *&Res) const;
template <typename coff_symbol_type>
std::error_code getSymbol(uint32_t Index,
@@ -1012,8 +1024,7 @@ public:
llvm_unreachable("null symbol table pointer!");
}
- iterator_range<const coff_relocation *>
- getRelocations(const coff_section *Sec) const;
+ ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const;
std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
uint64_t getSectionSize(const coff_section *Sec) const;
diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h
index 4b284de679b3..0a4556ad8884 100644
--- a/include/llvm/Object/COFFImportFile.h
+++ b/include/llvm/Object/COFFImportFile.h
@@ -74,6 +74,7 @@ struct COFFShortExport {
std::string Name;
std::string ExtName;
std::string SymbolName;
+ std::string AliasTarget;
uint16_t Ordinal = 0;
bool Noname = false;
@@ -81,10 +82,6 @@ struct COFFShortExport {
bool Private = false;
bool Constant = false;
- bool isWeak() {
- return ExtName.size() && ExtName != Name;
- }
-
friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) {
return L.Name == R.Name && L.ExtName == R.ExtName &&
L.Ordinal == R.Ordinal && L.Noname == R.Noname &&
@@ -98,7 +95,7 @@ struct COFFShortExport {
Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
- COFF::MachineTypes Machine, bool MakeWeakAliases);
+ COFF::MachineTypes Machine, bool MinGW);
} // namespace object
} // namespace llvm
diff --git a/include/llvm/Object/CVDebugRecord.h b/include/llvm/Object/CVDebugRecord.h
new file mode 100644
index 000000000000..faad72c0df29
--- /dev/null
+++ b/include/llvm/Object/CVDebugRecord.h
@@ -0,0 +1,55 @@
+//===- CVDebugRecord.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_CVDEBUGRECORD_H
+#define LLVM_OBJECT_CVDEBUGRECORD_H
+
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace OMF {
+struct Signature {
+ enum ID : uint32_t {
+ PDB70 = 0x53445352, // RSDS
+ PDB20 = 0x3031424e, // NB10
+ CV50 = 0x3131424e, // NB11
+ CV41 = 0x3930424e, // NB09
+ };
+
+ support::ulittle32_t CVSignature;
+ support::ulittle32_t Offset;
+};
+}
+
+namespace codeview {
+struct PDB70DebugInfo {
+ support::ulittle32_t CVSignature;
+ uint8_t Signature[16];
+ support::ulittle32_t Age;
+ // char PDBFileName[];
+};
+
+struct PDB20DebugInfo {
+ support::ulittle32_t CVSignature;
+ support::ulittle32_t Offset;
+ support::ulittle32_t Signature;
+ support::ulittle32_t Age;
+ // char PDBFileName[];
+};
+
+union DebugInfo {
+ struct OMF::Signature Signature;
+ struct PDB20DebugInfo PDB20;
+ struct PDB70DebugInfo PDB70;
+};
+}
+}
+
+#endif
+
diff --git a/include/llvm/Object/Decompressor.h b/include/llvm/Object/Decompressor.h
index c8e888d285e4..2a77d2ffbf68 100644
--- a/include/llvm/Object/Decompressor.h
+++ b/include/llvm/Object/Decompressor.h
@@ -17,10 +17,10 @@
namespace llvm {
namespace object {
-/// @brief Decompressor helps to handle decompression of compressed sections.
+/// Decompressor helps to handle decompression of compressed sections.
class Decompressor {
public:
- /// @brief Create decompressor object.
+ /// Create decompressor object.
/// @param Name Section name.
/// @param Data Section content.
/// @param IsLE Flag determines if Data is in little endian form.
@@ -28,27 +28,27 @@ public:
static Expected<Decompressor> create(StringRef Name, StringRef Data,
bool IsLE, bool Is64Bit);
- /// @brief Resize the buffer and uncompress section data into it.
+ /// Resize the buffer and uncompress section data into it.
/// @param Out Destination buffer.
template <class T> Error resizeAndDecompress(T &Out) {
Out.resize(DecompressedSize);
return decompress({Out.data(), (size_t)DecompressedSize});
}
- /// @brief Uncompress section data to raw buffer provided.
+ /// Uncompress section data to raw buffer provided.
/// @param Buffer Destination buffer.
Error decompress(MutableArrayRef<char> Buffer);
- /// @brief Return memory buffer size required for decompression.
+ /// Return memory buffer size required for decompression.
uint64_t getDecompressedSize() { return DecompressedSize; }
- /// @brief Return true if section is compressed, including gnu-styled case.
+ /// Return true if section is compressed, including gnu-styled case.
static bool isCompressed(const object::SectionRef &Section);
- /// @brief Return true if section is a ELF compressed one.
+ /// Return true if section is a ELF compressed one.
static bool isCompressedELFSection(uint64_t Flags, StringRef Name);
- /// @brief Return true if section name matches gnu style compressed one.
+ /// Return true if section name matches gnu style compressed one.
static bool isGnuStyle(StringRef Name);
private:
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 45c98233dec0..752d468fd25b 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -32,6 +32,7 @@ namespace llvm {
namespace object {
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type);
+uint32_t getELFRelrRelocationType(uint32_t Machine);
StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type);
// Subclasses of ELFFile may need this for template instantiation
@@ -60,6 +61,7 @@ public:
using Elf_Phdr = typename ELFT::Phdr;
using Elf_Rel = typename ELFT::Rel;
using Elf_Rela = typename ELFT::Rela;
+ using Elf_Relr = typename ELFT::Relr;
using Elf_Verdef = typename ELFT::Verdef;
using Elf_Verdaux = typename ELFT::Verdaux;
using Elf_Verneed = typename ELFT::Verneed;
@@ -67,11 +69,15 @@ public:
using Elf_Versym = typename ELFT::Versym;
using Elf_Hash = typename ELFT::Hash;
using Elf_GnuHash = typename ELFT::GnuHash;
+ using Elf_Nhdr = typename ELFT::Nhdr;
+ using Elf_Note = typename ELFT::Note;
+ using Elf_Note_Iterator = typename ELFT::NoteIterator;
using Elf_Dyn_Range = typename ELFT::DynRange;
using Elf_Shdr_Range = typename ELFT::ShdrRange;
using Elf_Sym_Range = typename ELFT::SymRange;
using Elf_Rel_Range = typename ELFT::RelRange;
using Elf_Rela_Range = typename ELFT::RelaRange;
+ using Elf_Relr_Range = typename ELFT::RelrRange;
using Elf_Phdr_Range = typename ELFT::PhdrRange;
const uint8_t *base() const {
@@ -107,8 +113,12 @@ public:
StringRef getRelocationTypeName(uint32_t Type) const;
void getRelocationTypeName(uint32_t Type,
SmallVectorImpl<char> &Result) const;
+ uint32_t getRelrRelocationType() const;
- /// \brief Get the symbol for a given relocation.
+ const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const;
+ const char *getDynamicTagAsString(uint64_t Type) const;
+
+ /// Get the symbol for a given relocation.
Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
const Elf_Shdr *SymTab) const;
@@ -126,6 +136,10 @@ public:
Expected<Elf_Shdr_Range> sections() const;
+ Expected<Elf_Dyn_Range> dynamicEntries() const;
+
+ Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const;
+
Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const {
if (!Sec)
return makeArrayRef<Elf_Sym>(nullptr, nullptr);
@@ -140,9 +154,15 @@ public:
return getSectionContentsAsArray<Elf_Rel>(Sec);
}
+ Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const {
+ return getSectionContentsAsArray<Elf_Relr>(Sec);
+ }
+
+ Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const;
+
Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const;
- /// \brief Iterate over program header table.
+ /// 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");
@@ -155,6 +175,73 @@ public:
return makeArrayRef(Begin, Begin + getHeader()->e_phnum);
}
+ /// Get an iterator over notes in a program header.
+ ///
+ /// The program header must be of type \c PT_NOTE.
+ ///
+ /// \param Phdr the program header to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const {
+ if (Phdr.p_type != ELF::PT_NOTE) {
+ Err = createError("attempt to iterate notes of non-note program header");
+ return Elf_Note_Iterator(Err);
+ }
+ if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) {
+ Err = createError("invalid program header offset/size");
+ return Elf_Note_Iterator(Err);
+ }
+ return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err);
+ }
+
+ /// Get an iterator over notes in a section.
+ ///
+ /// The section must be of type \c SHT_NOTE.
+ ///
+ /// \param Shdr the section to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const {
+ if (Shdr.sh_type != ELF::SHT_NOTE) {
+ Err = createError("attempt to iterate notes of non-note section");
+ return Elf_Note_Iterator(Err);
+ }
+ if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) {
+ Err = createError("invalid section offset/size");
+ return Elf_Note_Iterator(Err);
+ }
+ return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err);
+ }
+
+ /// Get the end iterator for notes.
+ Elf_Note_Iterator notes_end() const {
+ return Elf_Note_Iterator();
+ }
+
+ /// Get an iterator range over notes of a program header.
+ ///
+ /// The program header must be of type \c PT_NOTE.
+ ///
+ /// \param Phdr the program header to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr,
+ Error &Err) const {
+ return make_range(notes_begin(Phdr, Err), notes_end());
+ }
+
+ /// Get an iterator range over notes of a section.
+ ///
+ /// The section must be of type \c SHT_NOTE.
+ ///
+ /// \param Shdr the section to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr,
+ Error &Err) const {
+ return make_range(notes_begin(Shdr, Err), notes_end());
+ }
+
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;
@@ -165,6 +252,7 @@ public:
Elf_Sym_Range Symtab,
ArrayRef<Elf_Word> ShndxTable) const;
Expected<const Elf_Shdr *> getSection(uint32_t Index) const;
+ Expected<const Elf_Shdr *> getSection(const StringRef SectionName) const;
Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec,
uint32_t Index) const;
@@ -177,10 +265,10 @@ public:
Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const;
};
-using ELF32LEFile = ELFFile<ELFType<support::little, false>>;
-using ELF64LEFile = ELFFile<ELFType<support::little, true>>;
-using ELF32BEFile = ELFFile<ELFType<support::big, false>>;
-using ELF64BEFile = ELFFile<ELFType<support::big, true>>;
+using ELF32LEFile = ELFFile<ELF32LE>;
+using ELF64LEFile = ELFFile<ELF64LE>;
+using ELF32BEFile = ELFFile<ELF32BE>;
+using ELF64BEFile = ELFFile<ELF64BE>;
template <class ELFT>
inline Expected<const typename ELFT::Shdr *>
@@ -327,6 +415,11 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
}
template <class ELFT>
+uint32_t ELFFile<ELFT>::getRelrRelocationType() const {
+ return getELFRelrRelocationType(getHeader()->e_machine);
+}
+
+template <class ELFT>
Expected<const typename ELFT::Sym *>
ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
const Elf_Shdr *SymTab) const {
@@ -429,6 +522,22 @@ ELFFile<ELFT>::getSection(uint32_t Index) const {
}
template <class ELFT>
+Expected<const typename ELFT::Shdr *>
+ELFFile<ELFT>::getSection(const StringRef SectionName) const {
+ auto TableOrErr = sections();
+ if (!TableOrErr)
+ return TableOrErr.takeError();
+ for (auto &Sec : *TableOrErr) {
+ auto SecNameOrErr = getSectionName(&Sec);
+ if (!SecNameOrErr)
+ return SecNameOrErr.takeError();
+ if (*SecNameOrErr == SectionName)
+ return &Sec;
+ }
+ return createError("invalid section name");
+}
+
+template <class ELFT>
Expected<StringRef>
ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
if (Section->sh_type != ELF::SHT_STRTAB)
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 40503cb6bb9d..2c0905d545a7 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -15,6 +15,7 @@
#define LLVM_OBJECT_ELFOBJECTFILE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@@ -67,6 +68,9 @@ public:
virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0;
+ /// Returns platform-specific object flags, if any.
+ virtual unsigned getPlatformFlags() const = 0;
+
elf_symbol_iterator_range symbols() const;
static bool classof(const Binary *v) { return v->isELF(); }
@@ -77,7 +81,11 @@ public:
SubtargetFeatures getARMFeatures() const;
+ SubtargetFeatures getRISCVFeatures() const;
+
void setARMSubArch(Triple &TheTriple) const override;
+
+ virtual uint16_t getEType() const = 0;
};
class ELFSectionRef : public SectionRef {
@@ -195,19 +203,20 @@ ELFObjectFileBase::symbols() const {
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
uint16_t getEMachine() const override;
+ uint16_t getEType() const override;
uint64_t getSymbolSize(DataRefImpl Sym) const override;
public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
- using uintX_t = typename ELFFile<ELFT>::uintX_t;
+ using uintX_t = typename ELFT::uint;
- using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
- using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
- using Elf_Ehdr = typename ELFFile<ELFT>::Elf_Ehdr;
- using Elf_Rel = typename ELFFile<ELFT>::Elf_Rel;
- using Elf_Rela = typename ELFFile<ELFT>::Elf_Rela;
- using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;
+ using Elf_Sym = typename ELFT::Sym;
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Ehdr = typename ELFT::Ehdr;
+ using Elf_Rel = typename ELFT::Rel;
+ using Elf_Rela = typename ELFT::Rela;
+ using Elf_Dyn = typename ELFT::Dyn;
private:
ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF,
@@ -251,6 +260,7 @@ protected:
bool isSectionVirtual(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
+ std::vector<SectionRef> dynamic_relocation_sections() const override;
section_iterator getRelocatedSection(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
@@ -265,7 +275,7 @@ protected:
uint64_t getSectionOffset(DataRefImpl Sec) const override;
StringRef getRelocationTypeName(uint32_t Type) const;
- /// \brief Get the relocation section that contains \a Rel.
+ /// Get the relocation section that contains \a Rel.
const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
auto RelSecOrErr = EF.getSection(Rel.d.a);
if (!RelSecOrErr)
@@ -363,11 +373,9 @@ public:
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
Triple::ArchType getArch() const override;
+ Expected<uint64_t> getStartAddress() const override;
- std::error_code getPlatformFlags(unsigned &Result) const override {
- Result = EF.getHeader()->e_flags;
- return std::error_code();
- }
+ unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; }
std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override {
auto SectionsOrErr = EF.sections();
@@ -404,10 +412,10 @@ public:
bool isRelocatableObject() const override;
};
-using ELF32LEObjectFile = ELFObjectFile<ELFType<support::little, false>>;
-using ELF64LEObjectFile = ELFObjectFile<ELFType<support::little, true>>;
-using ELF32BEObjectFile = ELFObjectFile<ELFType<support::big, false>>;
-using ELF64BEObjectFile = ELFObjectFile<ELFType<support::big, true>>;
+using ELF32LEObjectFile = ELFObjectFile<ELF32LE>;
+using ELF64LEObjectFile = ELFObjectFile<ELF64LE>;
+using ELF32BEObjectFile = ELFObjectFile<ELF32BE>;
+using ELF64BEObjectFile = ELFObjectFile<ELF64BE>;
template <class ELFT>
void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const {
@@ -505,6 +513,10 @@ uint16_t ELFObjectFile<ELFT>::getEMachine() const {
return EF.getHeader()->e_machine;
}
+template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const {
+ return EF.getHeader()->e_type;
+}
+
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
return getSymbol(Sym)->st_size;
@@ -698,8 +710,9 @@ bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const {
const Elf_Shdr *EShdr = getSection(Sec);
- return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
- EShdr->sh_type == ELF::SHT_PROGBITS;
+ return EShdr->sh_type == ELF::SHT_PROGBITS &&
+ EShdr->sh_flags & ELF::SHF_ALLOC &&
+ !(EShdr->sh_flags & ELF::SHF_EXECINSTR);
}
template <class ELFT>
@@ -710,6 +723,35 @@ bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const {
}
template <class ELFT>
+std::vector<SectionRef>
+ELFObjectFile<ELFT>::dynamic_relocation_sections() const {
+ std::vector<SectionRef> Res;
+ std::vector<uintptr_t> Offsets;
+
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return Res;
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (Sec.sh_type != ELF::SHT_DYNAMIC)
+ continue;
+ Elf_Dyn *Dynamic =
+ reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset);
+ for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) {
+ if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA ||
+ Dynamic->d_tag == ELF::DT_JMPREL) {
+ Offsets.push_back(Dynamic->d_un.d_val);
+ }
+ }
+ }
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (is_contained(Offsets, Sec.sh_offset))
+ Res.emplace_back(toDRI(&Sec), this);
+ }
+ return Res;
+}
+
+template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
return getSection(Sec)->sh_type == ELF::SHT_NOBITS;
}
@@ -790,8 +832,6 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
- assert(EF.getHeader()->e_type == ELF::ET_REL &&
- "Only relocatable object files have relocation offsets");
const Elf_Shdr *sec = getRelSection(Rel);
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->r_offset;
@@ -986,8 +1026,6 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
case ELF::EM_SPARC:
case ELF::EM_SPARC32PLUS:
return "ELF32-sparc";
- case ELF::EM_WEBASSEMBLY:
- return "ELF32-wasm";
case ELF::EM_AMDGPU:
return "ELF32-amdgpu";
default:
@@ -1011,8 +1049,6 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF64-sparc";
case ELF::EM_MIPS:
return "ELF64-mips";
- case ELF::EM_WEBASSEMBLY:
- return "ELF64-wasm";
case ELF::EM_AMDGPU:
return "ELF64-amdgpu";
case ELF::EM_BPF:
@@ -1074,26 +1110,20 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
return IsLittleEndian ? Triple::sparcel : Triple::sparc;
case ELF::EM_SPARCV9:
return Triple::sparcv9;
- case ELF::EM_WEBASSEMBLY:
- switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
- case ELF::ELFCLASS32: return Triple::wasm32;
- case ELF::ELFCLASS64: return Triple::wasm64;
- default: return 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:
+ unsigned MACH = EF.getHeader()->e_flags & ELF::EF_AMDGPU_MACH;
+ if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST &&
+ MACH <= ELF::EF_AMDGPU_MACH_R600_LAST)
return Triple::r600;
- case ELF::EF_AMDGPU_ARCH_GCN:
+ if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST &&
+ MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST)
return Triple::amdgcn;
- default:
- return Triple::UnknownArch;
- }
+
+ return Triple::UnknownArch;
}
case ELF::EM_BPF:
@@ -1105,6 +1135,11 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
}
template <class ELFT>
+Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const {
+ return EF.getHeader()->e_entry;
+}
+
+template <class ELFT>
ELFObjectFileBase::elf_symbol_iterator_range
ELFObjectFile<ELFT>::getDynamicSymbolIterators() const {
return make_range(dynamic_symbol_begin(), dynamic_symbol_end());
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 83b688548fdc..fb386120e34d 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -40,11 +40,15 @@ template <class ELFT> struct Elf_Versym_Impl;
template <class ELFT> struct Elf_Hash_Impl;
template <class ELFT> struct Elf_GnuHash_Impl;
template <class ELFT> struct Elf_Chdr_Impl;
+template <class ELFT> struct Elf_Nhdr_Impl;
+template <class ELFT> class Elf_Note_Impl;
+template <class ELFT> class Elf_Note_Iterator_Impl;
+template <class ELFT> struct Elf_CGProfile_Impl;
template <endianness E, bool Is64> struct ELFType {
private:
template <typename Ty>
- using packed = support::detail::packed_endian_specific_integral<Ty, E, 2>;
+ using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>;
public:
static const endianness TargetEndianness = E;
@@ -58,6 +62,7 @@ public:
using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>;
using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>;
using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>;
+ using Relr = packed<uint>;
using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>;
@@ -66,11 +71,16 @@ public:
using Hash = Elf_Hash_Impl<ELFType<E, Is64>>;
using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>;
using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>;
+ using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>;
+ using Note = Elf_Note_Impl<ELFType<E, Is64>>;
+ using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
+ using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
using DynRange = ArrayRef<Dyn>;
using ShdrRange = ArrayRef<Shdr>;
using SymRange = ArrayRef<Sym>;
using RelRange = ArrayRef<Rel>;
using RelaRange = ArrayRef<Rela>;
+ using RelrRange = ArrayRef<Relr>;
using PhdrRange = ArrayRef<Phdr>;
using Half = packed<uint16_t>;
@@ -90,46 +100,7 @@ using ELF64BE = ELFType<support::big, true>;
// Use an alignment of 2 for the typedefs since that is the worst case for
// ELF files in archives.
-// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
-template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon {
- using Elf_Half = support::detail::packed_endian_specific_integral<
- uint16_t, target_endianness, 2>;
- using Elf_Word = support::detail::packed_endian_specific_integral<
- uint32_t, target_endianness, 2>;
- using Elf_Sword = support::detail::packed_endian_specific_integral<
- int32_t, target_endianness, 2>;
- using Elf_Xword = support::detail::packed_endian_specific_integral<
- uint64_t, target_endianness, 2>;
- using Elf_Sxword = support::detail::packed_endian_specific_integral<
- int64_t, target_endianness, 2>;
-};
-
-template <class ELFT> struct ELFDataTypeTypedefHelper;
-
-/// ELF 32bit types.
-template <endianness TargetEndianness>
-struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>>
- : ELFDataTypeTypedefHelperCommon<TargetEndianness> {
- using value_type = uint32_t;
- using Elf_Addr = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
- using Elf_Off = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
-};
-
-/// ELF 64bit types.
-template <endianness TargetEndianness>
-struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
- : ELFDataTypeTypedefHelperCommon<TargetEndianness> {
- using value_type = uint64_t;
- using Elf_Addr = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
- using Elf_Off = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
-};
-
// I really don't like doing this, but the alternative is copypasta.
-
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
using Elf_Addr = typename ELFT::Addr; \
using Elf_Off = typename ELFT::Off; \
@@ -139,9 +110,9 @@ struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
using Elf_Xword = typename ELFT::Xword; \
using Elf_Sxword = typename ELFT::Sxword;
-#define LLD_ELF_COMMA ,
+#define LLVM_ELF_COMMA ,
#define LLVM_ELF_IMPORT_TYPES(E, W) \
- LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLD_ELF_COMMA W>)
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>)
// Section header.
template <class ELFT> struct Elf_Shdr_Base;
@@ -181,7 +152,7 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
using Elf_Shdr_Base<ELFT>::sh_entsize;
using Elf_Shdr_Base<ELFT>::sh_size;
- /// @brief Get the number of entities this section contains if it has any.
+ /// Get the number of entities this section contains if it has any.
unsigned getEntityCount() const {
if (sh_entsize == 0)
return 0;
@@ -590,6 +561,134 @@ struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> {
Elf_Xword ch_addralign;
};
+/// Note header
+template <class ELFT>
+struct Elf_Nhdr_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Word n_namesz;
+ Elf_Word n_descsz;
+ Elf_Word n_type;
+
+ /// The alignment of the name and descriptor.
+ ///
+ /// Implementations differ from the specification here: in practice all
+ /// variants align both the name and descriptor to 4-bytes.
+ static const unsigned int Align = 4;
+
+ /// Get the size of the note, including name, descriptor, and padding.
+ size_t getSize() const {
+ return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz);
+ }
+};
+
+/// An ELF note.
+///
+/// Wraps a note header, providing methods for accessing the name and
+/// descriptor safely.
+template <class ELFT>
+class Elf_Note_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+
+ const Elf_Nhdr_Impl<ELFT> &Nhdr;
+
+ template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl;
+
+ Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {}
+
+public:
+ /// Get the note's name, excluding the terminating null byte.
+ StringRef getName() const {
+ if (!Nhdr.n_namesz)
+ return StringRef();
+ return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr),
+ Nhdr.n_namesz - 1);
+ }
+
+ /// Get the note's descriptor.
+ ArrayRef<Elf_Word> getDesc() const {
+ if (!Nhdr.n_descsz)
+ return ArrayRef<Elf_Word>();
+ return ArrayRef<Elf_Word>(
+ reinterpret_cast<const Elf_Word *>(
+ reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) +
+ alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz)),
+ Nhdr.n_descsz);
+ }
+
+ /// Get the note's type.
+ Elf_Word getType() const { return Nhdr.n_type; }
+};
+
+template <class ELFT>
+class Elf_Note_Iterator_Impl
+ : std::iterator<std::forward_iterator_tag, Elf_Note_Impl<ELFT>> {
+ // Nhdr being a nullptr marks the end of iteration.
+ const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr;
+ size_t RemainingSize = 0u;
+ Error *Err = nullptr;
+
+ template <class ELFFileELFT> friend class ELFFile;
+
+ // Stop iteration and indicate an overflow.
+ void stopWithOverflowError() {
+ Nhdr = nullptr;
+ *Err = make_error<StringError>("ELF note overflows container",
+ object_error::parse_failed);
+ }
+
+ // Advance Nhdr by NoteSize bytes, starting from NhdrPos.
+ //
+ // Assumes NoteSize <= RemainingSize. Ensures Nhdr->getSize() <= RemainingSize
+ // upon returning. Handles stopping iteration when reaching the end of the
+ // container, either cleanly or with an overflow error.
+ void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) {
+ RemainingSize -= NoteSize;
+ if (RemainingSize == 0u)
+ Nhdr = nullptr;
+ else if (sizeof(*Nhdr) > RemainingSize)
+ stopWithOverflowError();
+ else {
+ Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize);
+ if (Nhdr->getSize() > RemainingSize)
+ stopWithOverflowError();
+ }
+ }
+
+ Elf_Note_Iterator_Impl() {}
+ explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {}
+ Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err)
+ : RemainingSize(Size), Err(&Err) {
+ assert(Start && "ELF note iterator starting at NULL");
+ advanceNhdr(Start, 0u);
+ }
+
+public:
+ Elf_Note_Iterator_Impl &operator++() {
+ assert(Nhdr && "incremented ELF note end iterator");
+ const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr);
+ size_t NoteSize = Nhdr->getSize();
+ advanceNhdr(NhdrPos, NoteSize);
+ return *this;
+ }
+ bool operator==(Elf_Note_Iterator_Impl Other) const {
+ return Nhdr == Other.Nhdr;
+ }
+ bool operator!=(Elf_Note_Iterator_Impl Other) const {
+ return !(*this == Other);
+ }
+ Elf_Note_Impl<ELFT> operator*() const {
+ assert(Nhdr && "dereferenced ELF note end iterator");
+ return Elf_Note_Impl<ELFT>(*Nhdr);
+ }
+};
+
+template <class ELFT> struct Elf_CGProfile_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Word cgp_from;
+ Elf_Word cgp_to;
+ Elf_Xword cgp_weight;
+};
+
// MIPS .reginfo section
template <class ELFT>
struct Elf_Mips_RegInfo;
diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h
index 6c271b1a1f44..993359b766a1 100644
--- a/include/llvm/Object/IRObjectFile.h
+++ b/include/llvm/Object/IRObjectFile.h
@@ -50,11 +50,22 @@ public:
return v->isIR();
}
- /// \brief Finds and returns bitcode embedded in the given object file, or an
+ using module_iterator =
+ pointee_iterator<std::vector<std::unique_ptr<Module>>::const_iterator,
+ const Module>;
+
+ module_iterator module_begin() const { return module_iterator(Mods.begin()); }
+ module_iterator module_end() const { return module_iterator(Mods.end()); }
+
+ iterator_range<module_iterator> modules() const {
+ return make_range(module_begin(), module_end());
+ }
+
+ /// Finds and returns bitcode embedded in the given object file, or an
/// error code if not found.
static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
- /// \brief Finds and returns bitcode in the given memory buffer (which may
+ /// 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 Expected<MemoryBufferRef>
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index d0cc40da4293..531b3d249035 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -304,6 +304,8 @@ public:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ Expected<SectionRef> getSection(unsigned SectionIndex) const;
+ Expected<SectionRef> getSection(StringRef SectionName) const;
bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
@@ -463,7 +465,7 @@ public:
// In a MachO file, sections have a segment name. This is used in the .o
// files. They have a single segment, but this field specifies which segment
- // a section should be put in in the final object.
+ // a section should be put in the final object.
StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
// Names are stored as 16 bytes. These returns the raw 16 bytes without
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index 72837d0970c4..9e70b0bc30c0 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -34,9 +34,9 @@ class MachOUniversalBinary : public Binary {
public:
class ObjectForArch {
const MachOUniversalBinary *Parent;
- /// \brief Index of object in the universal binary.
+ /// Index of object in the universal binary.
uint32_t Index;
- /// \brief Descriptor of the object.
+ /// Descriptor of the object.
MachO::fat_arch Header;
MachO::fat_arch_64 Header64;
diff --git a/include/llvm/Object/ModuleSymbolTable.h b/include/llvm/Object/ModuleSymbolTable.h
index 9e9322885388..c3cbc27998e5 100644
--- a/include/llvm/Object/ModuleSymbolTable.h
+++ b/include/llvm/Object/ModuleSymbolTable.h
@@ -57,6 +57,15 @@ public:
static void CollectAsmSymbols(
const Module &M,
function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol);
+
+ /// Parse inline ASM and collect the symvers directives that are defined in
+ /// the current module.
+ ///
+ /// For each found symbol, call \p AsmSymver with the name of the symbol and
+ /// its alias.
+ static void
+ CollectAsmSymvers(const Module &M,
+ function_ref<void(StringRef, StringRef)> AsmSymver);
};
} // end namespace llvm
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 079a59468156..02d62e8e4879 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -65,7 +65,7 @@ public:
symbol_iterator getSymbol() const;
uint64_t getType() const;
- /// @brief Get a string that represents the type of this relocation.
+ /// Get a string that represents the type of this relocation.
///
/// This is for display purposes only.
void getTypeName(SmallVectorImpl<char> &Result) const;
@@ -100,7 +100,7 @@ public:
uint64_t getSize() const;
std::error_code getContents(StringRef &Result) const;
- /// @brief Get the alignment of this section as the actual value (not log 2).
+ /// Get the alignment of this section as the actual value (not log 2).
uint64_t getAlignment() const;
bool isCompressed() const;
@@ -154,12 +154,12 @@ public:
/// offset or a virtual address.
uint64_t getValue() const;
- /// @brief Get the alignment of this symbol as the actual value (not log 2).
+ /// Get the alignment of this symbol as the actual value (not log 2).
uint32_t getAlignment() const;
uint64_t getCommonSize() const;
Expected<SymbolRef::Type> getType() const;
- /// @brief Get section this symbol is defined in reference to. Result is
+ /// Get section this symbol is defined in reference to. Result is
/// end_sections() if it is undefined or is an absolute symbol.
Expected<section_iterator> getSection() const;
@@ -262,6 +262,10 @@ public:
return getCommonSymbolSizeImpl(Symb);
}
+ virtual std::vector<SectionRef> dynamic_relocation_sections() const {
+ return std::vector<SectionRef>();
+ }
+
using symbol_iterator_range = iterator_range<symbol_iterator>;
symbol_iterator_range symbols() const {
return symbol_iterator_range(symbol_begin(), symbol_end());
@@ -275,7 +279,7 @@ public:
return section_iterator_range(section_begin(), section_end());
}
- /// @brief The number of bytes used to represent an address in this object
+ /// The number of bytes used to represent an address in this object
/// file format.
virtual uint8_t getBytesInAddress() const = 0;
@@ -283,16 +287,13 @@ public:
virtual Triple::ArchType getArch() const = 0;
virtual SubtargetFeatures getFeatures() const = 0;
virtual void setARMSubArch(Triple &TheTriple) const { }
+ virtual Expected<uint64_t> getStartAddress() const {
+ return errorCodeToError(object_error::parse_failed);
+ };
- /// @brief Create a triple from the data in this object file.
+ /// 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;
- return object_error::invalid_file_type;
- }
-
virtual std::error_code
getBuildAttributes(ARMAttributeParser &Attributes) const {
return std::error_code();
@@ -307,7 +308,7 @@ public:
/// @returns Pointer to ObjectFile subclass to handle this type of object.
/// @param ObjectPath The path to the object file. ObjectPath.isObject must
/// return true.
- /// @brief Create ObjectFile from path.
+ /// Create ObjectFile from path.
static Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath);
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index 2d0e938f06fd..008e109f6679 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -23,6 +23,7 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/Wasm.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
@@ -31,7 +32,7 @@
namespace llvm {
namespace object {
-/// @brief Base class for object file relocation visitors.
+/// Base class for object file relocation visitors.
class RelocVisitor {
public:
explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
@@ -46,6 +47,8 @@ public:
return visitCOFF(Rel, R, Value);
if (isa<MachOObjectFile>(ObjToVisit))
return visitMachO(Rel, R, Value);
+ if (isa<WasmObjectFile>(ObjToVisit))
+ return visitWasm(Rel, R, Value);
HasError = true;
return 0;
@@ -316,6 +319,27 @@ private:
HasError = true;
return 0;
}
+
+ uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (ObjToVisit.getArch() == Triple::wasm32) {
+ switch (Rel) {
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
+ // For wasm section, its offset at 0 -- ignoring Value
+ return 0;
+ }
+ }
+ HasError = true;
+ return 0;
+ }
};
} // end namespace object
diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h
index 71951d83f3cc..fd34e45feb62 100644
--- a/include/llvm/Object/Wasm.h
+++ b/include/llvm/Object/Wasm.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
@@ -34,61 +35,49 @@ namespace object {
class WasmSymbol {
public:
- enum class SymbolType {
- FUNCTION_IMPORT,
- FUNCTION_EXPORT,
- GLOBAL_IMPORT,
- GLOBAL_EXPORT,
- DEBUG_FUNCTION_NAME,
- };
-
- WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section,
- uint32_t ElementIndex, uint32_t FunctionType = 0)
- : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex),
- FunctionType(FunctionType) {}
+ WasmSymbol(const wasm::WasmSymbolInfo &Info,
+ const wasm::WasmSignature *FunctionType,
+ const wasm::WasmGlobalType *GlobalType)
+ : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {}
- StringRef Name;
- SymbolType Type;
- uint32_t Section;
- uint32_t Flags = 0;
+ const wasm::WasmSymbolInfo &Info;
+ const wasm::WasmSignature *FunctionType;
+ const wasm::WasmGlobalType *GlobalType;
- // Index into either the function or global index space.
- uint32_t ElementIndex;
-
- // For function, the type index
- uint32_t FunctionType;
+ bool isTypeFunction() const {
+ return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
+ }
- // Symbols can be both exported and imported (in the case of the weakly
- // defined symbol). In this the import index is stored as AltIndex.
- uint32_t AltIndex = 0;
- bool HasAltIndex = false;
+ bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
- void setAltIndex(uint32_t Index) {
- HasAltIndex = true;
- AltIndex = Index;
+ bool isTypeGlobal() const {
+ return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
}
- bool isFunction() const {
- return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT ||
- Type == WasmSymbol::SymbolType::FUNCTION_EXPORT ||
- Type == WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME;
+ bool isTypeSection() const {
+ return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
}
+ bool isDefined() const { return !isUndefined(); }
- bool isWeak() const {
+ bool isUndefined() const {
+ return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
+ }
+
+ bool isBindingWeak() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
}
- bool isGlobal() const {
+ bool isBindingGlobal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
}
- bool isLocal() const {
+ bool isBindingLocal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
}
unsigned getBinding() const {
- return Flags & wasm::WASM_SYMBOL_BINDING_MASK;
+ return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
}
bool isHidden() const {
@@ -96,16 +85,13 @@ public:
}
unsigned getVisibility() const {
- return Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
+ return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
}
- void print(raw_ostream &Out) const {
- Out << "Name=" << Name << ", Type=" << static_cast<int>(Type)
- << ", Flags=" << Flags << " ElemIndex=" << ElementIndex;
- }
+ void print(raw_ostream &Out) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+ LLVM_DUMP_METHOD void dump() const;
#endif
};
@@ -144,12 +130,16 @@ public:
ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
ArrayRef<wasm::WasmExport> exports() const { return Exports; }
+ ArrayRef<WasmSymbol> syms() const { return Symbols; }
const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
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; }
+ ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
uint32_t startFunction() const { return StartFunction; }
+ uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
+ uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -203,39 +193,50 @@ public:
SubtargetFeatures getFeatures() const override;
bool isRelocatableObject() const override;
+ struct ReadContext {
+ const uint8_t *Start;
+ const uint8_t *Ptr;
+ const uint8_t *End;
+ };
+
private:
bool isValidFunctionIndex(uint32_t Index) const;
+ bool isDefinedFunctionIndex(uint32_t Index) const;
+ bool isValidGlobalIndex(uint32_t Index) const;
+ bool isDefinedGlobalIndex(uint32_t Index) const;
+ bool isValidFunctionSymbol(uint32_t Index) const;
+ bool isValidGlobalSymbol(uint32_t Index) const;
+ bool isValidDataSymbol(uint32_t Index) const;
+ bool isValidSectionSymbol(uint32_t Index) const;
+ wasm::WasmFunction &getDefinedFunction(uint32_t Index);
+ wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
+
const WasmSection &getWasmSection(DataRefImpl Ref) const;
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
- WasmSection* findCustomSectionByName(StringRef Name);
- WasmSection* findSectionByType(uint32_t Type);
-
const uint8_t *getPtr(size_t Offset) const;
Error parseSection(WasmSection &Sec);
- Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
- const uint8_t *End);
+ Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
// Standard section types
- Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
- Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseTypeSection(ReadContext &Ctx);
+ Error parseImportSection(ReadContext &Ctx);
+ Error parseFunctionSection(ReadContext &Ctx);
+ Error parseTableSection(ReadContext &Ctx);
+ Error parseMemorySection(ReadContext &Ctx);
+ Error parseGlobalSection(ReadContext &Ctx);
+ Error parseExportSection(ReadContext &Ctx);
+ Error parseStartSection(ReadContext &Ctx);
+ Error parseElemSection(ReadContext &Ctx);
+ Error parseCodeSection(ReadContext &Ctx);
+ Error parseDataSection(ReadContext &Ctx);
// Custom section types
- Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
- const uint8_t *End);
-
- void populateSymbolTable();
+ Error parseNameSection(ReadContext &Ctx);
+ Error parseLinkingSection(ReadContext &Ctx);
+ Error parseLinkingSectionSymtab(ReadContext &Ctx);
+ Error parseLinkingSectionComdat(ReadContext &Ctx);
+ Error parseRelocSection(StringRef Name, ReadContext &Ctx);
wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
@@ -250,15 +251,15 @@ private:
std::vector<WasmSegment> DataSegments;
std::vector<wasm::WasmFunction> Functions;
std::vector<WasmSymbol> Symbols;
+ std::vector<wasm::WasmFunctionName> DebugNames;
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;
+ uint32_t CodeSection = 0;
+ uint32_t DataSection = 0;
+ uint32_t GlobalSection = 0;
};
} // end namespace object
diff --git a/include/llvm/Object/WasmTraits.h b/include/llvm/Object/WasmTraits.h
new file mode 100644
index 000000000000..ebcd00b15227
--- /dev/null
+++ b/include/llvm/Object/WasmTraits.h
@@ -0,0 +1,63 @@
+//===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides llvm::DenseMapInfo traits for the Wasm structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_WASMTRAITS_H
+#define LLVM_OBJECT_WASMTRAITS_H
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/BinaryFormat/Wasm.h"
+
+namespace llvm {
+
+template <typename T> struct DenseMapInfo;
+
+// Traits for using WasmSignature in a DenseMap.
+template <> struct DenseMapInfo<wasm::WasmSignature> {
+ static wasm::WasmSignature getEmptyKey() {
+ return wasm::WasmSignature{{}, 1};
+ }
+ static wasm::WasmSignature getTombstoneKey() {
+ return wasm::WasmSignature{{}, 2};
+ }
+ static unsigned getHashValue(const wasm::WasmSignature &Sig) {
+ unsigned H = hash_value(Sig.ReturnType);
+ for (int32_t Param : Sig.ParamTypes)
+ H = hash_combine(H, Param);
+ return H;
+ }
+ static bool isEqual(const wasm::WasmSignature &LHS,
+ const wasm::WasmSignature &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Traits for using WasmGlobalType in a DenseMap
+template <> struct DenseMapInfo<wasm::WasmGlobalType> {
+ static wasm::WasmGlobalType getEmptyKey() {
+ return wasm::WasmGlobalType{1, true};
+ }
+ static wasm::WasmGlobalType getTombstoneKey() {
+ return wasm::WasmGlobalType{2, true};
+ }
+ static unsigned getHashValue(const wasm::WasmGlobalType &GlobalType) {
+ return hash_combine(GlobalType.Type, GlobalType.Mutable);
+ }
+ static bool isEqual(const wasm::WasmGlobalType &LHS,
+ const wasm::WasmGlobalType &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_WASMTRAITS_H