aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h1
-rw-r--r--include/llvm/Object/Binary.h11
-rw-r--r--include/llvm/Object/ELF.h2
-rw-r--r--include/llvm/Object/ELFObjectFile.h31
-rw-r--r--include/llvm/Object/IRSymtab.h302
-rw-r--r--include/llvm/Object/MachO.h197
-rw-r--r--include/llvm/Object/ModuleSummaryIndexObjectFile.h7
-rw-r--r--include/llvm/Object/ModuleSymbolTable.h3
-rw-r--r--include/llvm/Object/ObjectFile.h8
-rw-r--r--include/llvm/Object/RelocVisitor.h7
-rw-r--r--include/llvm/Object/SymbolicFile.h4
-rw-r--r--include/llvm/Object/Wasm.h112
12 files changed, 646 insertions, 39 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 08128b0c2515..d423957d9b79 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -212,6 +212,7 @@ public:
K_GNU,
K_MIPS64,
K_BSD,
+ K_DARWIN,
K_DARWIN64,
K_COFF
};
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 00d06e3c7437..bdbe94301dc7 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -14,6 +14,7 @@
#ifndef LLVM_OBJECT_BINARY_H
#define LLVM_OBJECT_BINARY_H
+#include "llvm/ADT/Triple.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -133,6 +134,16 @@ public:
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
}
+
+ Triple::ObjectFormatType getTripleObjectFormat() const {
+ if (isCOFF())
+ return Triple::COFF;
+ if (isMachO())
+ return Triple::MachO;
+ if (isELF())
+ return Triple::ELF;
+ return Triple::UnknownObjectFormat;
+ }
};
/// @brief Create a Binary from Source, autodetecting the file type.
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index aaa79ae70f01..7a3155b3953e 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -340,7 +340,7 @@ ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
}
template <class ELFT>
-static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
+bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
return VAddr < Phdr->p_vaddr;
}
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 69987d433e2d..9e95f2958aa4 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -26,6 +26,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
@@ -72,6 +73,12 @@ public:
static inline bool classof(const Binary *v) { return v->isELF(); }
SubtargetFeatures getFeatures() const override;
+
+ SubtargetFeatures getMIPSFeatures() const;
+
+ SubtargetFeatures getARMFeatures() const;
+
+ void setARMSubArch(Triple &TheTriple) const override;
};
class ELFSectionRef : public SectionRef {
@@ -356,6 +363,28 @@ public:
return std::error_code();
}
+ std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override {
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return errorToErrorCode(SectionsOrErr.takeError());
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) {
+ auto ErrorOrContents = EF.getSectionContents(&Sec);
+ if (!ErrorOrContents)
+ return errorToErrorCode(ErrorOrContents.takeError());
+
+ auto Contents = ErrorOrContents.get();
+ if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
+ return std::error_code();
+
+ Attributes.Parse(Contents, ELFT::TargetEndianness == support::little);
+ break;
+ }
+ }
+ return std::error_code();
+ }
+
const ELFFile<ELFT> *getELFFile() const { return &EF; }
bool isDyldType() const { return isDyldELFObject; }
@@ -866,6 +895,8 @@ elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const {
template <class ELFT>
elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const {
const Elf_Shdr *SymTab = DotDynSymSec;
+ if (!SymTab)
+ return dynamic_symbol_begin();
DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
return basic_symbol_iterator(SymbolRef(Sym, this));
}
diff --git a/include/llvm/Object/IRSymtab.h b/include/llvm/Object/IRSymtab.h
new file mode 100644
index 000000000000..cde6f3b0f651
--- /dev/null
+++ b/include/llvm/Object/IRSymtab.h
@@ -0,0 +1,302 @@
+//===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains data definitions and a reader and builder for a symbol
+// table for LLVM IR. Its purpose is to allow linkers and other consumers of
+// bitcode files to efficiently read the symbol table for symbol resolution
+// purposes without needing to construct a module in memory.
+//
+// As with most object files the symbol table has two parts: the symbol table
+// itself and a string table which is referenced by the symbol table.
+//
+// A symbol table corresponds to a single bitcode file, which may consist of
+// multiple modules, so symbol tables may likewise contain symbols for multiple
+// modules.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_IRSYMTAB_H
+#define LLVM_OBJECT_IRSYMTAB_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace irsymtab {
+namespace storage {
+
+// The data structures in this namespace define the low-level serialization
+// format. Clients that just want to read a symbol table should use the
+// irsymtab::Reader class.
+
+typedef support::ulittle32_t Word;
+
+/// A reference to a string in the string table.
+struct Str {
+ Word Offset;
+ StringRef get(StringRef Strtab) const {
+ return Strtab.data() + Offset;
+ }
+};
+
+/// A reference to a range of objects in the symbol table.
+template <typename T> struct Range {
+ Word Offset, Size;
+ ArrayRef<T> get(StringRef Symtab) const {
+ return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size};
+ }
+};
+
+/// Describes the range of a particular module's symbols within the symbol
+/// table.
+struct Module {
+ Word Begin, End;
+};
+
+/// This is equivalent to an IR comdat.
+struct Comdat {
+ Str Name;
+};
+
+/// Contains the information needed by linkers for symbol resolution, as well as
+/// by the LTO implementation itself.
+struct Symbol {
+ /// The mangled symbol name.
+ Str Name;
+
+ /// The unmangled symbol name, or the empty string if this is not an IR
+ /// symbol.
+ Str IRName;
+
+ /// The index into Header::Comdats, or -1 if not a comdat member.
+ Word ComdatIndex;
+
+ Word Flags;
+ enum FlagBits {
+ FB_visibility, // 2 bits
+ FB_undefined = FB_visibility + 2,
+ FB_weak,
+ FB_common,
+ FB_indirect,
+ FB_used,
+ FB_tls,
+ FB_may_omit,
+ FB_global,
+ FB_format_specific,
+ FB_unnamed_addr,
+ FB_executable,
+ };
+
+ /// The index into the Uncommon table, or -1 if this symbol does not have an
+ /// Uncommon.
+ Word UncommonIndex;
+};
+
+/// This data structure contains rarely used symbol fields and is optionally
+/// referenced by a Symbol.
+struct Uncommon {
+ Word CommonSize, CommonAlign;
+
+ /// COFF-specific: the name of the symbol that a weak external resolves to
+ /// if not defined.
+ Str COFFWeakExternFallbackName;
+};
+
+struct Header {
+ Range<Module> Modules;
+ Range<Comdat> Comdats;
+ Range<Symbol> Symbols;
+ Range<Uncommon> Uncommons;
+
+ Str TargetTriple, SourceFileName;
+
+ /// COFF-specific: linker directives.
+ Str COFFLinkerOpts;
+};
+
+}
+
+/// Fills in Symtab and Strtab with a valid symbol and string table for Mods.
+Error build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
+ SmallVector<char, 0> &Strtab);
+
+/// This represents a symbol that has been read from a storage::Symbol and
+/// possibly a storage::Uncommon.
+struct Symbol {
+ // Copied from storage::Symbol.
+ StringRef Name, IRName;
+ int ComdatIndex;
+ uint32_t Flags;
+
+ // Copied from storage::Uncommon.
+ uint32_t CommonSize, CommonAlign;
+ StringRef COFFWeakExternFallbackName;
+
+ /// Returns the mangled symbol name.
+ StringRef getName() const { return Name; }
+
+ /// Returns the unmangled symbol name, or the empty string if this is not an
+ /// IR symbol.
+ StringRef getIRName() const { return IRName; }
+
+ /// Returns the index into the comdat table (see Reader::getComdatTable()), or
+ /// -1 if not a comdat member.
+ int getComdatIndex() const { return ComdatIndex; }
+
+ using S = storage::Symbol;
+ GlobalValue::VisibilityTypes getVisibility() const {
+ return GlobalValue::VisibilityTypes((Flags >> S::FB_visibility) & 3);
+ }
+ bool isUndefined() const { return (Flags >> S::FB_undefined) & 1; }
+ bool isWeak() const { return (Flags >> S::FB_weak) & 1; }
+ bool isCommon() const { return (Flags >> S::FB_common) & 1; }
+ bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; }
+ bool isUsed() const { return (Flags >> S::FB_used) & 1; }
+ bool isTLS() const { return (Flags >> S::FB_tls) & 1; }
+ bool canBeOmittedFromSymbolTable() const {
+ return (Flags >> S::FB_may_omit) & 1;
+ }
+ bool isGlobal() const { return (Flags >> S::FB_global) & 1; }
+ bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; }
+ bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; }
+ bool isExecutable() const { return (Flags >> S::FB_executable) & 1; }
+
+ uint64_t getCommonSize() const {
+ assert(isCommon());
+ return CommonSize;
+ }
+ uint32_t getCommonAlignment() const {
+ assert(isCommon());
+ return CommonAlign;
+ }
+
+ /// COFF-specific: for weak externals, returns the name of the symbol that is
+ /// used as a fallback if the weak external remains undefined.
+ StringRef getCOFFWeakExternalFallback() const {
+ assert(isWeak() && isIndirect());
+ return COFFWeakExternFallbackName;
+ }
+};
+
+/// This class can be used to read a Symtab and Strtab produced by
+/// irsymtab::build.
+class Reader {
+ StringRef Symtab, Strtab;
+
+ ArrayRef<storage::Module> Modules;
+ ArrayRef<storage::Comdat> Comdats;
+ ArrayRef<storage::Symbol> Symbols;
+ ArrayRef<storage::Uncommon> Uncommons;
+
+ StringRef str(storage::Str S) const { return S.get(Strtab); }
+ template <typename T> ArrayRef<T> range(storage::Range<T> R) const {
+ return R.get(Symtab);
+ }
+ const storage::Header &header() const {
+ return *reinterpret_cast<const storage::Header *>(Symtab.data());
+ }
+
+public:
+ class SymbolRef;
+
+ Reader() = default;
+ Reader(StringRef Symtab, StringRef Strtab) : Symtab(Symtab), Strtab(Strtab) {
+ Modules = range(header().Modules);
+ Comdats = range(header().Comdats);
+ Symbols = range(header().Symbols);
+ Uncommons = range(header().Uncommons);
+ }
+
+ typedef iterator_range<object::content_iterator<SymbolRef>> symbol_range;
+
+ /// Returns the symbol table for the entire bitcode file.
+ /// The symbols enumerated by this method are ephemeral, but they can be
+ /// copied into an irsymtab::Symbol object.
+ symbol_range symbols() const;
+
+ /// Returns a slice of the symbol table for the I'th module in the file.
+ /// The symbols enumerated by this method are ephemeral, but they can be
+ /// copied into an irsymtab::Symbol object.
+ symbol_range module_symbols(unsigned I) const;
+
+ StringRef getTargetTriple() const { return str(header().TargetTriple); }
+
+ /// Returns the source file path specified at compile time.
+ StringRef getSourceFileName() const { return str(header().SourceFileName); }
+
+ /// Returns a table with all the comdats used by this file.
+ std::vector<StringRef> getComdatTable() const {
+ std::vector<StringRef> ComdatTable;
+ ComdatTable.reserve(Comdats.size());
+ for (auto C : Comdats)
+ ComdatTable.push_back(str(C.Name));
+ return ComdatTable;
+ }
+
+ /// COFF-specific: returns linker options specified in the input file.
+ StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); }
+};
+
+/// Ephemeral symbols produced by Reader::symbols() and
+/// Reader::module_symbols().
+class Reader::SymbolRef : public Symbol {
+ const storage::Symbol *SymI, *SymE;
+ const Reader *R;
+
+public:
+ SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE,
+ const Reader *R)
+ : SymI(SymI), SymE(SymE), R(R) {
+ read();
+ }
+
+ void read() {
+ if (SymI == SymE)
+ return;
+
+ Name = R->str(SymI->Name);
+ IRName = R->str(SymI->IRName);
+ ComdatIndex = SymI->ComdatIndex;
+ Flags = SymI->Flags;
+
+ uint32_t UncI = SymI->UncommonIndex;
+ if (UncI != -1u) {
+ const storage::Uncommon &Unc = R->Uncommons[UncI];
+ CommonSize = Unc.CommonSize;
+ CommonAlign = Unc.CommonAlign;
+ COFFWeakExternFallbackName = R->str(Unc.COFFWeakExternFallbackName);
+ }
+ }
+ void moveNext() {
+ ++SymI;
+ read();
+ }
+
+ bool operator==(const SymbolRef &Other) const { return SymI == Other.SymI; }
+};
+
+inline Reader::symbol_range Reader::symbols() const {
+ return {SymbolRef(Symbols.begin(), Symbols.end(), this),
+ SymbolRef(Symbols.end(), Symbols.end(), this)};
+}
+
+inline Reader::symbol_range Reader::module_symbols(unsigned I) const {
+ const storage::Module &M = Modules[I];
+ const storage::Symbol *MBegin = Symbols.begin() + M.Begin,
+ *MEnd = Symbols.begin() + M.End;
+ return {SymbolRef(MBegin, MEnd, this), SymbolRef(MEnd, MEnd, this)};
+}
+
+}
+
+}
+
+#endif
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 8c33ec8fd603..1ee571cce738 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -100,18 +100,58 @@ private:
};
typedef content_iterator<ExportEntry> export_iterator;
+// Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry
+// can be checked and translated. Only the SegIndex/SegOffset pairs from
+// checked entries are to be used with the segmentName(), sectionName() and
+// address() methods below.
+class BindRebaseSegInfo {
+public:
+ BindRebaseSegInfo(const object::MachOObjectFile *Obj);
+
+ // Used to check a Mach-O Bind or Rebase entry for errors when iterating.
+ const char *checkSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
+ bool endInvalid);
+ const char *checkCountAndSkip(uint32_t Count, uint32_t Skip,
+ uint8_t PointerSize, int32_t SegIndex,
+ uint64_t SegOffset);
+ // Used with valid SegIndex/SegOffset values from checked entries.
+ StringRef segmentName(int32_t SegIndex);
+ StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
+ uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
+
+private:
+ struct SectionInfo {
+ uint64_t Address;
+ uint64_t Size;
+ StringRef SectionName;
+ StringRef SegmentName;
+ uint64_t OffsetInSegment;
+ uint64_t SegmentStartAddress;
+ int32_t SegmentIndex;
+ };
+ const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset);
+ SmallVector<SectionInfo, 32> Sections;
+ int32_t MaxSegIndex;
+};
+
/// MachORebaseEntry encapsulates the current state in the decompression of
/// rebasing opcodes. This allows you to iterate through the compressed table of
/// rebasing using:
-/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
+/// Error Err;
+/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
/// }
+/// if (Err) { report error ...
class MachORebaseEntry {
public:
- MachORebaseEntry(ArrayRef<uint8_t> opcodes, bool is64Bit);
+ MachORebaseEntry(Error *Err, const MachOObjectFile *O,
+ ArrayRef<uint8_t> opcodes, bool is64Bit);
- uint32_t segmentIndex() const;
+ int32_t segmentIndex() const;
uint64_t segmentOffset() const;
StringRef typeName() const;
+ StringRef segmentName() const;
+ StringRef sectionName() const;
+ uint64_t address() const;
bool operator==(const MachORebaseEntry &) const;
@@ -121,17 +161,18 @@ private:
friend class MachOObjectFile;
void moveToFirst();
void moveToEnd();
- uint64_t readULEB128();
+ uint64_t readULEB128(const char **error);
+ Error *E;
+ const MachOObjectFile *O;
ArrayRef<uint8_t> Opcodes;
const uint8_t *Ptr;
uint64_t SegmentOffset;
- uint32_t SegmentIndex;
+ int32_t SegmentIndex;
uint64_t RemainingLoopCount;
uint64_t AdvanceAmount;
uint8_t RebaseType;
uint8_t PointerSize;
- bool Malformed;
bool Done;
};
typedef content_iterator<MachORebaseEntry> rebase_iterator;
@@ -139,15 +180,18 @@ typedef content_iterator<MachORebaseEntry> rebase_iterator;
/// MachOBindEntry encapsulates the current state in the decompression of
/// binding opcodes. This allows you to iterate through the compressed table of
/// bindings using:
-/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
+/// Error Err;
+/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
/// }
+/// if (Err) { report error ...
class MachOBindEntry {
public:
enum class Kind { Regular, Lazy, Weak };
- MachOBindEntry(ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
+ MachOBindEntry(Error *Err, const MachOObjectFile *O,
+ ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
- uint32_t segmentIndex() const;
+ int32_t segmentIndex() const;
uint64_t segmentOffset() const;
StringRef typeName() const;
StringRef symbolName() const;
@@ -155,6 +199,10 @@ public:
int64_t addend() const;
int ordinal() const;
+ StringRef segmentName() const;
+ StringRef sectionName() const;
+ uint64_t address() const;
+
bool operator==(const MachOBindEntry &) const;
void moveNext();
@@ -163,14 +211,17 @@ private:
friend class MachOObjectFile;
void moveToFirst();
void moveToEnd();
- uint64_t readULEB128();
- int64_t readSLEB128();
+ uint64_t readULEB128(const char **error);
+ int64_t readSLEB128(const char **error);
+ Error *E;
+ const MachOObjectFile *O;
ArrayRef<uint8_t> Opcodes;
const uint8_t *Ptr;
uint64_t SegmentOffset;
- uint32_t SegmentIndex;
+ int32_t SegmentIndex;
StringRef SymbolName;
+ bool LibraryOrdinalSet;
int Ordinal;
uint32_t Flags;
int64_t Addend;
@@ -179,7 +230,6 @@ private:
uint8_t BindType;
uint8_t PointerSize;
Kind TableKind;
- bool Malformed;
bool Done;
};
typedef content_iterator<MachOBindEntry> bind_iterator;
@@ -245,6 +295,7 @@ public:
// MachO specific.
std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
+ uint32_t getLibraryCount() const;
section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const;
@@ -285,26 +336,79 @@ public:
static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie);
/// For use iterating over all rebase table entries.
- iterator_range<rebase_iterator> rebaseTable() const;
+ iterator_range<rebase_iterator> rebaseTable(Error &Err);
- /// For use examining rebase opcodes not in a MachOObjectFile.
- static iterator_range<rebase_iterator> rebaseTable(ArrayRef<uint8_t> Opcodes,
+ /// For use examining rebase opcodes in a MachOObjectFile.
+ static iterator_range<rebase_iterator> rebaseTable(Error &Err,
+ MachOObjectFile *O,
+ ArrayRef<uint8_t> Opcodes,
bool is64);
/// For use iterating over all bind table entries.
- iterator_range<bind_iterator> bindTable() const;
+ iterator_range<bind_iterator> bindTable(Error &Err);
/// For use iterating over all lazy bind table entries.
- iterator_range<bind_iterator> lazyBindTable() const;
+ iterator_range<bind_iterator> lazyBindTable(Error &Err);
- /// For use iterating over all lazy bind table entries.
- iterator_range<bind_iterator> weakBindTable() const;
+ /// For use iterating over all weak bind table entries.
+ iterator_range<bind_iterator> weakBindTable(Error &Err);
- /// For use examining bind opcodes not in a MachOObjectFile.
- static iterator_range<bind_iterator> bindTable(ArrayRef<uint8_t> Opcodes,
+ /// For use examining bind opcodes in a MachOObjectFile.
+ static iterator_range<bind_iterator> bindTable(Error &Err,
+ MachOObjectFile *O,
+ ArrayRef<uint8_t> Opcodes,
bool is64,
MachOBindEntry::Kind);
+ /// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
+ /// validate a MachOBindEntry.
+ const char *BindEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
+ bool endInvalid) const {
+ return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
+ endInvalid);
+ }
+ /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
+ /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode.
+ const char *BindEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
+ uint8_t PointerSize, int32_t SegIndex,
+ uint64_t SegOffset) const {
+ return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
+ SegIndex, SegOffset);
+ }
+
+ /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to
+ /// validate a MachORebaseEntry.
+ const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
+ bool endInvalid) const {
+ return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
+ endInvalid);
+ }
+ /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
+ /// the REBASE_OPCODE_DO_*_TIMES* opcodes.
+ const char *RebaseEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
+ uint8_t PointerSize, int32_t SegIndex,
+ uint64_t SegOffset) const {
+ return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
+ SegIndex, SegOffset);
+ }
+
+ /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
+ /// get the segment name.
+ StringRef BindRebaseSegmentName(int32_t SegIndex) const {
+ return BindRebaseSectionTable->segmentName(SegIndex);
+ }
+
+ /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
+ /// Rebase entry to get the section name.
+ StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const {
+ return BindRebaseSectionTable->sectionName(SegIndex, SegOffset);
+ }
+
+ /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
+ /// Rebase entry to get the address.
+ uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const {
+ return BindRebaseSectionTable->address(SegIndex, SegOffset);
+ }
// 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
@@ -351,6 +455,12 @@ public:
getLinkerOptionLoadCommand(const LoadCommandInfo &L) const;
MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo &L) const;
+ MachO::note_command
+ getNoteLoadCommand(const LoadCommandInfo &L) const;
+ MachO::build_version_command
+ getBuildVersionLoadCommand(const LoadCommandInfo &L) const;
+ MachO::build_tool_version
+ getBuildToolVersion(unsigned index) const;
MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo &L) const;
MachO::dyld_info_command
@@ -444,6 +554,46 @@ public:
return VersionOrSDK & 0xff;
}
+ static std::string getBuildPlatform(uint32_t platform) {
+ switch (platform) {
+ case MachO::PLATFORM_MACOS: return "macos";
+ case MachO::PLATFORM_IOS: return "ios";
+ case MachO::PLATFORM_TVOS: return "tvos";
+ case MachO::PLATFORM_WATCHOS: return "watchos";
+ case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
+ default:
+ std::string ret;
+ llvm::raw_string_ostream ss(ret);
+ ss << format_hex(platform, 8, true);
+ return ss.str();
+ }
+ }
+
+ static std::string getBuildTool(uint32_t tools) {
+ switch (tools) {
+ case MachO::TOOL_CLANG: return "clang";
+ case MachO::TOOL_SWIFT: return "swift";
+ case MachO::TOOL_LD: return "ld";
+ default:
+ std::string ret;
+ llvm::raw_string_ostream ss(ret);
+ ss << format_hex(tools, 8, true);
+ return ss.str();
+ }
+ }
+
+ static std::string getVersionString(uint32_t version) {
+ uint32_t major = (version >> 16) & 0xffff;
+ uint32_t minor = (version >> 8) & 0xff;
+ uint32_t update = version & 0xff;
+
+ SmallString<32> Version;
+ Version = utostr(major) + "." + utostr(minor);
+ if (update != 0)
+ Version += "." + utostr(update);
+ return Version.str();
+ }
+
private:
MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
@@ -462,7 +612,10 @@ private:
LibraryList Libraries;
LoadCommandList LoadCommands;
typedef SmallVector<StringRef, 1> LibraryShortName;
+ using BuildToolList = SmallVector<const char*, 1>;
+ BuildToolList BuildTools;
mutable LibraryShortName LibrariesShortNames;
+ std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable;
const char *SymtabLoadCmd;
const char *DysymtabLoadCmd;
const char *DataInCodeLoadCmd;
diff --git a/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/include/llvm/Object/ModuleSummaryIndexObjectFile.h
index 6205927039dc..713022264ea7 100644
--- a/include/llvm/Object/ModuleSummaryIndexObjectFile.h
+++ b/include/llvm/Object/ModuleSummaryIndexObjectFile.h
@@ -88,9 +88,12 @@ public:
}
/// Parse the module summary index out of an IR file and return the module
-/// summary index object if found, or nullptr if not.
+/// summary index object if found, or nullptr if not. If Identifier is
+/// non-empty, it is used as the module ID (module path) in the resulting
+/// index. This can be used when the index is being read from a file
+/// containing minimized bitcode just for the thin link.
Expected<std::unique_ptr<ModuleSummaryIndex>>
-getModuleSummaryIndexForFile(StringRef Path);
+getModuleSummaryIndexForFile(StringRef Path, StringRef Identifier = "");
}
#endif
diff --git a/include/llvm/Object/ModuleSymbolTable.h b/include/llvm/Object/ModuleSymbolTable.h
index 70775352d977..333301d5b456 100644
--- a/include/llvm/Object/ModuleSymbolTable.h
+++ b/include/llvm/Object/ModuleSymbolTable.h
@@ -26,6 +26,7 @@
namespace llvm {
class GlobalValue;
+class RecordStreamer;
class ModuleSymbolTable {
public:
@@ -52,7 +53,7 @@ public:
/// 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,
+ const Module &M,
function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol);
};
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 13d5845c3a71..b689dc2ac03a 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -24,6 +24,8 @@
#include <cstring>
namespace llvm {
+class ARMAttributeParser;
+
namespace object {
class ObjectFile;
@@ -265,6 +267,7 @@ public:
virtual StringRef getFileFormatName() const = 0;
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
virtual SubtargetFeatures getFeatures() const = 0;
+ virtual void setARMSubArch(Triple &TheTriple) const { }
/// Returns platform-specific object flags, if any.
virtual std::error_code getPlatformFlags(unsigned &Result) const {
@@ -272,6 +275,11 @@ public:
return object_error::invalid_file_type;
}
+ virtual std::error_code
+ getBuildAttributes(ARMAttributeParser &Attributes) const {
+ return std::error_code();
+ }
+
/// True if this is a relocatable object (.o/.obj).
virtual bool isRelocatableObject() const = 0;
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index 3510d293d73d..3a0a62d9283b 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -155,6 +155,8 @@ private:
switch (RelocType) {
case llvm::ELF::R_AMDGPU_ABS32:
return visitELF_AMDGPU_ABS32(R, Value);
+ case llvm::ELF::R_AMDGPU_ABS64:
+ return visitELF_AMDGPU_ABS64(R, Value);
default:
HasError = true;
return RelocToApply();
@@ -450,6 +452,11 @@ private:
return RelocToApply(Value + Addend, 4);
}
+ RelocToApply visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
+ int64_t Addend = getELFAddend(R);
+ return RelocToApply(Value + Addend, 8);
+ }
+
/// 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/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index af62e62c51d8..ef0f96f7834a 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -16,6 +16,7 @@
#include "llvm/Object/Binary.h"
#include "llvm/Support/Format.h"
+#include <cinttypes>
#include <utility>
namespace llvm {
@@ -33,7 +34,8 @@ union DataRefImpl {
template <typename OStream>
OStream& operator<<(OStream &OS, const DataRefImpl &D) {
- OS << "(" << format("0x%x8", D.p) << " (" << format("0x%x8", D.d.a) << ", " << format("0x%x8", D.d.b) << "))";
+ OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a)
+ << ", " << format("0x%08x", D.d.b) << "))";
return OS;
}
diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h
index 2ece6a6c3770..43ad62be68b6 100644
--- a/include/llvm/Object/Wasm.h
+++ b/include/llvm/Object/Wasm.h
@@ -17,24 +17,74 @@
#ifndef LLVM_OBJECT_WASM_H
#define LLVM_OBJECT_WASM_H
+#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Wasm.h"
+#include <cstddef>
+#include <cstdint>
+#include <vector>
namespace llvm {
namespace object {
+class WasmSymbol {
+public:
+ enum class SymbolType {
+ FUNCTION_IMPORT,
+ FUNCTION_EXPORT,
+ GLOBAL_IMPORT,
+ GLOBAL_EXPORT,
+ DEBUG_FUNCTION_NAME,
+ };
+
+ WasmSymbol(StringRef Name, SymbolType Type) : Name(Name), Type(Type) {}
+
+ StringRef Name;
+ SymbolType Type;
+};
+
+class WasmSection {
+public:
+ WasmSection() : Type(0), Offset(0) {}
+
+ uint32_t Type; // Section type (See below)
+ uint32_t Offset; // Offset with in the file
+ StringRef Name; // Section name (User-defined sections only)
+ ArrayRef<uint8_t> Content; // Section content
+ std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
+};
+
class WasmObjectFile : public ObjectFile {
public:
WasmObjectFile(MemoryBufferRef Object, Error &Err);
+
const wasm::WasmObjectHeader &getHeader() const;
- const wasm::WasmSection *getWasmSection(const SectionRef &Section) const;
+ const WasmSymbol &getWasmSymbol(DataRefImpl Symb) const;
+ const WasmSection &getWasmSection(const SectionRef &Section) const;
+ const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
+
static bool classof(const Binary *v) { return v->isWasm(); }
-protected:
- void moveSymbolNext(DataRefImpl &Symb) const override;
+ 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; }
+ const std::vector<wasm::WasmElemSegment>& elements() const {
+ return ElemSegments;
+ }
+ const std::vector<wasm::WasmDataSegment>& dataSegments() const {
+ return DataSegments;
+ }
+ const std::vector<wasm::WasmFunction>& functions() const { return Functions; }
+ const ArrayRef<uint8_t>& code() const { return CodeSection; }
+ uint32_t startFunction() const { return StartFunction; }
- std::error_code printSymbolName(raw_ostream &OS,
- DataRefImpl Symb) const override;
+ void moveSymbolNext(DataRefImpl &Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
@@ -67,7 +117,6 @@ protected:
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;
@@ -86,14 +135,53 @@ protected:
bool isRelocatableObject() const override;
private:
+ 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 parseUserSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
- size_t Length);
+ Error parseSection(WasmSection &Sec);
+ Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
+ const uint8_t *End);
+
+ // 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);
+
+ // Custom section types
+ Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
+ const uint8_t *End);
wasm::WasmObjectHeader Header;
- std::vector<wasm::WasmSection> Sections;
+ std::vector<WasmSection> Sections;
+ std::vector<wasm::WasmSignature> Signatures;
+ std::vector<uint32_t> FunctionTypes;
+ std::vector<wasm::WasmTable> Tables;
+ std::vector<wasm::WasmLimits> Memories;
+ std::vector<wasm::WasmGlobal> Globals;
+ std::vector<wasm::WasmImport> Imports;
+ std::vector<wasm::WasmExport> Exports;
+ std::vector<wasm::WasmElemSegment> ElemSegments;
+ std::vector<wasm::WasmDataSegment> DataSegments;
+ std::vector<WasmSymbol> Symbols;
+ std::vector<wasm::WasmFunction> Functions;
+ ArrayRef<uint8_t> CodeSection;
+ uint32_t StartFunction;
};
-}
-}
-#endif
+} // end namespace object
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_WASM_H