aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:46:15 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:46:15 +0000
commitdd58ef019b700900793a1eb48b52123db01b654e (patch)
treefcfbb4df56a744f4ddc6122c50521dd3f1c5e196 /include/llvm/Object
parent2fe5752e3a7c345cdb59e869278d36af33c13fa4 (diff)
Notes
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h67
-rw-r--r--include/llvm/Object/ArchiveWriter.h13
-rw-r--r--include/llvm/Object/Binary.h10
-rw-r--r--include/llvm/Object/COFF.h4
-rw-r--r--include/llvm/Object/COFFImportFile.h74
-rw-r--r--include/llvm/Object/ELF.h871
-rw-r--r--include/llvm/Object/ELFObjectFile.h171
-rw-r--r--include/llvm/Object/ELFTypes.h37
-rw-r--r--include/llvm/Object/Error.h1
-rw-r--r--include/llvm/Object/FunctionIndexObjectFile.h110
-rw-r--r--include/llvm/Object/MachO.h26
-rw-r--r--include/llvm/Object/ObjectFile.h13
-rw-r--r--include/llvm/Object/SymbolicFile.h8
13 files changed, 584 insertions, 821 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 597f0d48c118..8dd042a2533f 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -37,7 +37,7 @@ struct ArchiveMemberHeader {
llvm::StringRef getName() const;
/// Members are not larger than 4GB.
- uint32_t getSize() const;
+ ErrorOr<uint32_t> getSize() const;
sys::fs::perms getAccessMode() const;
sys::TimeValue getLastModified() const;
@@ -52,6 +52,7 @@ class Archive : public Binary {
virtual void anchor();
public:
class Child {
+ friend Archive;
const Archive *Parent;
/// \brief Includes header but not padding byte.
StringRef Data;
@@ -62,19 +63,19 @@ public:
return reinterpret_cast<const ArchiveMemberHeader *>(Data.data());
}
+ bool isThinMember() const;
+
public:
- Child(const Archive *Parent, const char *Start);
+ Child(const Archive *Parent, const char *Start, std::error_code *EC);
+ Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile);
bool operator ==(const Child &other) const {
assert(Parent == other.Parent);
return Data.begin() == other.Data.begin();
}
- bool operator <(const Child &other) const {
- return Data.begin() < other.Data.begin();
- }
-
- Child getNext() const;
+ const Archive *getParent() const { return Parent; }
+ ErrorOr<Child> getNext() const;
ErrorOr<StringRef> getName() const;
StringRef getRawName() const { return getHeader()->getName(); }
@@ -90,9 +91,9 @@ public:
return getHeader()->getAccessMode();
}
/// \return the size of the archive member without the header or padding.
- uint64_t getSize() const;
+ ErrorOr<uint64_t> getSize() const;
/// \return the size in the archive header for this member.
- uint64_t getRawSize() const;
+ ErrorOr<uint64_t> getRawSize() const;
ErrorOr<StringRef> getBuffer() const;
uint64_t getChildOffset() const;
@@ -104,28 +105,32 @@ public:
};
class child_iterator {
- Child child;
+ ErrorOr<Child> child;
public:
- child_iterator() : child(Child(nullptr, nullptr)) {}
+ child_iterator() : child(Child(nullptr, nullptr, nullptr)) {}
child_iterator(const Child &c) : child(c) {}
- const Child *operator->() const { return &child; }
- const Child &operator*() const { return child; }
+ child_iterator(std::error_code EC) : child(EC) {}
+ const ErrorOr<Child> *operator->() const { return &child; }
+ const ErrorOr<Child> &operator*() const { return child; }
bool operator==(const child_iterator &other) const {
- return child == other.child;
+ // We ignore error states so that comparisions with end() work, which
+ // allows range loops.
+ if (child.getError() || other.child.getError())
+ return false;
+ return *child == *other.child;
}
bool operator!=(const child_iterator &other) const {
return !(*this == other);
}
- bool operator<(const child_iterator &other) const {
- return child < other.child;
- }
-
+ // Code in loops with child_iterators must check for errors on each loop
+ // iteration. And if there is an error break out of the loop.
child_iterator &operator++() { // Preincrement
- child = child.getNext();
+ assert(child && "Can't increment iterator with error");
+ child = child->getNext();
return *this;
}
};
@@ -145,7 +150,7 @@ public:
, SymbolIndex(symi)
, StringIndex(stri) {}
StringRef getName() const;
- ErrorOr<child_iterator> getMember() const;
+ ErrorOr<Child> getMember() const;
Symbol getNext() const;
};
@@ -186,14 +191,13 @@ public:
child_iterator child_begin(bool SkipInternal = true) const;
child_iterator child_end() const;
iterator_range<child_iterator> children(bool SkipInternal = true) const {
- return iterator_range<child_iterator>(child_begin(SkipInternal),
- child_end());
+ return make_range(child_begin(SkipInternal), child_end());
}
symbol_iterator symbol_begin() const;
symbol_iterator symbol_end() const;
iterator_range<symbol_iterator> symbols() const {
- return iterator_range<symbol_iterator>(symbol_begin(), symbol_end());
+ return make_range(symbol_begin(), symbol_end());
}
// Cast methods.
@@ -205,18 +209,17 @@ public:
child_iterator findSym(StringRef name) const;
bool hasSymbolTable() const;
- child_iterator getSymbolTableChild() const { return SymbolTable; }
- StringRef getSymbolTable() const {
- // We know that the symbol table is not an external file,
- // so we just assert there is no error.
- return *SymbolTable->getBuffer();
- }
+ StringRef getSymbolTable() const { return SymbolTable; }
uint32_t getNumberOfSymbols() const;
private:
- child_iterator SymbolTable;
- child_iterator StringTable;
- child_iterator FirstRegular;
+ StringRef SymbolTable;
+ StringRef StringTable;
+
+ StringRef FirstRegularData;
+ uint16_t FirstRegularStartOfFile = -1;
+ void setFirstRegular(const Child &C);
+
unsigned Format : 2;
unsigned IsThin : 1;
mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h
index 3648d0c77fb5..b5d2ba358080 100644
--- a/include/llvm/Object/ArchiveWriter.h
+++ b/include/llvm/Object/ArchiveWriter.h
@@ -24,17 +24,15 @@ class NewArchiveIterator {
bool IsNewMember;
StringRef Name;
- object::Archive::child_iterator OldI;
-
- StringRef NewFilename;
+ object::Archive::Child OldMember;
public:
- NewArchiveIterator(object::Archive::child_iterator I, StringRef Name);
- NewArchiveIterator(StringRef I, StringRef Name);
+ NewArchiveIterator(const object::Archive::Child &OldMember, StringRef Name);
+ NewArchiveIterator(StringRef FileName);
bool isNewMember() const;
StringRef getName() const;
- object::Archive::child_iterator getOld() const;
+ const object::Archive::Child &getOld() const;
StringRef getNew() const;
llvm::ErrorOr<int> getFD(sys::fs::file_status &NewStatus) const;
@@ -43,7 +41,8 @@ public:
std::pair<StringRef, std::error_code>
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
- bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic);
+ bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic,
+ bool Thin);
}
#endif
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index a3d6d0d4d428..a0d1127781f6 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -41,7 +41,9 @@ protected:
enum {
ID_Archive,
ID_MachOUniversalBinary,
- ID_IR, // LLVM IR
+ ID_COFFImportFile,
+ ID_IR, // LLVM IR
+ ID_FunctionIndex, // Function summary index
// Object and children.
ID_StartObjects,
@@ -113,10 +115,16 @@ public:
return TypeID == ID_COFF;
}
+ bool isCOFFImportFile() const {
+ return TypeID == ID_COFFImportFile;
+ }
+
bool isIR() const {
return TypeID == ID_IR;
}
+ bool isFunctionIndex() const { return TypeID == ID_FunctionIndex; }
+
bool isLittleEndian() const {
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index 025a9dbc6bc0..1b0e2e36bd5e 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -653,8 +653,7 @@ protected:
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
- std::error_code getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const override;
+ ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
@@ -774,6 +773,7 @@ public:
std::error_code getSectionContents(const coff_section *Sec,
ArrayRef<uint8_t> &Res) const;
+ uint64_t getImageBase() const;
std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h
new file mode 100644
index 000000000000..b04a44ea60d2
--- /dev/null
+++ b/include/llvm/Object/COFFImportFile.h
@@ -0,0 +1,74 @@
+//===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// COFF short import file is a special kind of file which contains
+// only symbol names for DLL-exported symbols. This class implements
+// SymbolicFile interface for the file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_COFF_IMPORT_FILE_H
+#define LLVM_OBJECT_COFF_IMPORT_FILE_H
+
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/IRObjectFile.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace object {
+
+class COFFImportFile : public SymbolicFile {
+public:
+ COFFImportFile(MemoryBufferRef Source)
+ : SymbolicFile(ID_COFFImportFile, Source) {}
+
+ static inline bool classof(Binary const *V) { return V->isCOFFImportFile(); }
+
+ void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; }
+
+ std::error_code printSymbolName(raw_ostream &OS,
+ DataRefImpl Symb) const override {
+ if (Symb.p == 0)
+ OS << "__imp_";
+ OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header));
+ return std::error_code();
+ }
+
+ uint32_t getSymbolFlags(DataRefImpl Symb) const override {
+ return SymbolRef::SF_Global;
+ }
+
+ basic_symbol_iterator symbol_begin_impl() const override {
+ return BasicSymbolRef(DataRefImpl(), this);
+ }
+
+ basic_symbol_iterator symbol_end_impl() const override {
+ DataRefImpl Symb;
+ Symb.p = isCode() ? 2 : 1;
+ return BasicSymbolRef(Symb, this);
+ }
+
+ const coff_import_header *getCOFFImportHeader() const {
+ return reinterpret_cast<const object::coff_import_header *>(
+ Data.getBufferStart());
+ }
+
+private:
+ bool isCode() const {
+ return getCOFFImportHeader()->getType() == COFF::IMPORT_CODE;
+ }
+};
+
+} // namespace object
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index cc271851e6b0..b0eaa3f5ed4d 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -14,25 +14,9 @@
#ifndef LLVM_OBJECT_ELF_H
#define LLVM_OBJECT_ELF_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntervalMap.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Object/ELFTypes.h"
-#include "llvm/Object/Error.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <limits>
-#include <utility>
namespace llvm {
namespace object {
@@ -56,78 +40,6 @@ public:
typedef typename std::conditional<ELFT::Is64Bits,
uint64_t, uint32_t>::type uintX_t;
- /// \brief Iterate over constant sized entities.
- template <class EntT>
- class ELFEntityIterator {
- public:
- typedef ptrdiff_t difference_type;
- typedef EntT value_type;
- typedef std::forward_iterator_tag iterator_category;
- typedef value_type &reference;
- typedef value_type *pointer;
-
- /// \brief Default construct iterator.
- ELFEntityIterator() : EntitySize(0), Current(nullptr) {}
- ELFEntityIterator(uintX_t EntSize, const char *Start)
- : EntitySize(EntSize), Current(Start) {}
-
- reference operator *() {
- assert(Current && "Attempted to dereference an invalid iterator!");
- return *reinterpret_cast<pointer>(Current);
- }
-
- pointer operator ->() {
- assert(Current && "Attempted to dereference an invalid iterator!");
- return reinterpret_cast<pointer>(Current);
- }
-
- bool operator ==(const ELFEntityIterator &Other) {
- return Current == Other.Current;
- }
-
- bool operator !=(const ELFEntityIterator &Other) {
- return !(*this == Other);
- }
-
- ELFEntityIterator &operator ++() {
- assert(Current && "Attempted to increment an invalid iterator!");
- Current += EntitySize;
- return *this;
- }
-
- ELFEntityIterator &operator+(difference_type n) {
- assert(Current && "Attempted to increment an invalid iterator!");
- Current += (n * EntitySize);
- return *this;
- }
-
- ELFEntityIterator &operator-(difference_type n) {
- assert(Current && "Attempted to subtract an invalid iterator!");
- Current -= (n * EntitySize);
- return *this;
- }
-
- ELFEntityIterator operator ++(int) {
- ELFEntityIterator Tmp = *this;
- ++*this;
- return Tmp;
- }
-
- difference_type operator -(const ELFEntityIterator &Other) const {
- assert(EntitySize == Other.EntitySize &&
- "Subtracting iterators of different EntitySize!");
- return (Current - Other.Current) / EntitySize;
- }
-
- const char *get() const { return Current; }
-
- uintX_t getEntSize() const { return EntitySize; }
-
- private:
- uintX_t EntitySize;
- const char *Current;
- };
-
typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
typedef Elf_Sym_Impl<ELFT> Elf_Sym;
@@ -141,98 +53,22 @@ public:
typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux;
typedef Elf_Versym_Impl<ELFT> Elf_Versym;
typedef Elf_Hash_Impl<ELFT> Elf_Hash;
- typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter;
- typedef iterator_range<Elf_Dyn_Iter> Elf_Dyn_Range;
- typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter;
- typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter;
+ typedef Elf_GnuHash_Impl<ELFT> Elf_GnuHash;
+ typedef iterator_range<const Elf_Dyn *> Elf_Dyn_Range;
typedef iterator_range<const Elf_Shdr *> Elf_Shdr_Range;
-
- /// \brief Archive files are 2 byte aligned, so we need this for
- /// PointerIntPair to work.
- template <typename T>
- class ArchivePointerTypeTraits {
- public:
- static inline const void *getAsVoidPointer(T *P) { return P; }
- static inline T *getFromVoidPointer(const void *P) {
- return static_cast<T *>(P);
- }
- enum { NumLowBitsAvailable = 1 };
- };
-
typedef iterator_range<const Elf_Sym *> Elf_Sym_Range;
-private:
- typedef SmallVector<const Elf_Shdr *, 2> Sections_t;
- typedef DenseMap<unsigned, unsigned> IndexMap_t;
-
- StringRef Buf;
-
const uint8_t *base() const {
return reinterpret_cast<const uint8_t *>(Buf.data());
}
+private:
+
+ StringRef Buf;
+
const Elf_Ehdr *Header;
const Elf_Shdr *SectionHeaderTable = nullptr;
StringRef DotShstrtab; // Section header string table.
- StringRef DotStrtab; // Symbol header string table.
- const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section.
- const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
- const Elf_Hash *HashTable = nullptr;
-
- const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr;
- DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable;
-
- const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version
- const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r
- const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d
-
- /// \brief Represents a region described by entries in the .dynamic table.
- struct DynRegionInfo {
- DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
- /// \brief Address in current address space.
- const void *Addr;
- /// \brief Size in bytes of the region.
- uintX_t Size;
- /// \brief Size of each entity in the region.
- uintX_t EntSize;
- };
-
- DynRegionInfo DynamicRegion;
- DynRegionInfo DynHashRegion;
- DynRegionInfo DynStrRegion;
- DynRegionInfo DynRelaRegion;
-
- // Pointer to SONAME entry in dynamic string table
- // This is set the first time getLoadName is called.
- mutable const char *dt_soname = nullptr;
-
- // Records for each version index the corresponding Verdef or Vernaux entry.
- // This is filled the first time LoadVersionMap() is called.
- class VersionMapEntry : public PointerIntPair<const void*, 1> {
- public:
- // If the integer is 0, this is an Elf_Verdef*.
- // If the integer is 1, this is an Elf_Vernaux*.
- VersionMapEntry() : PointerIntPair<const void*, 1>(nullptr, 0) { }
- VersionMapEntry(const Elf_Verdef *verdef)
- : PointerIntPair<const void*, 1>(verdef, 0) { }
- VersionMapEntry(const Elf_Vernaux *vernaux)
- : PointerIntPair<const void*, 1>(vernaux, 1) { }
- bool isNull() const { return getPointer() == nullptr; }
- bool isVerdef() const { return !isNull() && getInt() == 0; }
- bool isVernaux() const { return !isNull() && getInt() == 1; }
- const Elf_Verdef *getVerdef() const {
- return isVerdef() ? (const Elf_Verdef*)getPointer() : nullptr;
- }
- const Elf_Vernaux *getVernaux() const {
- return isVernaux() ? (const Elf_Vernaux*)getPointer() : nullptr;
- }
- };
- mutable SmallVector<VersionMapEntry, 16> VersionMap;
- void LoadVersionDefs(const Elf_Shdr *sec) const;
- void LoadVersionNeeds(const Elf_Shdr *ec) const;
- void LoadVersionMap() const;
-
- void scanDynamicTable();
public:
template<typename T>
@@ -240,25 +76,20 @@ public:
template <typename T>
const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const;
- const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; }
- const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
- const Elf_Hash *getHashTable() const { return HashTable; }
-
ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const;
- const char *getDynamicString(uintX_t Offset) const;
- ErrorOr<StringRef> getSymbolVersion(const Elf_Shdr *section,
- const Elf_Sym *Symb,
- bool &IsDefault) const;
+ ErrorOr<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const;
+
+ ErrorOr<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const;
+
void VerifyStrTab(const Elf_Shdr *sh) const;
StringRef getRelocationTypeName(uint32_t Type) const;
void getRelocationTypeName(uint32_t Type,
SmallVectorImpl<char> &Result) const;
- /// \brief Get the symbol table section and symbol for a given relocation.
- template <class RelT>
- std::pair<const Elf_Shdr *, const Elf_Sym *>
- getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const;
+ /// \brief Get the symbol for a given relocation.
+ const Elf_Sym *getRelocationSymbol(const Elf_Rel *Rel,
+ const Elf_Shdr *SymTab) const;
ELFFile(StringRef Object, std::error_code &EC);
@@ -273,111 +104,116 @@ public:
Header->getDataEncoding() == ELF::ELFDATA2LSB;
}
+ ErrorOr<const Elf_Dyn *> dynamic_table_begin(const Elf_Phdr *Phdr) const;
+ ErrorOr<const Elf_Dyn *> dynamic_table_end(const Elf_Phdr *Phdr) const;
+ ErrorOr<Elf_Dyn_Range> dynamic_table(const Elf_Phdr *Phdr) const {
+ ErrorOr<const Elf_Dyn *> Begin = dynamic_table_begin(Phdr);
+ if (std::error_code EC = Begin.getError())
+ return EC;
+ ErrorOr<const Elf_Dyn *> End = dynamic_table_end(Phdr);
+ if (std::error_code EC = End.getError())
+ return EC;
+ return make_range(*Begin, *End);
+ }
+
const Elf_Shdr *section_begin() const;
const Elf_Shdr *section_end() const;
Elf_Shdr_Range sections() const {
return make_range(section_begin(), section_end());
}
- const Elf_Sym *symbol_begin() const;
- const Elf_Sym *symbol_end() const;
- Elf_Sym_Range symbols() const {
- return make_range(symbol_begin(), symbol_end());
- }
-
- Elf_Dyn_Iter dynamic_table_begin() const;
- /// \param NULLEnd use one past the first DT_NULL entry as the end instead of
- /// the section size.
- Elf_Dyn_Iter dynamic_table_end(bool NULLEnd = false) const;
- Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const {
- return make_range(dynamic_table_begin(), dynamic_table_end(NULLEnd));
- }
-
- const Elf_Sym *dynamic_symbol_begin() const {
- if (!DotDynSymSec)
+ const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const {
+ if (!Sec)
return nullptr;
- if (DotDynSymSec->sh_entsize != sizeof(Elf_Sym))
+ if (Sec->sh_entsize != sizeof(Elf_Sym))
report_fatal_error("Invalid symbol size");
- return reinterpret_cast<const Elf_Sym *>(base() + DotDynSymSec->sh_offset);
+ return reinterpret_cast<const Elf_Sym *>(base() + Sec->sh_offset);
}
-
- const Elf_Sym *dynamic_symbol_end() const {
- if (!DotDynSymSec)
+ const Elf_Sym *symbol_end(const Elf_Shdr *Sec) const {
+ if (!Sec)
return nullptr;
- return reinterpret_cast<const Elf_Sym *>(base() + DotDynSymSec->sh_offset +
- DotDynSymSec->sh_size);
+ uint64_t Size = Sec->sh_size;
+ if (Size % sizeof(Elf_Sym))
+ report_fatal_error("Invalid symbol table size");
+ return symbol_begin(Sec) + Size / sizeof(Elf_Sym);
}
-
- Elf_Sym_Range dynamic_symbols() const {
- return make_range(dynamic_symbol_begin(), dynamic_symbol_end());
+ Elf_Sym_Range symbols(const Elf_Shdr *Sec) const {
+ return make_range(symbol_begin(Sec), symbol_end(Sec));
}
- Elf_Rela_Iter dyn_rela_begin() const {
- if (DynRelaRegion.Addr)
- return Elf_Rela_Iter(DynRelaRegion.EntSize,
- (const char *)DynRelaRegion.Addr);
- return Elf_Rela_Iter(0, nullptr);
+ typedef iterator_range<const Elf_Rela *> Elf_Rela_Range;
+
+ const Elf_Rela *rela_begin(const Elf_Shdr *sec) const {
+ if (sec->sh_entsize != sizeof(Elf_Rela))
+ report_fatal_error("Invalid relocation entry size");
+ return reinterpret_cast<const Elf_Rela *>(base() + sec->sh_offset);
}
- Elf_Rela_Iter dyn_rela_end() const {
- if (DynRelaRegion.Addr)
- return Elf_Rela_Iter(
- DynRelaRegion.EntSize,
- (const char *)DynRelaRegion.Addr + DynRelaRegion.Size);
- return Elf_Rela_Iter(0, nullptr);
+ const Elf_Rela *rela_end(const Elf_Shdr *sec) const {
+ uint64_t Size = sec->sh_size;
+ if (Size % sizeof(Elf_Rela))
+ report_fatal_error("Invalid relocation table size");
+ return rela_begin(sec) + Size / sizeof(Elf_Rela);
}
- Elf_Rela_Iter rela_begin(const Elf_Shdr *sec) const {
- return Elf_Rela_Iter(sec->sh_entsize,
- (const char *)(base() + sec->sh_offset));
+ Elf_Rela_Range relas(const Elf_Shdr *Sec) const {
+ return make_range(rela_begin(Sec), rela_end(Sec));
}
- Elf_Rela_Iter rela_end(const Elf_Shdr *sec) const {
- return Elf_Rela_Iter(
- sec->sh_entsize,
- (const char *)(base() + sec->sh_offset + sec->sh_size));
+ const Elf_Rel *rel_begin(const Elf_Shdr *sec) const {
+ if (sec->sh_entsize != sizeof(Elf_Rel))
+ report_fatal_error("Invalid relocation entry size");
+ return reinterpret_cast<const Elf_Rel *>(base() + sec->sh_offset);
}
- Elf_Rel_Iter rel_begin(const Elf_Shdr *sec) const {
- return Elf_Rel_Iter(sec->sh_entsize,
- (const char *)(base() + sec->sh_offset));
+ const Elf_Rel *rel_end(const Elf_Shdr *sec) const {
+ uint64_t Size = sec->sh_size;
+ if (Size % sizeof(Elf_Rel))
+ report_fatal_error("Invalid relocation table size");
+ return rel_begin(sec) + Size / sizeof(Elf_Rel);
}
- Elf_Rel_Iter rel_end(const Elf_Shdr *sec) const {
- return Elf_Rel_Iter(sec->sh_entsize,
- (const char *)(base() + sec->sh_offset + sec->sh_size));
+ typedef iterator_range<const Elf_Rel *> Elf_Rel_Range;
+ Elf_Rel_Range rels(const Elf_Shdr *Sec) const {
+ return make_range(rel_begin(Sec), rel_end(Sec));
}
/// \brief Iterate over program header table.
- typedef ELFEntityIterator<const Elf_Phdr> Elf_Phdr_Iter;
+ const Elf_Phdr *program_header_begin() const {
+ if (Header->e_phnum && Header->e_phentsize != sizeof(Elf_Phdr))
+ report_fatal_error("Invalid program header size");
+ return reinterpret_cast<const Elf_Phdr *>(base() + Header->e_phoff);
+ }
- Elf_Phdr_Iter program_header_begin() const {
- return Elf_Phdr_Iter(Header->e_phentsize,
- (const char*)base() + Header->e_phoff);
+ const Elf_Phdr *program_header_end() const {
+ return program_header_begin() + Header->e_phnum;
}
- Elf_Phdr_Iter program_header_end() const {
- return Elf_Phdr_Iter(Header->e_phentsize,
- (const char*)base() +
- Header->e_phoff +
- (Header->e_phnum * Header->e_phentsize));
+ typedef iterator_range<const Elf_Phdr *> Elf_Phdr_Range;
+
+ const Elf_Phdr_Range program_headers() const {
+ return make_range(program_header_begin(), program_header_end());
}
uint64_t getNumSections() const;
uintX_t getStringTableIndex() const;
- ELF::Elf64_Word getExtendedSymbolTableIndex(const Elf_Sym *symb) const;
+ uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
+ const Elf_Shdr *SymTab,
+ ArrayRef<Elf_Word> ShndxTable) const;
const Elf_Ehdr *getHeader() const { return Header; }
- ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *symb) const;
+ ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
+ const Elf_Shdr *SymTab,
+ ArrayRef<Elf_Word> ShndxTable) const;
ErrorOr<const Elf_Shdr *> getSection(uint32_t Index) const;
- const Elf_Sym *getSymbol(uint32_t index) const;
- ErrorOr<StringRef> getStaticSymbolName(const Elf_Sym *Symb) const;
- ErrorOr<StringRef> getDynamicSymbolName(const Elf_Sym *Symb) const;
- ErrorOr<StringRef> getSymbolName(const Elf_Sym *Symb, bool IsDynamic) const;
+ const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const {
+ return &*(symbol_begin(Sec) + Index);
+ }
ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const;
+ template <typename T>
+ ErrorOr<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const;
ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const;
- StringRef getLoadName() const;
};
typedef ELFFile<ELFType<support::little, false>> ELF32LEFile;
@@ -385,118 +221,50 @@ typedef ELFFile<ELFType<support::little, true>> ELF64LEFile;
typedef ELFFile<ELFType<support::big, false>> ELF32BEFile;
typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
-// Iterate through the version definitions, and place each Elf_Verdef
-// in the VersionMap according to its index.
-template <class ELFT>
-void ELFFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const {
- unsigned vd_size = sec->sh_size; // Size of section in bytes
- unsigned vd_count = sec->sh_info; // Number of Verdef entries
- const char *sec_start = (const char*)base() + sec->sh_offset;
- const char *sec_end = sec_start + vd_size;
- // The first Verdef entry is at the start of the section.
- const char *p = sec_start;
- for (unsigned i = 0; i < vd_count; i++) {
- if (p + sizeof(Elf_Verdef) > sec_end)
- report_fatal_error("Section ended unexpectedly while scanning "
- "version definitions.");
- const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p);
- if (vd->vd_version != ELF::VER_DEF_CURRENT)
- report_fatal_error("Unexpected verdef version");
- size_t index = vd->vd_ndx & ELF::VERSYM_VERSION;
- if (index >= VersionMap.size())
- VersionMap.resize(index + 1);
- VersionMap[index] = VersionMapEntry(vd);
- p += vd->vd_next;
- }
-}
-
-// Iterate through the versions needed section, and place each Elf_Vernaux
-// in the VersionMap according to its index.
template <class ELFT>
-void ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const {
- unsigned vn_size = sec->sh_size; // Size of section in bytes
- unsigned vn_count = sec->sh_info; // Number of Verneed entries
- const char *sec_start = (const char *)base() + sec->sh_offset;
- const char *sec_end = sec_start + vn_size;
- // The first Verneed entry is at the start of the section.
- const char *p = sec_start;
- for (unsigned i = 0; i < vn_count; i++) {
- if (p + sizeof(Elf_Verneed) > sec_end)
- report_fatal_error("Section ended unexpectedly while scanning "
- "version needed records.");
- const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p);
- if (vn->vn_version != ELF::VER_NEED_CURRENT)
- report_fatal_error("Unexpected verneed version");
- // Iterate through the Vernaux entries
- const char *paux = p + vn->vn_aux;
- for (unsigned j = 0; j < vn->vn_cnt; j++) {
- if (paux + sizeof(Elf_Vernaux) > sec_end)
- report_fatal_error("Section ended unexpected while scanning auxiliary "
- "version needed records.");
- const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux);
- size_t index = vna->vna_other & ELF::VERSYM_VERSION;
- if (index >= VersionMap.size())
- VersionMap.resize(index + 1);
- VersionMap[index] = VersionMapEntry(vna);
- paux += vna->vna_next;
- }
- p += vn->vn_next;
- }
-}
-
-template <class ELFT>
-void ELFFile<ELFT>::LoadVersionMap() const {
- // If there is no dynamic symtab or version table, there is nothing to do.
- if (!DotDynSymSec || !dot_gnu_version_sec)
- return;
-
- // Has the VersionMap already been loaded?
- if (VersionMap.size() > 0)
- return;
-
- // The first two version indexes are reserved.
- // Index 0 is LOCAL, index 1 is GLOBAL.
- VersionMap.push_back(VersionMapEntry());
- VersionMap.push_back(VersionMapEntry());
-
- if (dot_gnu_version_d_sec)
- LoadVersionDefs(dot_gnu_version_d_sec);
+uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
+ const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+ ArrayRef<Elf_Word> ShndxTable) const {
+ assert(Sym->st_shndx == ELF::SHN_XINDEX);
+ unsigned Index = Sym - symbol_begin(SymTab);
- if (dot_gnu_version_r_sec)
- LoadVersionNeeds(dot_gnu_version_r_sec);
-}
-
-template <class ELFT>
-ELF::Elf64_Word
-ELFFile<ELFT>::getExtendedSymbolTableIndex(const Elf_Sym *symb) const {
- assert(symb->st_shndx == ELF::SHN_XINDEX);
- return ExtendedSymbolTable.lookup(symb);
+ // The size of the table was checked in getSHNDXTable.
+ return ShndxTable[Index];
}
template <class ELFT>
ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *>
-ELFFile<ELFT>::getSection(const Elf_Sym *symb) const {
- uint32_t Index = symb->st_shndx;
+ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+ ArrayRef<Elf_Word> ShndxTable) const {
+ uint32_t Index = Sym->st_shndx;
if (Index == ELF::SHN_XINDEX)
- return getSection(ExtendedSymbolTable.lookup(symb));
+ return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable));
+
if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
return nullptr;
- return getSection(symb->st_shndx);
+ return getSection(Sym->st_shndx);
}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Sym *
-ELFFile<ELFT>::getSymbol(uint32_t Index) const {
- return &*(symbol_begin() + Index);
+template <typename T>
+ErrorOr<ArrayRef<T>>
+ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const {
+ uintX_t Offset = Sec->sh_offset;
+ uintX_t Size = Sec->sh_size;
+
+ if (Size % sizeof(T))
+ return object_error::parse_failed;
+ if (Offset + Size > Buf.size())
+ return object_error::parse_failed;
+
+ const T *Start = reinterpret_cast<const T *>(base() + Offset);
+ return makeArrayRef(Start, Size / sizeof(T));
}
template <class ELFT>
-ErrorOr<ArrayRef<uint8_t> >
+ErrorOr<ArrayRef<uint8_t>>
ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const {
- if (Sec->sh_offset + Sec->sh_size > Buf.size())
- return object_error::parse_failed;
- const uint8_t *Start = base() + Sec->sh_offset;
- return makeArrayRef(Start, Sec->sh_size);
+ return getSectionContentsAsArray<uint8_t>(Sec);
}
template <class ELFT>
@@ -536,18 +304,13 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
}
template <class ELFT>
-template <class RelT>
-std::pair<const typename ELFFile<ELFT>::Elf_Shdr *,
- const typename ELFFile<ELFT>::Elf_Sym *>
-ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const {
- if (!Sec->sh_link)
- return std::make_pair(nullptr, nullptr);
- ErrorOr<const Elf_Shdr *> SymTableOrErr = getSection(Sec->sh_link);
- if (std::error_code EC = SymTableOrErr.getError())
- report_fatal_error(EC.message());
- const Elf_Shdr *SymTable = *SymTableOrErr;
- return std::make_pair(
- SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL())));
+const typename ELFFile<ELFT>::Elf_Sym *
+ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
+ const Elf_Shdr *SymTab) const {
+ uint32_t Index = Rel->getSymbol(isMips64EL());
+ if (Index == 0)
+ return nullptr;
+ return getEntry<Elf_Sym>(SymTab, Index);
}
template <class ELFT>
@@ -584,10 +347,8 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
Header = reinterpret_cast<const Elf_Ehdr *>(base());
- if (Header->e_shoff == 0) {
- scanDynamicTable();
+ if (Header->e_shoff == 0)
return;
- }
const uint64_t SectionTableOffset = Header->e_shoff;
@@ -608,185 +369,25 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
return;
}
- // Scan sections for special sections.
-
- for (const Elf_Shdr &Sec : sections()) {
- switch (Sec.sh_type) {
- case ELF::SHT_HASH:
- if (HashTable) {
- EC = object_error::parse_failed;
- return;
- }
- HashTable = reinterpret_cast<const Elf_Hash *>(base() + Sec.sh_offset);
- break;
- case ELF::SHT_SYMTAB_SHNDX:
- if (SymbolTableSectionHeaderIndex) {
- // More than one .symtab_shndx!
- EC = object_error::parse_failed;
- return;
- }
- SymbolTableSectionHeaderIndex = &Sec;
- break;
- case ELF::SHT_SYMTAB: {
- if (dot_symtab_sec) {
- // More than one .symtab!
- EC = object_error::parse_failed;
- return;
- }
- dot_symtab_sec = &Sec;
- ErrorOr<const Elf_Shdr *> SectionOrErr = getSection(Sec.sh_link);
- if ((EC = SectionOrErr.getError()))
- return;
- ErrorOr<StringRef> SymtabOrErr = getStringTable(*SectionOrErr);
- if ((EC = SymtabOrErr.getError()))
- return;
- DotStrtab = *SymtabOrErr;
- } break;
- case ELF::SHT_DYNSYM: {
- if (DotDynSymSec) {
- // More than one .dynsym!
- EC = object_error::parse_failed;
- return;
- }
- DotDynSymSec = &Sec;
- ErrorOr<const Elf_Shdr *> SectionOrErr = getSection(Sec.sh_link);
- if ((EC = SectionOrErr.getError()))
- return;
- ErrorOr<StringRef> SymtabOrErr = getStringTable(*SectionOrErr);
- if ((EC = SymtabOrErr.getError()))
- return;
- DynStrRegion.Addr = SymtabOrErr->data();
- DynStrRegion.Size = SymtabOrErr->size();
- DynStrRegion.EntSize = 1;
- break;
- }
- case ELF::SHT_DYNAMIC:
- if (DynamicRegion.Addr) {
- // More than one .dynamic!
- EC = object_error::parse_failed;
- return;
- }
- DynamicRegion.Addr = base() + Sec.sh_offset;
- DynamicRegion.Size = Sec.sh_size;
- DynamicRegion.EntSize = Sec.sh_entsize;
- break;
- case ELF::SHT_GNU_versym:
- if (dot_gnu_version_sec != nullptr) {
- // More than one .gnu.version section!
- EC = object_error::parse_failed;
- return;
- }
- dot_gnu_version_sec = &Sec;
- break;
- case ELF::SHT_GNU_verdef:
- if (dot_gnu_version_d_sec != nullptr) {
- // More than one .gnu.version_d section!
- EC = object_error::parse_failed;
- return;
- }
- dot_gnu_version_d_sec = &Sec;
- break;
- case ELF::SHT_GNU_verneed:
- if (dot_gnu_version_r_sec != nullptr) {
- // More than one .gnu.version_r section!
- EC = object_error::parse_failed;
- return;
- }
- dot_gnu_version_r_sec = &Sec;
- break;
- }
- }
-
// Get string table sections.
- ErrorOr<const Elf_Shdr *> StrTabSecOrErr = getSection(getStringTableIndex());
- if ((EC = StrTabSecOrErr.getError()))
- return;
-
- ErrorOr<StringRef> SymtabOrErr = getStringTable(*StrTabSecOrErr);
- if ((EC = SymtabOrErr.getError()))
- return;
- DotShstrtab = *SymtabOrErr;
+ uintX_t StringTableIndex = getStringTableIndex();
+ if (StringTableIndex) {
+ ErrorOr<const Elf_Shdr *> StrTabSecOrErr = getSection(StringTableIndex);
+ if ((EC = StrTabSecOrErr.getError()))
+ return;
- // Build symbol name side-mapping if there is one.
- if (SymbolTableSectionHeaderIndex) {
- const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() +
- SymbolTableSectionHeaderIndex->sh_offset);
- for (const Elf_Sym &S : symbols()) {
- if (*ShndxTable != ELF::SHN_UNDEF)
- ExtendedSymbolTable[&S] = *ShndxTable;
- ++ShndxTable;
- }
+ ErrorOr<StringRef> StringTableOrErr = getStringTable(*StrTabSecOrErr);
+ if ((EC = StringTableOrErr.getError()))
+ return;
+ DotShstrtab = *StringTableOrErr;
}
- scanDynamicTable();
-
EC = std::error_code();
}
template <class ELFT>
-void ELFFile<ELFT>::scanDynamicTable() {
- // Build load-address to file-offset map.
- typedef IntervalMap<
- uintX_t, uintptr_t,
- IntervalMapImpl::NodeSizer<uintX_t, uintptr_t>::LeafSize,
- IntervalMapHalfOpenInfo<uintX_t>> LoadMapT;
- typename LoadMapT::Allocator Alloc;
- // Allocate the IntervalMap on the heap to work around MSVC bug where the
- // stack doesn't get realigned despite LoadMap having alignment 8 (PR24113).
- std::unique_ptr<LoadMapT> LoadMap(new LoadMapT(Alloc));
-
- for (Elf_Phdr_Iter PhdrI = program_header_begin(),
- PhdrE = program_header_end();
- PhdrI != PhdrE; ++PhdrI) {
- if (PhdrI->p_type == ELF::PT_DYNAMIC) {
- DynamicRegion.Addr = base() + PhdrI->p_offset;
- DynamicRegion.Size = PhdrI->p_filesz;
- DynamicRegion.EntSize = sizeof(Elf_Dyn);
- continue;
- }
- if (PhdrI->p_type != ELF::PT_LOAD)
- continue;
- if (PhdrI->p_filesz == 0)
- continue;
- LoadMap->insert(PhdrI->p_vaddr, PhdrI->p_vaddr + PhdrI->p_filesz,
- PhdrI->p_offset);
- }
-
- auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
- auto I = LoadMap->find(VAddr);
- if (I == LoadMap->end())
- return nullptr;
- return this->base() + I.value() + (VAddr - I.start());
- };
-
- for (Elf_Dyn_Iter DynI = dynamic_table_begin(), DynE = dynamic_table_end();
- DynI != DynE; ++DynI) {
- switch (DynI->d_tag) {
- case ELF::DT_HASH:
- if (HashTable)
- continue;
- HashTable =
- reinterpret_cast<const Elf_Hash *>(toMappedAddr(DynI->getPtr()));
- break;
- case ELF::DT_STRTAB:
- if (!DynStrRegion.Addr)
- DynStrRegion.Addr = toMappedAddr(DynI->getPtr());
- break;
- case ELF::DT_STRSZ:
- if (!DynStrRegion.Size)
- DynStrRegion.Size = DynI->getVal();
- break;
- case ELF::DT_RELA:
- if (!DynRelaRegion.Addr)
- DynRelaRegion.Addr = toMappedAddr(DynI->getPtr());
- break;
- case ELF::DT_RELASZ:
- DynRelaRegion.Size = DynI->getVal();
- break;
- case ELF::DT_RELAENT:
- DynRelaRegion.EntSize = DynI->getVal();
- }
- }
+static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
+ return VAddr < Phdr->p_vaddr;
}
template <class ELFT>
@@ -803,64 +404,31 @@ const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_end() const {
}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Sym *ELFFile<ELFT>::symbol_begin() const {
- if (!dot_symtab_sec)
+ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *>
+ELFFile<ELFT>::dynamic_table_begin(const Elf_Phdr *Phdr) const {
+ if (!Phdr)
return nullptr;
- if (dot_symtab_sec->sh_entsize != sizeof(Elf_Sym))
- report_fatal_error("Invalid symbol size");
- return reinterpret_cast<const Elf_Sym *>(base() + dot_symtab_sec->sh_offset);
+ assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header");
+ uintX_t Offset = Phdr->p_offset;
+ if (Offset > Buf.size())
+ return object_error::parse_failed;
+ return reinterpret_cast<const Elf_Dyn *>(base() + Offset);
}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Sym *ELFFile<ELFT>::symbol_end() const {
- if (!dot_symtab_sec)
+ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *>
+ELFFile<ELFT>::dynamic_table_end(const Elf_Phdr *Phdr) const {
+ if (!Phdr)
return nullptr;
- return reinterpret_cast<const Elf_Sym *>(base() + dot_symtab_sec->sh_offset +
- dot_symtab_sec->sh_size);
-}
-
-template <class ELFT>
-typename ELFFile<ELFT>::Elf_Dyn_Iter
-ELFFile<ELFT>::dynamic_table_begin() const {
- if (DynamicRegion.Addr)
- return Elf_Dyn_Iter(DynamicRegion.EntSize,
- (const char *)DynamicRegion.Addr);
- return Elf_Dyn_Iter(0, nullptr);
-}
-
-template <class ELFT>
-typename ELFFile<ELFT>::Elf_Dyn_Iter
-ELFFile<ELFT>::dynamic_table_end(bool NULLEnd) const {
- if (!DynamicRegion.Addr)
- return Elf_Dyn_Iter(0, nullptr);
- Elf_Dyn_Iter Ret(DynamicRegion.EntSize,
- (const char *)DynamicRegion.Addr + DynamicRegion.Size);
-
- if (NULLEnd) {
- Elf_Dyn_Iter Start = dynamic_table_begin();
- while (Start != Ret && Start->getTag() != ELF::DT_NULL)
- ++Start;
-
- // Include the DT_NULL.
- if (Start != Ret)
- ++Start;
- Ret = Start;
- }
- return Ret;
-}
-
-template <class ELFT>
-StringRef ELFFile<ELFT>::getLoadName() const {
- if (!dt_soname) {
- dt_soname = "";
- // Find the DT_SONAME entry
- for (const auto &Entry : dynamic_table())
- if (Entry.getTag() == ELF::DT_SONAME) {
- dt_soname = getDynamicString(Entry.getVal());
- break;
- }
- }
- return dt_soname;
+ assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header");
+ uintX_t Size = Phdr->p_filesz;
+ if (Size % sizeof(Elf_Dyn))
+ return object_error::elf_invalid_dynamic_table_size;
+ // FIKME: Check for overflow?
+ uintX_t End = Phdr->p_offset + Size;
+ if (End > Buf.size())
+ return object_error::parse_failed;
+ return reinterpret_cast<const Elf_Dyn *>(base() + End);
}
template <class ELFT>
@@ -908,127 +476,52 @@ ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
}
template <class ELFT>
-const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const {
- if (Offset >= DynStrRegion.Size)
- return nullptr;
- return (const char *)DynStrRegion.Addr + Offset;
-}
-
-template <class ELFT>
-ErrorOr<StringRef>
-ELFFile<ELFT>::getStaticSymbolName(const Elf_Sym *Symb) const {
- return Symb->getName(DotStrtab);
+ErrorOr<ArrayRef<typename ELFFile<ELFT>::Elf_Word>>
+ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const {
+ assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);
+ const Elf_Word *ShndxTableBegin =
+ reinterpret_cast<const Elf_Word *>(base() + Section.sh_offset);
+ uintX_t Size = Section.sh_size;
+ if (Size % sizeof(uint32_t))
+ return object_error::parse_failed;
+ uintX_t NumSymbols = Size / sizeof(uint32_t);
+ const Elf_Word *ShndxTableEnd = ShndxTableBegin + NumSymbols;
+ if (reinterpret_cast<const char *>(ShndxTableEnd) > Buf.end())
+ return object_error::parse_failed;
+ ErrorOr<const Elf_Shdr *> SymTableOrErr = getSection(Section.sh_link);
+ if (std::error_code EC = SymTableOrErr.getError())
+ return EC;
+ const Elf_Shdr &SymTable = **SymTableOrErr;
+ if (SymTable.sh_type != ELF::SHT_SYMTAB &&
+ SymTable.sh_type != ELF::SHT_DYNSYM)
+ return object_error::parse_failed;
+ if (NumSymbols != (SymTable.sh_size / sizeof(Elf_Sym)))
+ return object_error::parse_failed;
+ return makeArrayRef(ShndxTableBegin, ShndxTableEnd);
}
template <class ELFT>
ErrorOr<StringRef>
-ELFFile<ELFT>::getDynamicSymbolName(const Elf_Sym *Symb) const {
- return StringRef(getDynamicString(Symb->st_name));
-}
-
-template <class ELFT>
-ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Sym *Symb,
- bool IsDynamic) const {
- if (IsDynamic)
- return getDynamicSymbolName(Symb);
- return getStaticSymbolName(Symb);
+ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const {
+ if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)
+ return object_error::parse_failed;
+ ErrorOr<const Elf_Shdr *> SectionOrErr = getSection(Sec.sh_link);
+ if (std::error_code EC = SectionOrErr.getError())
+ return EC;
+ return getStringTable(*SectionOrErr);
}
template <class ELFT>
ErrorOr<StringRef>
ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const {
uint32_t Offset = Section->sh_name;
+ if (Offset == 0)
+ return StringRef();
if (Offset >= DotShstrtab.size())
return object_error::parse_failed;
return StringRef(DotShstrtab.data() + Offset);
}
-template <class ELFT>
-ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
- const Elf_Sym *symb,
- bool &IsDefault) const {
- StringRef StrTab;
- if (section) {
- ErrorOr<StringRef> StrTabOrErr = getStringTable(section);
- if (std::error_code EC = StrTabOrErr.getError())
- return EC;
- StrTab = *StrTabOrErr;
- }
- // Handle non-dynamic symbols.
- if (section != DotDynSymSec && section != nullptr) {
- // Non-dynamic symbols can have versions in their names
- // A name of the form 'foo@V1' indicates version 'V1', non-default.
- // A name of the form 'foo@@V2' indicates version 'V2', default version.
- ErrorOr<StringRef> SymName = symb->getName(StrTab);
- if (!SymName)
- return SymName;
- StringRef Name = *SymName;
- size_t atpos = Name.find('@');
- if (atpos == StringRef::npos) {
- IsDefault = false;
- return StringRef("");
- }
- ++atpos;
- if (atpos < Name.size() && Name[atpos] == '@') {
- IsDefault = true;
- ++atpos;
- } else {
- IsDefault = false;
- }
- return Name.substr(atpos);
- }
-
- // This is a dynamic symbol. Look in the GNU symbol version table.
- if (!dot_gnu_version_sec) {
- // No version table.
- IsDefault = false;
- return StringRef("");
- }
-
- // Determine the position in the symbol table of this entry.
- size_t entry_index =
- (reinterpret_cast<uintptr_t>(symb) - DotDynSymSec->sh_offset -
- reinterpret_cast<uintptr_t>(base())) /
- sizeof(Elf_Sym);
-
- // Get the corresponding version index entry
- const Elf_Versym *vs = getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index);
- size_t version_index = vs->vs_index & ELF::VERSYM_VERSION;
-
- // Special markers for unversioned symbols.
- if (version_index == ELF::VER_NDX_LOCAL ||
- version_index == ELF::VER_NDX_GLOBAL) {
- IsDefault = false;
- return StringRef("");
- }
-
- // Lookup this symbol in the version table
- LoadVersionMap();
- if (version_index >= VersionMap.size() || VersionMap[version_index].isNull())
- return object_error::parse_failed;
- const VersionMapEntry &entry = VersionMap[version_index];
-
- // Get the version name string
- size_t name_offset;
- if (entry.isVerdef()) {
- // The first Verdaux entry holds the name.
- name_offset = entry.getVerdef()->getAux()->vda_name;
- } else {
- name_offset = entry.getVernaux()->vna_name;
- }
-
- // Set IsDefault
- if (entry.isVerdef()) {
- IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN);
- } else {
- IsDefault = false;
- }
-
- if (name_offset >= DynStrRegion.Size)
- return object_error::parse_failed;
- return StringRef(getDynamicString(name_offset));
-}
-
/// This function returns the hash value for a symbol in the .dynsym section
/// Name of the API remains consistent as specified in the libelf
/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 6e8ace427a20..5823848aaacb 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -189,11 +189,13 @@ public:
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
- typedef typename ELFFile<ELFT>::Elf_Dyn_Iter Elf_Dyn_Iter;
-
protected:
ELFFile<ELFT> EF;
+ const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
+ const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
+ ArrayRef<Elf_Word> ShndxTable;
+
void moveSymbolNext(DataRefImpl &Symb) const override;
ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
@@ -204,9 +206,9 @@ protected:
uint8_t getSymbolOther(DataRefImpl Symb) const override;
uint8_t getSymbolELFType(DataRefImpl Symb) const override;
SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
- section_iterator getSymbolSection(const Elf_Sym *Symb) const;
- std::error_code getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const override;
+ ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb,
+ const Elf_Shdr *SymTab) const;
+ ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
@@ -240,10 +242,6 @@ protected:
return *EF.getSection(Rel.d.a);
}
- const Elf_Sym *toELFSymIter(DataRefImpl Sym) const {
- return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
- }
-
DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const {
DataRefImpl DRI;
if (!SymTable) {
@@ -273,9 +271,9 @@ protected:
return DRI;
}
- DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const {
+ DataRefImpl toDRI(const Elf_Dyn *Dyn) const {
DataRefImpl DRI;
- DRI.p = reinterpret_cast<uintptr_t>(Dyn.get());
+ DRI.p = reinterpret_cast<uintptr_t>(Dyn);
return DRI;
}
@@ -304,7 +302,13 @@ public:
const Elf_Rel *getRel(DataRefImpl Rel) const;
const Elf_Rela *getRela(DataRefImpl Rela) const;
- const Elf_Sym *getSymbol(DataRefImpl Symb) const;
+ const Elf_Sym *getSymbol(DataRefImpl Sym) const {
+ return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
+ }
+
+ const Elf_Shdr *getSection(DataRefImpl Sec) const {
+ return reinterpret_cast<const Elf_Shdr *>(Sec.p);
+ }
basic_symbol_iterator symbol_begin_impl() const override;
basic_symbol_iterator symbol_end_impl() const override;
@@ -320,7 +324,6 @@ public:
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
unsigned getArch() const override;
- StringRef getLoadName() const;
std::error_code getPlatformFlags(unsigned &Result) const override {
Result = EF.getHeader()->e_flags;
@@ -352,7 +355,7 @@ void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const {
template <class ELFT>
ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
- const Elf_Sym *ESym = toELFSymIter(Sym);
+ const Elf_Sym *ESym = getSymbol(Sym);
const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a);
const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link);
StringRef SymTable = *EF.getStringTable(StringTableSec);
@@ -361,12 +364,12 @@ ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSectionFlags(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_flags;
+ return getSection(Sec)->sh_flags;
}
template <class ELFT>
uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_type;
+ return getSection(Sec)->sh_type;
}
template <class ELFT>
@@ -398,9 +401,11 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
}
const Elf_Ehdr *Header = EF.getHeader();
+ const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a);
if (Header->e_type == ELF::ET_REL) {
- ErrorOr<const Elf_Shdr *> SectionOrErr = EF.getSection(ESym);
+ ErrorOr<const Elf_Shdr *> SectionOrErr =
+ EF.getSection(ESym, SymTab, ShndxTable);
if (std::error_code EC = SectionOrErr.getError())
return EC;
const Elf_Shdr *Section = *SectionOrErr;
@@ -413,7 +418,7 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
template <class ELFT>
uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
- const Elf_Sym *Sym = toELFSymIter(Symb);
+ const Elf_Sym *Sym = getSymbol(Symb);
if (Sym->st_shndx == ELF::SHN_COMMON)
return Sym->st_value;
return 0;
@@ -421,22 +426,22 @@ uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
- return toELFSymIter(Sym)->st_size;
+ return getSymbol(Sym)->st_size;
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
- return toELFSymIter(Symb)->st_size;
+ return getSymbol(Symb)->st_size;
}
template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const {
- return toELFSymIter(Symb)->st_other;
+ return getSymbol(Symb)->st_other;
}
template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const {
- return toELFSymIter(Symb)->getType();
+ return getSymbol(Symb)->getType();
}
template <class ELFT>
@@ -463,7 +468,7 @@ SymbolRef::Type ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
template <class ELFT>
uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
- const Elf_Sym *ESym = toELFSymIter(Sym);
+ const Elf_Sym *ESym = getSymbol(Sym);
uint32_t Result = SymbolRef::SF_None;
@@ -477,7 +482,8 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
Result |= SymbolRef::SF_Absolute;
if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION ||
- ESym == EF.symbol_begin() || ESym == EF.dynamic_symbol_begin())
+ ESym == EF.symbol_begin(DotSymtabSec) ||
+ ESym == EF.symbol_begin(DotDynSymSec))
Result |= SymbolRef::SF_FormatSpecific;
if (EF.getHeader()->e_machine == ELF::EM_ARM) {
@@ -505,11 +511,12 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
}
template <class ELFT>
-section_iterator
-ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
- ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym);
+ErrorOr<section_iterator>
+ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
+ const Elf_Shdr *SymTab) const {
+ ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable);
if (std::error_code EC = ESecOrErr.getError())
- report_fatal_error(EC.message());
+ return EC;
const Elf_Shdr *ESec = *ESecOrErr;
if (!ESec)
@@ -521,23 +528,23 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const {
- Res = getSymbolSection(getSymbol(Symb));
- return std::error_code();
+ErrorOr<section_iterator>
+ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const {
+ const Elf_Sym *Sym = getSymbol(Symb);
+ const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a);
+ return getSymbolSection(Sym, SymTab);
}
template <class ELFT>
void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const {
- const Elf_Shdr *ESec = toELFShdrIter(Sec);
+ const Elf_Shdr *ESec = getSection(Sec);
Sec = toDRI(++ESec);
}
template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
StringRef &Result) const {
- ErrorOr<StringRef> Name = EF.getSectionName(&*toELFShdrIter(Sec));
+ ErrorOr<StringRef> Name = EF.getSectionName(&*getSection(Sec));
if (!Name)
return Name.getError();
Result = *Name;
@@ -546,50 +553,50 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_addr;
+ return getSection(Sec)->sh_addr;
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_size;
+ return getSection(Sec)->sh_size;
}
template <class ELFT>
std::error_code
ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
StringRef &Result) const {
- const Elf_Shdr *EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = getSection(Sec);
Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
return std::error_code();
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_addralign;
+ return getSection(Sec)->sh_addralign;
}
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR;
+ return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR;
}
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const {
- const Elf_Shdr *EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = getSection(Sec);
return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
EShdr->sh_type == ELF::SHT_PROGBITS;
}
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const {
- const Elf_Shdr *EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = getSection(Sec);
return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
EShdr->sh_type == ELF::SHT_NOBITS;
}
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS;
+ return getSection(Sec)->sh_type == ELF::SHT_NOBITS;
}
template <class ELFT>
@@ -636,7 +643,7 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
if (EF.getHeader()->e_type != ELF::ET_REL)
return section_end();
- const Elf_Shdr *EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = getSection(Sec);
uintX_t Type = EShdr->sh_type;
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
return section_end();
@@ -668,9 +675,9 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
bool IsDyn = Rel.d.b & 1;
DataRefImpl SymbolData;
if (IsDyn)
- SymbolData = toDRI(EF.getDotDynSymSec(), symbolIdx);
+ SymbolData = toDRI(DotDynSymSec, symbolIdx);
else
- SymbolData = toDRI(EF.getDotSymtabSec(), symbolIdx);
+ SymbolData = toDRI(DotSymtabSec, symbolIdx);
return symbol_iterator(SymbolRef(SymbolData, this));
}
@@ -715,12 +722,6 @@ ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const {
}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Sym *
-ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const {
- return &*toELFSymIter(Symb);
-}
-
-template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rel *
ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const {
assert(getRelSection(Rel)->sh_type == ELF::SHT_REL);
@@ -737,21 +738,51 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
template <class ELFT>
ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC)
: ELFObjectFileBase(
- getELFType(static_cast<endianness>(ELFT::TargetEndianness) ==
- support::little,
- ELFT::Is64Bits),
+ getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits),
Object),
- EF(Data.getBuffer(), EC) {}
+ EF(Data.getBuffer(), EC) {
+ if (EC)
+ return;
+ for (const Elf_Shdr &Sec : EF.sections()) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_DYNSYM: {
+ if (DotDynSymSec) {
+ // More than one .dynsym!
+ EC = object_error::parse_failed;
+ return;
+ }
+ DotDynSymSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB: {
+ if (DotSymtabSec) {
+ // More than one .dynsym!
+ EC = object_error::parse_failed;
+ return;
+ }
+ DotSymtabSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB_SHNDX: {
+ ErrorOr<ArrayRef<Elf_Word>> TableOrErr = EF.getSHNDXTable(Sec);
+ if ((EC = TableOrErr.getError()))
+ return;
+ ShndxTable = *TableOrErr;
+ break;
+ }
+ }
+ }
+}
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const {
- DataRefImpl Sym = toDRI(EF.getDotSymtabSec(), 0);
+ DataRefImpl Sym = toDRI(DotSymtabSec, 0);
return basic_symbol_iterator(SymbolRef(Sym, this));
}
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end_impl() const {
- const Elf_Shdr *SymTab = EF.getDotSymtabSec();
+ const Elf_Shdr *SymTab = DotSymtabSec;
if (!SymTab)
return symbol_begin_impl();
DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
@@ -760,13 +791,13 @@ basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end_impl() const {
template <class ELFT>
elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const {
- DataRefImpl Sym = toDRI(EF.getDotDynSymSec(), 0);
+ DataRefImpl Sym = toDRI(DotDynSymSec, 0);
return symbol_iterator(SymbolRef(Sym, this));
}
template <class ELFT>
elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const {
- const Elf_Shdr *SymTab = EF.getDotDynSymSec();
+ const Elf_Shdr *SymTab = DotDynSymSec;
DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
return basic_symbol_iterator(SymbolRef(Sym, this));
}
@@ -782,19 +813,6 @@ section_iterator ELFObjectFile<ELFT>::section_end() const {
}
template <class ELFT>
-StringRef ELFObjectFile<ELFT>::getLoadName() const {
- Elf_Dyn_Iter DI = EF.dynamic_table_begin();
- Elf_Dyn_Iter DE = EF.dynamic_table_end();
-
- while (DI != DE && DI->getTag() != ELF::DT_SONAME)
- ++DI;
-
- if (DI != DE)
- return EF.getDynamicString(DI->getVal());
- return "";
-}
-
-template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const {
return ELFT::Is64Bits ? 8 : 4;
}
@@ -807,10 +825,14 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
switch (EF.getHeader()->e_machine) {
case ELF::EM_386:
return "ELF32-i386";
+ case ELF::EM_IAMCU:
+ return "ELF32-iamcu";
case ELF::EM_X86_64:
return "ELF32-x86-64";
case ELF::EM_ARM:
return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big");
+ case ELF::EM_AVR:
+ return "ELF32-avr";
case ELF::EM_HEXAGON:
return "ELF32-hexagon";
case ELF::EM_MIPS:
@@ -853,6 +875,7 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
bool IsLittleEndian = ELFT::TargetEndianness == support::little;
switch (EF.getHeader()->e_machine) {
case ELF::EM_386:
+ case ELF::EM_IAMCU:
return Triple::x86;
case ELF::EM_X86_64:
return Triple::x86_64;
@@ -860,6 +883,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
return Triple::aarch64;
case ELF::EM_ARM:
return Triple::arm;
+ case ELF::EM_AVR:
+ return Triple::avr;
case ELF::EM_HEXAGON:
return Triple::hexagon;
case ELF::EM_MIPS:
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 27e987ba2852..07b312a7d77c 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -12,7 +12,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/Error.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorOr.h"
@@ -307,14 +306,18 @@ struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> {
} d_un;
};
-/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters.
+/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters.
template <class ELFT>
struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
using Elf_Dyn_Base<ELFT>::d_tag;
using Elf_Dyn_Base<ELFT>::d_un;
- int64_t getTag() const { return d_tag; }
- uint64_t getVal() const { return d_un.d_val; }
- uint64_t getPtr() const { return d_un.d_ptr; }
+ typedef typename std::conditional<ELFT::Is64Bits,
+ int64_t, int32_t>::type intX_t;
+ typedef typename std::conditional<ELFT::Is64Bits,
+ uint64_t, uint32_t>::type uintX_t;
+ intX_t getTag() const { return d_tag; }
+ uintX_t getVal() const { return d_un.d_val; }
+ uintX_t getPtr() const { return d_un.d_ptr; }
};
// Elf_Rel: Elf Relocation
@@ -481,6 +484,30 @@ struct Elf_Hash_Impl {
}
};
+// .gnu.hash section
+template <class ELFT>
+struct Elf_GnuHash_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Word nbuckets;
+ Elf_Word symndx;
+ Elf_Word maskwords;
+ Elf_Word shift2;
+
+ ArrayRef<Elf_Off> filter() const {
+ return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1),
+ maskwords);
+ }
+
+ ArrayRef<Elf_Word> buckets() const {
+ return ArrayRef<Elf_Word>(
+ reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets);
+ }
+
+ ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const {
+ return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx);
+ }
+};
+
// MIPS .reginfo section
template <class ELFT>
struct Elf_Mips_RegInfo;
diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h
index aa320bb51a46..0f79a6ed0dd8 100644
--- a/include/llvm/Object/Error.h
+++ b/include/llvm/Object/Error.h
@@ -30,6 +30,7 @@ enum class object_error {
string_table_non_null_end,
invalid_section_index,
bitcode_section_not_found,
+ elf_invalid_dynamic_table_size,
macho_small_load_command,
macho_load_segment_too_many_sections,
macho_load_segment_too_small,
diff --git a/include/llvm/Object/FunctionIndexObjectFile.h b/include/llvm/Object/FunctionIndexObjectFile.h
new file mode 100644
index 000000000000..74b461dc7cc7
--- /dev/null
+++ b/include/llvm/Object/FunctionIndexObjectFile.h
@@ -0,0 +1,110 @@
+//===- FunctionIndexObjectFile.h - Function index file implementation -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the FunctionIndexObjectFile template class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H
+#define LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H
+
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/Object/SymbolicFile.h"
+
+namespace llvm {
+class FunctionInfoIndex;
+class Module;
+
+namespace object {
+class ObjectFile;
+
+/// This class is used to read just the function summary index related
+/// sections out of the given object (which may contain a single module's
+/// bitcode or be a combined index bitcode file). It builds a FunctionInfoIndex
+/// object.
+class FunctionIndexObjectFile : public SymbolicFile {
+ std::unique_ptr<FunctionInfoIndex> Index;
+
+public:
+ FunctionIndexObjectFile(MemoryBufferRef Object,
+ std::unique_ptr<FunctionInfoIndex> I);
+ ~FunctionIndexObjectFile() override;
+
+ // TODO: Walk through FunctionMap entries for function symbols.
+ // However, currently these interfaces are not used by any consumers.
+ void moveSymbolNext(DataRefImpl &Symb) const override {
+ llvm_unreachable("not implemented");
+ }
+ std::error_code printSymbolName(raw_ostream &OS,
+ DataRefImpl Symb) const override {
+ llvm_unreachable("not implemented");
+ return std::error_code();
+ }
+ uint32_t getSymbolFlags(DataRefImpl Symb) const override {
+ llvm_unreachable("not implemented");
+ return 0;
+ }
+ basic_symbol_iterator symbol_begin_impl() const override {
+ llvm_unreachable("not implemented");
+ return basic_symbol_iterator(BasicSymbolRef());
+ }
+ basic_symbol_iterator symbol_end_impl() const override {
+ llvm_unreachable("not implemented");
+ return basic_symbol_iterator(BasicSymbolRef());
+ }
+
+ const FunctionInfoIndex &getIndex() const {
+ return const_cast<FunctionIndexObjectFile *>(this)->getIndex();
+ }
+ FunctionInfoIndex &getIndex() { return *Index; }
+ std::unique_ptr<FunctionInfoIndex> takeIndex();
+
+ static inline bool classof(const Binary *v) { return v->isFunctionIndex(); }
+
+ /// \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);
+
+ /// \brief Finds and returns bitcode in the given memory buffer (which may
+ /// be either a bitcode file or a native object file with embedded bitcode),
+ /// or an error code if not found.
+ static ErrorOr<MemoryBufferRef>
+ findBitcodeInMemBuffer(MemoryBufferRef Object);
+
+ /// \brief Looks for function summary in the given memory buffer,
+ /// returns true if found, else false.
+ static bool
+ hasFunctionSummaryInMemBuffer(MemoryBufferRef Object,
+ DiagnosticHandlerFunction DiagnosticHandler);
+
+ /// \brief Parse function index in the given memory buffer.
+ /// Return new FunctionIndexObjectFile instance containing parsed function
+ /// summary/index.
+ static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
+ create(MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler,
+ bool IsLazy = false);
+
+ /// \brief Parse the function summary information for function with the
+ /// given name out of the given buffer. Parsed information is
+ /// stored on the index object saved in this object.
+ std::error_code
+ findFunctionSummaryInMemBuffer(MemoryBufferRef Object,
+ DiagnosticHandlerFunction DiagnosticHandler,
+ StringRef FunctionName);
+};
+}
+
+/// Parse the function index out of an IR file and return the function
+/// index object if found, or nullptr if not.
+ErrorOr<std::unique_ptr<FunctionInfoIndex>>
+getFunctionIndexForFile(StringRef Path,
+ DiagnosticHandlerFunction DiagnosticHandler);
+}
+
+#endif
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 489ecef5c996..e02ce3b21416 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -100,7 +100,7 @@ private:
};
typedef content_iterator<ExportEntry> export_iterator;
-/// MachORebaseEntry encapsulates the current state in the decompression of
+/// 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()) {
@@ -116,7 +116,7 @@ public:
bool operator==(const MachORebaseEntry &) const;
void moveNext();
-
+
private:
friend class MachOObjectFile;
void moveToFirst();
@@ -210,8 +210,7 @@ public:
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
- std::error_code getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const override;
+ ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
unsigned getSymbolSectionID(SymbolRef Symb) const;
unsigned getSectionID(SectionRef Sec) const;
@@ -423,6 +422,24 @@ public:
return v->isMachO();
}
+ static uint32_t
+ getVersionMinMajor(MachO::version_min_command &C, bool SDK) {
+ uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
+ return (VersionOrSDK >> 16) & 0xffff;
+ }
+
+ static uint32_t
+ getVersionMinMinor(MachO::version_min_command &C, bool SDK) {
+ uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
+ return (VersionOrSDK >> 8) & 0xff;
+ }
+
+ static uint32_t
+ getVersionMinUpdate(MachO::version_min_command &C, bool SDK) {
+ uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
+ return VersionOrSDK & 0xff;
+ }
+
private:
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
@@ -504,4 +521,3 @@ inline const ObjectFile *DiceRef::getObjectFile() const {
}
#endif
-
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 8dd525626218..ce0c891ee0c2 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -100,8 +100,7 @@ public:
relocation_iterator relocation_begin() const;
relocation_iterator relocation_end() const;
iterator_range<relocation_iterator> relocations() const {
- return iterator_range<relocation_iterator>(relocation_begin(),
- relocation_end());
+ return make_range(relocation_begin(), relocation_end());
}
section_iterator getRelocatedSection() const;
@@ -147,7 +146,7 @@ public:
/// @brief Get section this symbol is defined in reference to. Result is
/// end_sections() if it is undefined or is an absolute symbol.
- std::error_code getSection(section_iterator &Result) const;
+ ErrorOr<section_iterator> getSection() const;
const ObjectFile *getObject() const;
};
@@ -202,8 +201,8 @@ protected:
virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0;
virtual SymbolRef::Type getSymbolType(DataRefImpl Symb) const = 0;
- virtual std::error_code getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const = 0;
+ virtual ErrorOr<section_iterator>
+ getSymbolSection(DataRefImpl Symb) const = 0;
// Same as above for SectionRef.
friend class SectionRef;
@@ -323,8 +322,8 @@ inline uint64_t SymbolRef::getCommonSize() const {
return getObject()->getCommonSymbolSize(getRawDataRefImpl());
}
-inline std::error_code SymbolRef::getSection(section_iterator &Result) const {
- return getObject()->getSymbolSection(getRawDataRefImpl(), Result);
+inline ErrorOr<section_iterator> SymbolRef::getSection() const {
+ return getObject()->getSymbolSection(getRawDataRefImpl());
}
inline SymbolRef::Type SymbolRef::getType() const {
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index 537997ac6318..0c5b38111a9c 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -15,6 +15,7 @@
#define LLVM_OBJECT_SYMBOLICFILE_H
#include "llvm/Object/Binary.h"
+#include "llvm/Support/Format.h"
namespace llvm {
namespace object {
@@ -29,6 +30,12 @@ union DataRefImpl {
DataRefImpl() { std::memset(this, 0, sizeof(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) << "))";
+ return OS;
+}
+
inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) {
// Check bitwise identical. This is the only legal way to compare a union w/o
// knowing which member is in use.
@@ -94,6 +101,7 @@ public:
// (e.g. section symbols)
SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary
SF_Hidden = 1U << 9, // Symbol has hidden visibility
+ SF_Const = 1U << 10, // Symbol value is constant
};
BasicSymbolRef() : OwningObject(nullptr) { }