summaryrefslogtreecommitdiffstats
path: root/include/llvm/Object
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h4
-rw-r--r--include/llvm/Object/ArchiveWriter.h2
-rw-r--r--include/llvm/Object/Binary.h4
-rw-r--r--include/llvm/Object/COFF.h70
-rw-r--r--include/llvm/Object/COFFYAML.h6
-rw-r--r--include/llvm/Object/ELF.h470
-rw-r--r--include/llvm/Object/ELFObjectFile.h589
-rw-r--r--include/llvm/Object/ELFTypes.h125
-rw-r--r--include/llvm/Object/Error.h2
-rw-r--r--include/llvm/Object/IRObjectFile.h4
-rw-r--r--include/llvm/Object/MachO.h34
-rw-r--r--include/llvm/Object/MachOUniversal.h6
-rw-r--r--include/llvm/Object/ObjectFile.h134
-rw-r--r--include/llvm/Object/RelocVisitor.h16
-rw-r--r--include/llvm/Object/StackMapParser.h442
-rw-r--r--include/llvm/Object/SymbolSize.h23
-rw-r--r--include/llvm/Object/SymbolicFile.h6
17 files changed, 1229 insertions, 708 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 3a52a9d..8da6919 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -217,7 +217,7 @@ private:
unsigned IsThin : 1;
};
-} // namespace object
-} // namespace llvm
+}
+}
#endif
diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h
index 8a394fa..1616e46 100644
--- a/include/llvm/Object/ArchiveWriter.h
+++ b/include/llvm/Object/ArchiveWriter.h
@@ -46,6 +46,6 @@ std::pair<StringRef, std::error_code>
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab);
-} // namespace llvm
+}
#endif
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 949edf8..a3d6d0d 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -178,7 +178,7 @@ template <typename T> const T* OwningBinary<T>::getBinary() const {
}
ErrorOr<OwningBinary<Binary>> createBinary(StringRef Path);
-} // namespace object
-} // namespace llvm
+}
+}
#endif
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index ad657b5..fc60582 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -249,6 +249,15 @@ struct coff_symbol {
typedef coff_symbol<support::ulittle16_t> coff_symbol16;
typedef coff_symbol<support::ulittle32_t> coff_symbol32;
+// Contains only common parts of coff_symbol16 and coff_symbol32.
+struct coff_symbol_generic {
+ union {
+ char ShortName[COFF::NameSize];
+ StringTableOffset Offset;
+ } Name;
+ support::ulittle32_t Value;
+};
+
class COFFSymbolRef {
public:
COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {}
@@ -259,6 +268,12 @@ public:
return CS16 ? static_cast<const void *>(CS16) : CS32;
}
+ const coff_symbol_generic *getGeneric() const {
+ if (CS16)
+ return reinterpret_cast<const coff_symbol_generic *>(CS16);
+ return reinterpret_cast<const coff_symbol_generic *>(CS32);
+ }
+
friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) {
return A.getRawPtr() < B.getRawPtr();
}
@@ -493,6 +508,29 @@ struct coff_load_configuration32 {
support::ulittle32_t SEHandlerCount;
};
+struct coff_load_configuration64 {
+ support::ulittle32_t Characteristics;
+ support::ulittle32_t TimeDateStamp;
+ support::ulittle16_t MajorVersion;
+ support::ulittle16_t MinorVersion;
+ support::ulittle32_t GlobalFlagsClear;
+ support::ulittle32_t GlobalFlagsSet;
+ support::ulittle32_t CriticalSectionDefaultTimeout;
+ support::ulittle32_t DeCommitFreeBlockThreshold;
+ support::ulittle32_t DeCommitTotalFreeThreshold;
+ support::ulittle32_t LockPrefixTable;
+ support::ulittle32_t MaximumAllocationSize;
+ support::ulittle32_t VirtualMemoryThreshold;
+ support::ulittle32_t ProcessAffinityMask;
+ support::ulittle32_t ProcessHeapFlags;
+ support::ulittle16_t CSDVersion;
+ support::ulittle16_t Reserved;
+ support::ulittle32_t EditList;
+ support::ulittle64_t SecurityCookie;
+ support::ulittle64_t SEHandlerTable;
+ support::ulittle64_t SEHandlerCount;
+};
+
struct coff_runtime_function_x64 {
support::ulittle32_t BeginAddress;
support::ulittle32_t EndAddress;
@@ -609,14 +647,13 @@ public:
}
protected:
void moveSymbolNext(DataRefImpl &Symb) const override;
- std::error_code getSymbolName(DataRefImpl Symb,
- StringRef &Res) const override;
+ ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override;
- uint64_t getSymbolSize(DataRefImpl Symb) const override;
+ uint64_t getSymbolValue(DataRefImpl Symb) const override;
+ uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
- std::error_code getSymbolType(DataRefImpl Symb,
- SymbolRef::Type &Res) const override;
+ SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
std::error_code getSymbolSection(DataRefImpl Symb,
section_iterator &Res) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
@@ -631,21 +668,17 @@ protected:
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
- bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
- std::error_code getRelocationAddress(DataRefImpl Rel,
- uint64_t &Res) const override;
- std::error_code getRelocationOffset(DataRefImpl Rel,
- uint64_t &Res) const override;
+ ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const override;
+ uint64_t getRelocationOffset(DataRefImpl Rel) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
- std::error_code getRelocationType(DataRefImpl Rel,
- uint64_t &Res) const override;
- std::error_code
- getRelocationTypeName(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const override;
+ uint64_t getRelocationType(DataRefImpl Rel) const override;
+ void getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const override;
+
public:
COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
basic_symbol_iterator symbol_begin_impl() const override;
@@ -657,6 +690,8 @@ public:
COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
+ unsigned getSectionID(SectionRef Sec) const;
+ unsigned getSymbolSectionID(SymbolRef Sym) const;
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
@@ -720,6 +755,8 @@ public:
return std::error_code();
}
std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
+ std::error_code getSymbolName(const coff_symbol_generic *Symbol,
+ StringRef &Res) const;
ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
@@ -731,6 +768,9 @@ public:
llvm_unreachable("null symbol table pointer!");
}
+ iterator_range<const coff_relocation *>
+ getRelocations(const coff_section *Sec) const;
+
std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
uint64_t getSectionSize(const coff_section *Sec) const;
std::error_code getSectionContents(const coff_section *Sec,
diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h
index 5ba3db3..12a2522 100644
--- a/include/llvm/Object/COFFYAML.h
+++ b/include/llvm/Object/COFFYAML.h
@@ -37,7 +37,7 @@ inline DLLCharacteristics operator|(DLLCharacteristics a,
uint16_t Ret = static_cast<uint16_t>(a) | static_cast<uint16_t>(b);
return static_cast<DLLCharacteristics>(Ret);
}
-} // namespace COFF
+}
// The structure of the yaml files is not an exact 1:1 match to COFF. In order
// to use yaml::IO, we use these structures which are closer to the source.
@@ -87,8 +87,8 @@ namespace COFFYAML {
std::vector<Symbol> Symbols;
Object();
};
-} // namespace COFFYAML
-} // namespace llvm
+}
+}
LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section)
LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol)
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index e87737d..3b0c548 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -143,8 +143,7 @@ public:
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 ELFEntityIterator<const Elf_Shdr> Elf_Shdr_Iter;
- typedef iterator_range<Elf_Shdr_Iter> Elf_Shdr_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.
@@ -158,74 +157,7 @@ public:
enum { NumLowBitsAvailable = 1 };
};
- class Elf_Sym_Iter {
- public:
- typedef ptrdiff_t difference_type;
- typedef const Elf_Sym value_type;
- typedef std::random_access_iterator_tag iterator_category;
- typedef value_type &reference;
- typedef value_type *pointer;
-
- /// \brief Default construct iterator.
- Elf_Sym_Iter() : EntitySize(0), Current(0, false) {}
- Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic)
- : EntitySize(EntSize), Current(Start, IsDynamic) {}
-
- reference operator*() {
- assert(Current.getPointer() &&
- "Attempted to dereference an invalid iterator!");
- return *reinterpret_cast<pointer>(Current.getPointer());
- }
-
- pointer operator->() {
- assert(Current.getPointer() &&
- "Attempted to dereference an invalid iterator!");
- return reinterpret_cast<pointer>(Current.getPointer());
- }
-
- bool operator==(const Elf_Sym_Iter &Other) {
- return Current == Other.Current;
- }
-
- bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); }
-
- Elf_Sym_Iter &operator++() {
- assert(Current.getPointer() &&
- "Attempted to increment an invalid iterator!");
- Current.setPointer(Current.getPointer() + EntitySize);
- return *this;
- }
-
- Elf_Sym_Iter operator++(int) {
- Elf_Sym_Iter Tmp = *this;
- ++*this;
- return Tmp;
- }
-
- Elf_Sym_Iter operator+(difference_type Dist) {
- assert(Current.getPointer() &&
- "Attempted to increment an invalid iterator!");
- Current.setPointer(Current.getPointer() + EntitySize * Dist);
- return *this;
- }
-
- difference_type operator-(const Elf_Sym_Iter &Other) const {
- assert(EntitySize == Other.EntitySize &&
- "Subtracting iterators of different EntitySize!");
- return (Current.getPointer() - Other.Current.getPointer()) / EntitySize;
- }
-
- const char *get() const { return Current.getPointer(); }
-
- bool isDynamic() const { return Current.getInt(); }
-
- uintX_t getEntSize() const { return EntitySize; }
-
- private:
- uintX_t EntitySize;
- PointerIntPair<const char *, 1, bool,
- ArchivePointerTypeTraits<const char> > Current;
- };
+ typedef iterator_range<const Elf_Sym *> Elf_Sym_Range;
private:
typedef SmallVector<const Elf_Shdr *, 2> Sections_t;
@@ -238,17 +170,19 @@ private:
}
const Elf_Ehdr *Header;
- const Elf_Shdr *SectionHeaderTable;
- const Elf_Shdr *dot_shstrtab_sec; // Section header string table.
- const Elf_Shdr *dot_strtab_sec; // Symbol header string table.
- const Elf_Shdr *dot_symtab_sec; // Symbol table section.
-
- const Elf_Shdr *SymbolTableSectionHeaderIndex;
+ 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.
+ StringRef DynSymStrTab; // Dynnamic symbol string table.
+ const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
+
+ const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr;
DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable;
- const Elf_Shdr *dot_gnu_version_sec; // .gnu.version
- const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r
- const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d
+ 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 {
@@ -263,12 +197,11 @@ private:
DynRegionInfo DynamicRegion;
DynRegionInfo DynHashRegion;
- DynRegionInfo DynStrRegion;
- DynRegionInfo DynSymRegion;
+ DynRegionInfo DynRelaRegion;
// Pointer to SONAME entry in dynamic string table
// This is set the first time getLoadName is called.
- mutable const char *dt_soname;
+ 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.
@@ -301,8 +234,11 @@ public:
const T *getEntry(uint32_t Section, uint32_t Entry) const;
template <typename T>
const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const;
- const char *getString(uint32_t section, uint32_t offset) const;
- const char *getString(const Elf_Shdr *section, uint32_t offset) const;
+
+ const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; }
+ const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
+
+ 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,
@@ -331,55 +267,77 @@ public:
Header->getDataEncoding() == ELF::ELFDATA2LSB;
}
- Elf_Shdr_Iter begin_sections() const;
- Elf_Shdr_Iter end_sections() const;
+ const Elf_Shdr *section_begin() const;
+ const Elf_Shdr *section_end() const;
Elf_Shdr_Range sections() const {
- return make_range(begin_sections(), end_sections());
+ return make_range(section_begin(), section_end());
}
- Elf_Sym_Iter begin_symbols() const;
- Elf_Sym_Iter end_symbols() const;
+ 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 begin_dynamic_table() const;
+ 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 end_dynamic_table(bool NULLEnd = false) const;
+ Elf_Dyn_Iter dynamic_table_end(bool NULLEnd = false) const;
Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const {
- return make_range(begin_dynamic_table(), end_dynamic_table(NULLEnd));
+ return make_range(dynamic_table_begin(), dynamic_table_end(NULLEnd));
+ }
+
+ const Elf_Sym *dynamic_symbol_begin() const {
+ if (!DotDynSymSec)
+ return nullptr;
+ if (DotDynSymSec->sh_entsize != sizeof(Elf_Sym))
+ report_fatal_error("Invalid symbol size");
+ return reinterpret_cast<const Elf_Sym *>(base() + DotDynSymSec->sh_offset);
+ }
+
+ const Elf_Sym *dynamic_symbol_end() const {
+ if (!DotDynSymSec)
+ return nullptr;
+ return reinterpret_cast<const Elf_Sym *>(base() + DotDynSymSec->sh_offset +
+ DotDynSymSec->sh_size);
}
- Elf_Sym_Iter begin_dynamic_symbols() const {
- if (DynSymRegion.Addr)
- return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr,
- true);
- return Elf_Sym_Iter(0, nullptr, true);
+ Elf_Sym_Range dynamic_symbols() const {
+ return make_range(dynamic_symbol_begin(), dynamic_symbol_end());
}
- Elf_Sym_Iter end_dynamic_symbols() const {
- if (DynSymRegion.Addr)
- return Elf_Sym_Iter(DynSymRegion.EntSize,
- (const char *)DynSymRegion.Addr + DynSymRegion.Size,
- true);
- return Elf_Sym_Iter(0, nullptr, true);
+ 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);
}
- Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const {
+ 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);
+ }
+
+ 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_Iter end_rela(const Elf_Shdr *sec) const {
+ 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));
}
- Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const {
+ Elf_Rel_Iter rel_begin(const Elf_Shdr *sec) const {
return Elf_Rel_Iter(sec->sh_entsize,
(const char *)(base() + sec->sh_offset));
}
- Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const {
+ 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));
}
@@ -387,12 +345,12 @@ public:
/// \brief Iterate over program header table.
typedef ELFEntityIterator<const Elf_Phdr> Elf_Phdr_Iter;
- Elf_Phdr_Iter begin_program_headers() const {
+ Elf_Phdr_Iter program_header_begin() const {
return Elf_Phdr_Iter(Header->e_phentsize,
(const char*)base() + Header->e_phoff);
}
- Elf_Phdr_Iter end_program_headers() const {
+ Elf_Phdr_Iter program_header_end() const {
return Elf_Phdr_Iter(Header->e_phentsize,
(const char*)base() +
Header->e_phoff +
@@ -401,24 +359,17 @@ public:
uint64_t getNumSections() const;
uintX_t getStringTableIndex() const;
- ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const;
+ ELF::Elf64_Word getExtendedSymbolTableIndex(const Elf_Sym *symb) const;
const Elf_Ehdr *getHeader() const { return Header; }
- const Elf_Shdr *getSection(const Elf_Sym *symb) const;
- const Elf_Shdr *getSection(uint32_t Index) const;
+ ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *symb) const;
+ ErrorOr<const Elf_Shdr *> getSection(uint32_t Index) const;
const Elf_Sym *getSymbol(uint32_t index) const;
- ErrorOr<StringRef> getSymbolName(Elf_Sym_Iter Sym) 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;
- /// \brief Get the name of \p Symb.
- /// \param SymTab The symbol table section \p Symb is contained in.
- /// \param Symb The symbol to get the name of.
- ///
- /// \p SymTab is used to lookup the string table to use to get the symbol's
- /// name.
- ErrorOr<StringRef> getSymbolName(const Elf_Shdr *SymTab,
- const Elf_Sym *Symb) const;
ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const;
- uint64_t getSymbolIndex(const Elf_Sym *sym) const;
ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const;
StringRef getLoadName() const;
};
@@ -490,7 +441,7 @@ void ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const {
template <class ELFT>
void ELFFile<ELFT>::LoadVersionMap() const {
// If there is no dynamic symtab or version table, there is nothing to do.
- if (!DynSymRegion.Addr || !dot_gnu_version_sec)
+ if (!DotDynSymSec || !dot_gnu_version_sec)
return;
// Has the VersionMap already been loaded?
@@ -510,18 +461,19 @@ void ELFFile<ELFT>::LoadVersionMap() const {
}
template <class ELFT>
-ELF::Elf64_Word ELFFile<ELFT>::getSymbolTableIndex(const Elf_Sym *symb) const {
- if (symb->st_shndx == ELF::SHN_XINDEX)
- return ExtendedSymbolTable.lookup(symb);
- return symb->st_shndx;
+ELF::Elf64_Word
+ELFFile<ELFT>::getExtendedSymbolTableIndex(const Elf_Sym *symb) const {
+ assert(symb->st_shndx == ELF::SHN_XINDEX);
+ return ExtendedSymbolTable.lookup(symb);
}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Shdr *
+ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *>
ELFFile<ELFT>::getSection(const Elf_Sym *symb) const {
- if (symb->st_shndx == ELF::SHN_XINDEX)
+ uint32_t Index = symb->st_shndx;
+ if (Index == ELF::SHN_XINDEX)
return getSection(ExtendedSymbolTable.lookup(symb));
- if (symb->st_shndx >= ELF::SHN_LORESERVE)
+ if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
return nullptr;
return getSection(symb->st_shndx);
}
@@ -529,7 +481,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym *symb) const {
template <class ELFT>
const typename ELFFile<ELFT>::Elf_Sym *
ELFFile<ELFT>::getSymbol(uint32_t Index) const {
- return &*(begin_symbols() + Index);
+ return &*(symbol_begin() + Index);
}
template <class ELFT>
@@ -584,20 +536,14 @@ std::pair<const typename ELFFile<ELFT>::Elf_Shdr *,
ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const {
if (!Sec->sh_link)
return std::make_pair(nullptr, nullptr);
- const Elf_Shdr *SymTable = getSection(Sec->sh_link);
+ 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())));
}
-// Verify that the last byte in the string table in a null.
-template <class ELFT>
-void ELFFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const {
- const char *strtab = (const char *)base() + sh->sh_offset;
- if (strtab[sh->sh_size - 1] != 0)
- // FIXME: Proper error handling.
- report_fatal_error("String table must end with a null terminator!");
-}
-
template <class ELFT>
uint64_t ELFFile<ELFT>::getNumSections() const {
assert(Header && "Header not initialized!");
@@ -621,11 +567,7 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const {
template <class ELFT>
ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
- : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr),
- dot_strtab_sec(nullptr), dot_symtab_sec(nullptr),
- SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr),
- dot_gnu_version_r_sec(nullptr), dot_gnu_version_d_sec(nullptr),
- dt_soname(nullptr) {
+ : Buf(Object) {
const uint64_t FileSize = Buf.size();
if (sizeof(Elf_Ehdr) > FileSize) {
@@ -670,28 +612,35 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
}
SymbolTableSectionHeaderIndex = &Sec;
break;
- case ELF::SHT_SYMTAB:
+ case ELF::SHT_SYMTAB: {
if (dot_symtab_sec) {
// More than one .symtab!
EC = object_error::parse_failed;
return;
}
dot_symtab_sec = &Sec;
- dot_strtab_sec = getSection(Sec.sh_link);
- break;
+ 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 (DynSymRegion.Addr) {
+ if (DotDynSymSec) {
// More than one .dynsym!
EC = object_error::parse_failed;
return;
}
- DynSymRegion.Addr = base() + Sec.sh_offset;
- DynSymRegion.Size = Sec.sh_size;
- DynSymRegion.EntSize = Sec.sh_entsize;
- const Elf_Shdr *DynStr = getSection(Sec.sh_link);
- DynStrRegion.Addr = base() + DynStr->sh_offset;
- DynStrRegion.Size = DynStr->sh_size;
- DynStrRegion.EntSize = DynStr->sh_entsize;
+ 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;
+ DynSymStrTab = *SymtabOrErr;
break;
}
case ELF::SHT_DYNAMIC:
@@ -732,27 +681,29 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
}
// Get string table sections.
- dot_shstrtab_sec = getSection(getStringTableIndex());
- if (dot_shstrtab_sec) {
- // Verify that the last byte in the string table in a null.
- VerifyStrTab(dot_shstrtab_sec);
- }
+ ErrorOr<const Elf_Shdr *> StrTabSecOrErr = getSection(getStringTableIndex());
+ if ((EC = StrTabSecOrErr.getError()))
+ return;
+
+ ErrorOr<StringRef> SymtabOrErr = getStringTable(*StrTabSecOrErr);
+ if ((EC = SymtabOrErr.getError()))
+ return;
+ DotShstrtab = *SymtabOrErr;
// 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 (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE;
- ++SI) {
+ for (const Elf_Sym &S : symbols()) {
if (*ShndxTable != ELF::SHN_UNDEF)
- ExtendedSymbolTable[&*SI] = *ShndxTable;
+ ExtendedSymbolTable[&S] = *ShndxTable;
++ShndxTable;
}
}
// Scan program headers.
- for (Elf_Phdr_Iter PhdrI = begin_program_headers(),
- PhdrE = end_program_headers();
+ 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;
@@ -762,55 +713,74 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
}
}
- EC = std::error_code();
-}
+ // Scan dynamic table.
+ for (Elf_Dyn_Iter DynI = dynamic_table_begin(), DynE = dynamic_table_end();
+ DynI != DynE; ++DynI) {
+ switch (DynI->d_tag) {
+ case ELF::DT_RELA: {
+ uint64_t VBase = 0;
+ const uint8_t *FBase = nullptr;
+ for (Elf_Phdr_Iter PhdrI = program_header_begin(),
+ PhdrE = program_header_end();
+ PhdrI != PhdrE; ++PhdrI) {
+ if (PhdrI->p_type != ELF::PT_LOAD)
+ continue;
+ if (DynI->getPtr() >= PhdrI->p_vaddr &&
+ DynI->getPtr() < PhdrI->p_vaddr + PhdrI->p_memsz) {
+ VBase = PhdrI->p_vaddr;
+ FBase = base() + PhdrI->p_offset;
+ break;
+ }
+ }
+ if (!VBase)
+ return;
+ DynRelaRegion.Addr = FBase + DynI->getPtr() - VBase;
+ break;
+ }
+ case ELF::DT_RELASZ:
+ DynRelaRegion.Size = DynI->getVal();
+ break;
+ case ELF::DT_RELAENT:
+ DynRelaRegion.EntSize = DynI->getVal();
+ }
+ }
-// Get the symbol table index in the symtab section given a symbol
-template <class ELFT>
-uint64_t ELFFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const {
- uintptr_t SymLoc = uintptr_t(Sym);
- uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset);
- assert(SymLoc > SymTabLoc && "Symbol not in symbol table!");
- uint64_t SymOffset = SymLoc - SymTabLoc;
- assert(SymOffset % dot_symtab_sec->sh_entsize == 0 &&
- "Symbol not multiple of symbol size!");
- return SymOffset / dot_symtab_sec->sh_entsize;
+ EC = std::error_code();
}
template <class ELFT>
-typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::begin_sections() const {
- return Elf_Shdr_Iter(Header->e_shentsize,
- (const char *)base() + Header->e_shoff);
+const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_begin() const {
+ if (Header->e_shentsize != sizeof(Elf_Shdr))
+ report_fatal_error(
+ "Invalid section header entry size (e_shentsize) in ELF header");
+ return reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff);
}
template <class ELFT>
-typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::end_sections() const {
- return Elf_Shdr_Iter(Header->e_shentsize,
- (const char *)base() + Header->e_shoff +
- (getNumSections() * Header->e_shentsize));
+const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_end() const {
+ return section_begin() + getNumSections();
}
template <class ELFT>
-typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const {
+const typename ELFFile<ELFT>::Elf_Sym *ELFFile<ELFT>::symbol_begin() const {
if (!dot_symtab_sec)
- return Elf_Sym_Iter(0, nullptr, false);
- return Elf_Sym_Iter(dot_symtab_sec->sh_entsize,
- (const char *)base() + dot_symtab_sec->sh_offset, false);
+ 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);
}
template <class ELFT>
-typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::end_symbols() const {
+const typename ELFFile<ELFT>::Elf_Sym *ELFFile<ELFT>::symbol_end() const {
if (!dot_symtab_sec)
- return Elf_Sym_Iter(0, nullptr, false);
- return Elf_Sym_Iter(dot_symtab_sec->sh_entsize,
- (const char *)base() + dot_symtab_sec->sh_offset +
- dot_symtab_sec->sh_size,
- false);
+ 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>::begin_dynamic_table() const {
+ELFFile<ELFT>::dynamic_table_begin() const {
if (DynamicRegion.Addr)
return Elf_Dyn_Iter(DynamicRegion.EntSize,
(const char *)DynamicRegion.Addr);
@@ -819,14 +789,14 @@ ELFFile<ELFT>::begin_dynamic_table() const {
template <class ELFT>
typename ELFFile<ELFT>::Elf_Dyn_Iter
-ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const {
+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 = begin_dynamic_table();
+ Elf_Dyn_Iter Start = dynamic_table_begin();
while (Start != Ret && Start->getTag() != ELF::DT_NULL)
++Start;
@@ -855,7 +825,10 @@ StringRef ELFFile<ELFT>::getLoadName() const {
template <class ELFT>
template <typename T>
const T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const {
- return getEntry<T>(getSection(Section), Entry);
+ ErrorOr<const Elf_Shdr *> Sec = getSection(Section);
+ if (std::error_code EC = Sec.getError())
+ report_fatal_error(EC.message());
+ return getEntry<T>(*Sec, Entry);
}
template <class ELFT>
@@ -867,82 +840,85 @@ const T *ELFFile<ELFT>::getEntry(const Elf_Shdr *Section,
}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Shdr *
-ELFFile<ELFT>::getSection(uint32_t index) const {
- if (index == 0)
- return nullptr;
- if (!SectionHeaderTable || index >= getNumSections())
- // FIXME: Proper error handling.
- report_fatal_error("Invalid section index!");
+ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *>
+ELFFile<ELFT>::getSection(uint32_t Index) const {
+ assert(SectionHeaderTable && "SectionHeaderTable not initialized!");
+ if (Index >= getNumSections())
+ return object_error::invalid_section_index;
return reinterpret_cast<const Elf_Shdr *>(
- reinterpret_cast<const char *>(SectionHeaderTable)
- + (index * Header->e_shentsize));
+ reinterpret_cast<const char *>(SectionHeaderTable) +
+ (Index * Header->e_shentsize));
}
template <class ELFT>
-const char *ELFFile<ELFT>::getString(uint32_t section,
- ELF::Elf32_Word offset) const {
- return getString(getSection(section), offset);
-}
-
-template <class ELFT>
-const char *ELFFile<ELFT>::getString(const Elf_Shdr *section,
- ELF::Elf32_Word offset) const {
- assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!");
- if (offset >= section->sh_size)
- // FIXME: Proper error handling.
- report_fatal_error("Symbol name offset outside of string table!");
- return (const char *)base() + section->sh_offset + offset;
+ErrorOr<StringRef>
+ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
+ if (Section->sh_type != ELF::SHT_STRTAB)
+ return object_error::parse_failed;
+ uint64_t Offset = Section->sh_offset;
+ uint64_t Size = Section->sh_size;
+ if (Offset + Size > Buf.size())
+ return object_error::parse_failed;
+ StringRef Data((const char *)base() + Section->sh_offset, Size);
+ if (Data[Size - 1] != '\0')
+ return object_error::string_table_non_null_end;
+ return Data;
}
template <class ELFT>
const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const {
- if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size)
+ if (!DotDynSymSec || Offset >= DynSymStrTab.size())
return nullptr;
- return (const char *)DynStrRegion.Addr + Offset;
+ return (const char *)DynSymStrTab.begin() + Offset;
}
template <class ELFT>
-ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(Elf_Sym_Iter Sym) const {
- if (!Sym.isDynamic())
- return getSymbolName(dot_symtab_sec, &*Sym);
-
- if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size)
- return object_error::parse_failed;
- return StringRef(getDynamicString(Sym->st_name));
+ErrorOr<StringRef>
+ELFFile<ELFT>::getStaticSymbolName(const Elf_Sym *Symb) const {
+ return Symb->getName(DotStrtab);
}
template <class ELFT>
-ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section,
- const Elf_Sym *Symb) const {
- if (Symb->st_name == 0)
- return StringRef("");
+ErrorOr<StringRef>
+ELFFile<ELFT>::getDynamicSymbolName(const Elf_Sym *Symb) const {
+ return StringRef(getDynamicString(Symb->st_name));
+}
- const Elf_Shdr *StrTab = getSection(Section->sh_link);
- if (Symb->st_name >= StrTab->sh_size)
- return object_error::parse_failed;
- return StringRef(getString(StrTab, 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);
}
template <class ELFT>
ErrorOr<StringRef>
ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const {
- if (Section->sh_name >= dot_shstrtab_sec->sh_size)
+ uint32_t Offset = Section->sh_name;
+ if (Offset >= DotShstrtab.size())
return object_error::parse_failed;
- return StringRef(getString(dot_shstrtab_sec, Section->sh_name));
+ 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 != DynSymRegion.Addr && section != nullptr) {
+ 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 = getSymbolName(section, symb);
+ ErrorOr<StringRef> SymName = symb->getName(StrTab);
if (!SymName)
return SymName;
StringRef Name = *SymName;
@@ -969,8 +945,10 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
}
// Determine the position in the symbol table of this entry.
- size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) /
- DynSymRegion.EntSize;
+ 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);
@@ -1005,7 +983,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
IsDefault = false;
}
- if (name_offset >= DynStrRegion.Size)
+ if (name_offset >= DynSymStrTab.size())
return object_error::parse_failed;
return StringRef(getDynamicString(name_offset));
}
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 7fc56ad..5b9b113 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -35,27 +35,148 @@
namespace llvm {
namespace object {
+class elf_symbol_iterator;
+class ELFSymbolRef;
+class ELFRelocationRef;
+
class ELFObjectFileBase : public ObjectFile {
+ friend class ELFSymbolRef;
+ friend class ELFSectionRef;
+ friend class ELFRelocationRef;
+
protected:
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
-public:
- virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
+ virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
+ virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0;
+ virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0;
- // FIXME: This is a bit of a hack. Every caller should know if it expecting
- // and addend or not.
- virtual bool hasRelocationAddend(DataRefImpl Rel) const = 0;
+ virtual uint32_t getSectionType(DataRefImpl Sec) const = 0;
+ virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0;
- virtual std::pair<symbol_iterator, symbol_iterator>
- getELFDynamicSymbolIterators() const = 0;
+ virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
+public:
- virtual uint64_t getSectionFlags(SectionRef Sec) const = 0;
- virtual uint32_t getSectionType(SectionRef Sec) const = 0;
+ typedef iterator_range<elf_symbol_iterator> elf_symbol_iterator_range;
+ virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0;
+
+ elf_symbol_iterator_range symbols() const;
static inline bool classof(const Binary *v) { return v->isELF(); }
};
+class ELFSectionRef : public SectionRef {
+public:
+ ELFSectionRef(const SectionRef &B) : SectionRef(B) {
+ assert(isa<ELFObjectFileBase>(SectionRef::getObject()));
+ }
+
+ const ELFObjectFileBase *getObject() const {
+ return cast<ELFObjectFileBase>(SectionRef::getObject());
+ }
+
+ uint32_t getType() const {
+ return getObject()->getSectionType(getRawDataRefImpl());
+ }
+
+ uint64_t getFlags() const {
+ return getObject()->getSectionFlags(getRawDataRefImpl());
+ }
+};
+
+class elf_section_iterator : public section_iterator {
+public:
+ elf_section_iterator(const section_iterator &B) : section_iterator(B) {
+ assert(isa<ELFObjectFileBase>(B->getObject()));
+ }
+
+ const ELFSectionRef *operator->() const {
+ return static_cast<const ELFSectionRef *>(section_iterator::operator->());
+ }
+
+ const ELFSectionRef &operator*() const {
+ return static_cast<const ELFSectionRef &>(section_iterator::operator*());
+ }
+};
+
+class ELFSymbolRef : public SymbolRef {
+public:
+ ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) {
+ assert(isa<ELFObjectFileBase>(SymbolRef::getObject()));
+ }
+
+ const ELFObjectFileBase *getObject() const {
+ return cast<ELFObjectFileBase>(BasicSymbolRef::getObject());
+ }
+
+ uint64_t getSize() const {
+ return getObject()->getSymbolSize(getRawDataRefImpl());
+ }
+
+ uint8_t getOther() const {
+ return getObject()->getSymbolOther(getRawDataRefImpl());
+ }
+
+ uint8_t getELFType() const {
+ return getObject()->getSymbolELFType(getRawDataRefImpl());
+ }
+};
+
+class elf_symbol_iterator : public symbol_iterator {
+public:
+ elf_symbol_iterator(const basic_symbol_iterator &B)
+ : symbol_iterator(SymbolRef(B->getRawDataRefImpl(),
+ cast<ELFObjectFileBase>(B->getObject()))) {}
+
+ const ELFSymbolRef *operator->() const {
+ return static_cast<const ELFSymbolRef *>(symbol_iterator::operator->());
+ }
+
+ const ELFSymbolRef &operator*() const {
+ return static_cast<const ELFSymbolRef &>(symbol_iterator::operator*());
+ }
+};
+
+class ELFRelocationRef : public RelocationRef {
+public:
+ ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) {
+ assert(isa<ELFObjectFileBase>(RelocationRef::getObject()));
+ }
+
+ const ELFObjectFileBase *getObject() const {
+ return cast<ELFObjectFileBase>(RelocationRef::getObject());
+ }
+
+ ErrorOr<int64_t> getAddend() const {
+ return getObject()->getRelocationAddend(getRawDataRefImpl());
+ }
+};
+
+class elf_relocation_iterator : public relocation_iterator {
+public:
+ elf_relocation_iterator(const relocation_iterator &B)
+ : relocation_iterator(RelocationRef(
+ B->getRawDataRefImpl(), cast<ELFObjectFileBase>(B->getObject()))) {}
+
+ const ELFRelocationRef *operator->() const {
+ return static_cast<const ELFRelocationRef *>(
+ relocation_iterator::operator->());
+ }
+
+ const ELFRelocationRef &operator*() const {
+ return static_cast<const ELFRelocationRef &>(
+ relocation_iterator::operator*());
+ }
+};
+
+inline ELFObjectFileBase::elf_symbol_iterator_range
+ELFObjectFileBase::symbols() const {
+ return elf_symbol_iterator_range(symbol_begin(), symbol_end());
+}
+
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
+ uint64_t getSymbolSize(DataRefImpl Sym) const override;
+
public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
@@ -68,24 +189,22 @@ public:
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
- typedef typename ELFFile<ELFT>::Elf_Sym_Iter Elf_Sym_Iter;
- typedef typename ELFFile<ELFT>::Elf_Shdr_Iter Elf_Shdr_Iter;
typedef typename ELFFile<ELFT>::Elf_Dyn_Iter Elf_Dyn_Iter;
protected:
ELFFile<ELFT> EF;
void moveSymbolNext(DataRefImpl &Symb) const override;
- std::error_code getSymbolName(DataRefImpl Symb,
- StringRef &Res) const override;
+ ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override;
+ uint64_t getSymbolValue(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
- uint64_t getSymbolSize(DataRefImpl Symb) const override;
+ uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
- std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
- std::error_code getSymbolType(DataRefImpl Symb,
- SymbolRef::Type &Res) const override;
+ 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;
@@ -102,62 +221,55 @@ protected:
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
- bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) 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;
void moveRelocationNext(DataRefImpl &Rel) const override;
- std::error_code getRelocationAddress(DataRefImpl Rel,
- uint64_t &Res) const override;
- std::error_code getRelocationOffset(DataRefImpl Rel,
- uint64_t &Res) const override;
+ ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const override;
+ uint64_t getRelocationOffset(DataRefImpl Rel) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
- std::error_code getRelocationType(DataRefImpl Rel,
- uint64_t &Res) const override;
- std::error_code
- getRelocationTypeName(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const override;
+ uint64_t getRelocationType(DataRefImpl Rel) const override;
+ void getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const override;
+ uint32_t getSectionType(DataRefImpl Sec) const override;
+ uint64_t getSectionFlags(DataRefImpl Sec) const override;
uint64_t getROffset(DataRefImpl Rel) const;
StringRef getRelocationTypeName(uint32_t Type) const;
/// \brief Get the relocation section that contains \a Rel.
const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
- return EF.getSection(Rel.d.a);
+ return *EF.getSection(Rel.d.a);
}
- const Elf_Rel *getRel(DataRefImpl Rel) const;
- const Elf_Rela *getRela(DataRefImpl Rela) const;
-
- Elf_Sym_Iter toELFSymIter(DataRefImpl Symb) const {
- bool IsDynamic = Symb.p & 1;
- if (IsDynamic)
- return Elf_Sym_Iter(
- EF.begin_dynamic_symbols().getEntSize(),
- reinterpret_cast<const char *>(Symb.p & ~uintptr_t(1)), IsDynamic);
- return Elf_Sym_Iter(EF.begin_symbols().getEntSize(),
- reinterpret_cast<const char *>(Symb.p), IsDynamic);
+ const Elf_Sym *toELFSymIter(DataRefImpl Sym) const {
+ return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
}
- DataRefImpl toDRI(Elf_Sym_Iter Symb) const {
+ DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const {
DataRefImpl DRI;
- DRI.p = reinterpret_cast<uintptr_t>(Symb.get()) |
- static_cast<uintptr_t>(Symb.isDynamic());
- return DRI;
- }
+ if (!SymTable) {
+ DRI.d.a = 0;
+ DRI.d.b = 0;
+ return DRI;
+ }
+ assert(SymTable->sh_type == ELF::SHT_SYMTAB ||
+ SymTable->sh_type == ELF::SHT_DYNSYM);
- Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const {
- return Elf_Shdr_Iter(EF.getHeader()->e_shentsize,
- reinterpret_cast<const char *>(Sec.p));
- }
+ uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin());
+ unsigned SymTableIndex =
+ (reinterpret_cast<uintptr_t>(SymTable) - SHT) / sizeof(Elf_Shdr);
- DataRefImpl toDRI(Elf_Shdr_Iter Sec) const {
- DataRefImpl DRI;
- DRI.p = reinterpret_cast<uintptr_t>(Sec.get());
+ DRI.d.a = SymTableIndex;
+ DRI.d.b = SymbolNum;
return DRI;
}
+ const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const {
+ return reinterpret_cast<const Elf_Shdr *>(Sec.p);
+ }
+
DataRefImpl toDRI(const Elf_Shdr *Sec) const {
DataRefImpl DRI;
DRI.p = reinterpret_cast<uintptr_t>(Sec);
@@ -197,22 +309,21 @@ protected:
public:
ELFObjectFile(MemoryBufferRef Object, std::error_code &EC);
+ const Elf_Rel *getRel(DataRefImpl Rel) const;
+ const Elf_Rela *getRela(DataRefImpl Rela) const;
+
const Elf_Sym *getSymbol(DataRefImpl Symb) const;
basic_symbol_iterator symbol_begin_impl() const override;
basic_symbol_iterator symbol_end_impl() const override;
- symbol_iterator dynamic_symbol_begin() const;
- symbol_iterator dynamic_symbol_end() const;
+ elf_symbol_iterator dynamic_symbol_begin() const;
+ elf_symbol_iterator dynamic_symbol_end() const;
section_iterator section_begin() const override;
section_iterator section_end() const override;
ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const override;
- bool hasRelocationAddend(DataRefImpl Rel) const override;
-
- uint64_t getSectionFlags(SectionRef Sec) const override;
- uint32_t getSectionType(SectionRef Sec) const override;
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
@@ -232,8 +343,7 @@ public:
ELFT::Is64Bits);
}
- std::pair<symbol_iterator, symbol_iterator>
- getELFDynamicSymbolIterators() const override;
+ elf_symbol_iterator_range getDynamicSymbolIterators() const override;
bool isRelocatableObject() const override;
};
@@ -244,59 +354,71 @@ typedef ELFObjectFile<ELFType<support::big, false>> ELF32BEObjectFile;
typedef ELFObjectFile<ELFType<support::big, true>> ELF64BEObjectFile;
template <class ELFT>
-void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const {
- Symb = toDRI(++toELFSymIter(Symb));
+void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const {
+ ++Sym.d.b;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb,
- StringRef &Result) const {
- ErrorOr<StringRef> Name = EF.getSymbolName(toELFSymIter(Symb));
- if (!Name)
- return Name.getError();
- Result = *Name;
- return std::error_code();
+ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
+ const Elf_Sym *ESym = toELFSymIter(Sym);
+ const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a);
+ const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link);
+ StringRef SymTable = *EF.getStringTable(StringTableSec);
+ return ESym->getName(SymTable);
}
template <class ELFT>
-uint64_t ELFObjectFile<ELFT>::getSectionFlags(SectionRef Sec) const {
- DataRefImpl DRI = Sec.getRawDataRefImpl();
- return toELFShdrIter(DRI)->sh_flags;
+uint64_t ELFObjectFile<ELFT>::getSectionFlags(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_flags;
}
template <class ELFT>
-uint32_t ELFObjectFile<ELFT>::getSectionType(SectionRef Sec) const {
- DataRefImpl DRI = Sec.getRawDataRefImpl();
- return toELFShdrIter(DRI)->sh_type;
+uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_type;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
- uint64_t &Result) const {
+uint64_t ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb) const {
const Elf_Sym *ESym = getSymbol(Symb);
- switch (EF.getSymbolTableIndex(ESym)) {
+ switch (ESym->st_shndx) {
case ELF::SHN_COMMON:
case ELF::SHN_UNDEF:
- Result = UnknownAddressOrSize;
- return std::error_code();
+ return UnknownAddress;
case ELF::SHN_ABS:
- Result = ESym->st_value;
- return std::error_code();
- default:
- break;
+ return ESym->st_value;
}
const Elf_Ehdr *Header = EF.getHeader();
- Result = ESym->st_value;
+ uint64_t Ret = ESym->st_value;
// Clear the ARM/Thumb or microMIPS indicator flag.
if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) &&
ESym->getType() == ELF::STT_FUNC)
- Result &= ~1;
+ Ret &= ~1;
+
+ return Ret;
+}
+
+template <class ELFT>
+std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
+ uint64_t &Result) const {
+ Result = getSymbolValue(Symb);
+ const Elf_Sym *ESym = getSymbol(Symb);
+ switch (ESym->st_shndx) {
+ case ELF::SHN_COMMON:
+ case ELF::SHN_UNDEF:
+ case ELF::SHN_ABS:
+ return std::error_code();
+ }
+
+ const Elf_Ehdr *Header = EF.getHeader();
if (Header->e_type == ELF::ET_REL) {
- const typename ELFFile<ELFT>::Elf_Shdr * Section = EF.getSection(ESym);
- if (Section != nullptr)
+ ErrorOr<const Elf_Shdr *> SectionOrErr = EF.getSection(ESym);
+ if (std::error_code EC = SectionOrErr.getError())
+ return EC;
+ const Elf_Shdr *Section = *SectionOrErr;
+ if (Section)
Result += Section->sh_addr;
}
@@ -305,59 +427,57 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
template <class ELFT>
uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
- Elf_Sym_Iter Sym = toELFSymIter(Symb);
+ const Elf_Sym *Sym = toELFSymIter(Symb);
if (Sym->st_shndx == ELF::SHN_COMMON)
return Sym->st_value;
return 0;
}
template <class ELFT>
-uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb) const {
+uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
+ return toELFSymIter(Sym)->st_size;
+}
+
+template <class ELFT>
+uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
return toELFSymIter(Symb)->st_size;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb,
- uint8_t &Result) const {
- Result = toELFSymIter(Symb)->st_other;
- return std::error_code();
+uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const {
+ return toELFSymIter(Symb)->st_other;
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb,
- SymbolRef::Type &Result) const {
+uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const {
+ return toELFSymIter(Symb)->getType();
+}
+
+template <class ELFT>
+SymbolRef::Type ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
const Elf_Sym *ESym = getSymbol(Symb);
switch (ESym->getType()) {
case ELF::STT_NOTYPE:
- Result = SymbolRef::ST_Unknown;
- break;
+ return SymbolRef::ST_Unknown;
case ELF::STT_SECTION:
- Result = SymbolRef::ST_Debug;
- break;
+ return SymbolRef::ST_Debug;
case ELF::STT_FILE:
- Result = SymbolRef::ST_File;
- break;
+ return SymbolRef::ST_File;
case ELF::STT_FUNC:
- Result = SymbolRef::ST_Function;
- break;
+ return SymbolRef::ST_Function;
case ELF::STT_OBJECT:
case ELF::STT_COMMON:
case ELF::STT_TLS:
- Result = SymbolRef::ST_Data;
- break;
+ return SymbolRef::ST_Data;
default:
- Result = SymbolRef::ST_Other;
- break;
+ return SymbolRef::ST_Other;
}
- return std::error_code();
}
template <class ELFT>
-uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const {
- Elf_Sym_Iter EIter = toELFSymIter(Symb);
- const Elf_Sym *ESym = &*EIter;
+uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
+ const Elf_Sym *ESym = toELFSymIter(Sym);
uint32_t Result = SymbolRef::SF_None;
@@ -371,14 +491,22 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const {
Result |= SymbolRef::SF_Absolute;
if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION ||
- EIter == EF.begin_symbols() || EIter == EF.begin_dynamic_symbols())
+ ESym == EF.symbol_begin() || ESym == EF.dynamic_symbol_begin())
Result |= SymbolRef::SF_FormatSpecific;
- if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF)
+ if (EF.getHeader()->e_machine == ELF::EM_ARM) {
+ if (ErrorOr<StringRef> NameOrErr = getSymbolName(Sym)) {
+ StringRef Name = *NameOrErr;
+ if (Name.startswith("$d") || Name.startswith("$t") ||
+ Name.startswith("$a"))
+ Result |= SymbolRef::SF_FormatSpecific;
+ }
+ }
+
+ if (ESym->st_shndx == ELF::SHN_UNDEF)
Result |= SymbolRef::SF_Undefined;
- if (ESym->getType() == ELF::STT_COMMON ||
- EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON)
+ if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON)
Result |= SymbolRef::SF_Common;
if (isExportedToOtherDSO(ESym))
@@ -393,14 +521,17 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const {
template <class ELFT>
section_iterator
ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
- const Elf_Shdr *ESec = EF.getSection(ESym);
+ ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym);
+ if (std::error_code EC = ESecOrErr.getError())
+ report_fatal_error(EC.message());
+
+ const Elf_Shdr *ESec = *ESecOrErr;
if (!ESec)
return section_end();
- else {
- DataRefImpl Sec;
- Sec.p = reinterpret_cast<intptr_t>(ESec);
- return section_iterator(SectionRef(Sec, this));
- }
+
+ DataRefImpl Sec;
+ Sec.p = reinterpret_cast<intptr_t>(ESec);
+ return section_iterator(SectionRef(Sec, this));
}
template <class ELFT>
@@ -413,7 +544,8 @@ ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
template <class ELFT>
void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const {
- Sec = toDRI(++toELFShdrIter(Sec));
+ const Elf_Shdr *ESec = toELFShdrIter(Sec);
+ Sec = toDRI(++ESec);
}
template <class ELFT>
@@ -440,7 +572,7 @@ template <class ELFT>
std::error_code
ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
StringRef &Result) const {
- Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = toELFShdrIter(Sec);
Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
return std::error_code();
}
@@ -457,14 +589,14 @@ bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const {
- Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = toELFShdrIter(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 {
- Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = toELFShdrIter(Sec);
return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
EShdr->sh_type == ELF::SHT_NOBITS;
}
@@ -475,38 +607,40 @@ bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
}
template <class ELFT>
-bool ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb) const {
- Elf_Sym_Iter ESym = toELFSymIter(Symb);
-
- uintX_t Index = ESym->st_shndx;
- bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE;
-
- return !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx));
-}
-
-template <class ELFT>
relocation_iterator
ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
DataRefImpl RelData;
- uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.begin_sections().get());
+ uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin());
RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize;
RelData.d.b = 0;
+
+ const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
+ if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
+ return relocation_iterator(RelocationRef(RelData, this));
+
+ const Elf_Shdr *RelSec = getRelSection(RelData);
+ ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link);
+ if (std::error_code EC = SymSecOrErr.getError())
+ report_fatal_error(EC.message());
+ const Elf_Shdr *SymSec = *SymSecOrErr;
+ uint32_t SymSecType = SymSec->sh_type;
+ if (SymSecType != ELF::SHT_SYMTAB && SymSecType != ELF::SHT_DYNSYM)
+ report_fatal_error("Invalid symbol table section type!");
+ if (SymSecType == ELF::SHT_DYNSYM)
+ RelData.d.b = 1;
+
return relocation_iterator(RelocationRef(RelData, this));
}
template <class ELFT>
relocation_iterator
ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
- DataRefImpl RelData;
- uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.begin_sections().get());
const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize;
+ relocation_iterator Begin = section_rel_begin(Sec);
if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
- RelData.d.b = 0;
- else
- RelData.d.b = S->sh_size / S->sh_entsize;
-
+ return Begin;
+ DataRefImpl RelData = Begin->getRawDataRefImpl();
+ RelData.d.b += (S->sh_size / S->sh_entsize) << 1;
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -516,19 +650,21 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
if (EF.getHeader()->e_type != ELF::ET_REL)
return section_end();
- Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
+ const Elf_Shdr *EShdr = toELFShdrIter(Sec);
uintX_t Type = EShdr->sh_type;
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
return section_end();
- const Elf_Shdr *R = EF.getSection(EShdr->sh_info);
- return section_iterator(SectionRef(toDRI(R), this));
+ ErrorOr<const Elf_Shdr *> R = EF.getSection(EShdr->sh_info);
+ if (std::error_code EC = R.getError())
+ report_fatal_error(EC.message());
+ return section_iterator(SectionRef(toDRI(*R), this));
}
// Relocations
template <class ELFT>
void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const {
- ++Rel.d.b;
+ Rel.d.b += 2;
}
template <class ELFT>
@@ -536,96 +672,62 @@ symbol_iterator
ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
uint32_t symbolIdx;
const Elf_Shdr *sec = getRelSection(Rel);
- switch (sec->sh_type) {
- default:
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL: {
+ if (sec->sh_type == ELF::SHT_REL)
symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL());
- break;
- }
- case ELF::SHT_RELA: {
+ else
symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL());
- break;
- }
- }
if (!symbolIdx)
return symbol_end();
- const Elf_Shdr *SymSec = EF.getSection(sec->sh_link);
-
+ bool IsDyn = Rel.d.b & 1;
DataRefImpl SymbolData;
- switch (SymSec->sh_type) {
- default:
- report_fatal_error("Invalid symbol table section type!");
- case ELF::SHT_SYMTAB:
- SymbolData = toDRI(EF.begin_symbols() + symbolIdx);
- break;
- case ELF::SHT_DYNSYM:
- SymbolData = toDRI(EF.begin_dynamic_symbols() + symbolIdx);
- break;
- }
-
+ if (IsDyn)
+ SymbolData = toDRI(EF.getDotDynSymSec(), symbolIdx);
+ else
+ SymbolData = toDRI(EF.getDotSymtabSec(), symbolIdx);
return symbol_iterator(SymbolRef(SymbolData, this));
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
- uint64_t &Result) const {
+ErrorOr<uint64_t>
+ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel) const {
uint64_t ROffset = getROffset(Rel);
const Elf_Ehdr *Header = EF.getHeader();
if (Header->e_type == ELF::ET_REL) {
const Elf_Shdr *RelocationSec = getRelSection(Rel);
- const Elf_Shdr *RelocatedSec = EF.getSection(RelocationSec->sh_info);
- Result = ROffset + RelocatedSec->sh_addr;
- } else {
- Result = ROffset;
+ ErrorOr<const Elf_Shdr *> RelocatedSec =
+ EF.getSection(RelocationSec->sh_info);
+ if (std::error_code EC = RelocatedSec.getError())
+ return EC;
+ return ROffset + (*RelocatedSec)->sh_addr;
}
-
- return std::error_code();
+ return ROffset;
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel,
- uint64_t &Result) const {
+uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
assert(EF.getHeader()->e_type == ELF::ET_REL &&
"Only relocatable object files have relocation offsets");
- Result = getROffset(Rel);
- return std::error_code();
+ return getROffset(Rel);
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const {
const Elf_Shdr *sec = getRelSection(Rel);
- switch (sec->sh_type) {
- default:
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL:
+ if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->r_offset;
- case ELF::SHT_RELA:
- return getRela(Rel)->r_offset;
- }
+
+ return getRela(Rel)->r_offset;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel,
- uint64_t &Result) const {
+uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const {
const Elf_Shdr *sec = getRelSection(Rel);
- switch (sec->sh_type) {
- default:
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL: {
- Result = getRel(Rel)->getType(EF.isMips64EL());
- break;
- }
- case ELF::SHT_RELA: {
- Result = getRela(Rel)->getType(EF.isMips64EL());
- break;
- }
- }
- return std::error_code();
+ if (sec->sh_type == ELF::SHT_REL)
+ return getRel(Rel)->getType(EF.isMips64EL());
+ else
+ return getRela(Rel)->getType(EF.isMips64EL());
}
template <class ELFT>
@@ -634,25 +736,10 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getRelocationTypeName(
+void ELFObjectFile<ELFT>::getRelocationTypeName(
DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
- const Elf_Shdr *sec = getRelSection(Rel);
- uint32_t type;
- switch (sec->sh_type) {
- default:
- return object_error::parse_failed;
- case ELF::SHT_REL: {
- type = getRel(Rel)->getType(EF.isMips64EL());
- break;
- }
- case ELF::SHT_RELA: {
- type = getRela(Rel)->getType(EF.isMips64EL());
- break;
- }
- }
-
+ uint32_t type = getRelocationType(Rel);
EF.getRelocationTypeName(type, Result);
- return std::error_code();
}
template <class ELFT>
@@ -664,11 +751,6 @@ ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const {
}
template <class ELFT>
-bool ELFObjectFile<ELFT>::hasRelocationAddend(DataRefImpl Rel) const {
- return getRelSection(Rel)->sh_type == ELF::SHT_RELA;
-}
-
-template <class ELFT>
const typename ELFFile<ELFT>::Elf_Sym *
ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const {
return &*toELFSymIter(Symb);
@@ -677,13 +759,15 @@ ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const {
template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rel *
ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const {
- return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b);
+ assert(getRelSection(Rel)->sh_type == ELF::SHT_REL);
+ return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b >> 1);
}
template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rela *
ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
- return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b);
+ assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA);
+ return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b >> 1);
}
template <class ELFT>
@@ -697,38 +781,46 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC)
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const {
- return basic_symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this));
+ DataRefImpl Sym = toDRI(EF.getDotSymtabSec(), 0);
+ return basic_symbol_iterator(SymbolRef(Sym, this));
}
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end_impl() const {
- return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this));
+ const Elf_Shdr *SymTab = EF.getDotSymtabSec();
+ if (!SymTab)
+ return symbol_begin_impl();
+ DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
+ return basic_symbol_iterator(SymbolRef(Sym, this));
}
template <class ELFT>
-symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const {
- return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this));
+elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const {
+ DataRefImpl Sym = toDRI(EF.getDotDynSymSec(), 0);
+ return symbol_iterator(SymbolRef(Sym, this));
}
template <class ELFT>
-symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const {
- return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this));
+elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const {
+ const Elf_Shdr *SymTab = EF.getDotDynSymSec();
+ DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
+ return basic_symbol_iterator(SymbolRef(Sym, this));
}
template <class ELFT>
section_iterator ELFObjectFile<ELFT>::section_begin() const {
- return section_iterator(SectionRef(toDRI(EF.begin_sections()), this));
+ return section_iterator(SectionRef(toDRI(EF.section_begin()), this));
}
template <class ELFT>
section_iterator ELFObjectFile<ELFT>::section_end() const {
- return section_iterator(SectionRef(toDRI(EF.end_sections()), this));
+ return section_iterator(SectionRef(toDRI(EF.section_end()), this));
}
template <class ELFT>
StringRef ELFObjectFile<ELFT>::getLoadName() const {
- Elf_Dyn_Iter DI = EF.begin_dynamic_table();
- Elf_Dyn_Iter DE = EF.end_dynamic_table();
+ 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;
@@ -834,21 +926,16 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
}
template <class ELFT>
-std::pair<symbol_iterator, symbol_iterator>
-ELFObjectFile<ELFT>::getELFDynamicSymbolIterators() const {
- return std::make_pair(dynamic_symbol_begin(), dynamic_symbol_end());
+ELFObjectFileBase::elf_symbol_iterator_range
+ELFObjectFile<ELFT>::getDynamicSymbolIterators() const {
+ return make_range(dynamic_symbol_begin(), dynamic_symbol_end());
}
template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
return EF.getHeader()->e_type == ELF::ET_REL;
}
-inline std::pair<symbol_iterator, symbol_iterator>
-getELFDynamicSymbolIterators(const SymbolicFile *Obj) {
- return cast<ELFObjectFileBase>(Obj)->getELFDynamicSymbolIterators();
}
-
-} // namespace object
-} // namespace llvm
+}
#endif
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 2eda0c1..63e1390 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -10,9 +10,11 @@
#ifndef LLVM_OBJECT_ELFTYPES_H
#define LLVM_OBJECT_ELFTYPES_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"
namespace llvm {
namespace object {
@@ -24,6 +26,11 @@ template <endianness target_endianness, bool is64Bits> struct ELFType {
static const bool Is64Bits = is64Bits;
};
+typedef ELFType<support::little, false> ELF32LE;
+typedef ELFType<support::big, false> ELF32BE;
+typedef ELFType<support::little, true> ELF64LE;
+typedef ELFType<support::big, true> ELF64BE;
+
// Use an alignment of 2 for the typedefs since that is the worst case for
// ELF files in archives.
@@ -197,8 +204,21 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
return st_shndx >= ELF::SHN_LORESERVE;
}
bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; }
+ bool isExternal() const {
+ return getBinding() != ELF::STB_LOCAL;
+ }
+
+ ErrorOr<StringRef> getName(StringRef StrTab) const;
};
+template <class ELFT>
+ErrorOr<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
+ uint32_t Offset = this->st_name;
+ if (Offset >= StrTab.size())
+ return object_error::parse_failed;
+ return StringRef(StrTab.data() + Offset);
+}
+
/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
/// (.gnu.version). This structure is identical for ELF32 and ELF64.
template <class ELFT>
@@ -293,14 +313,14 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
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.ptr; }
+ uint64_t getPtr() const { return d_un.d_ptr; }
};
// Elf_Rel: Elf Relocation
-template <class ELFT, bool isRela> struct Elf_Rel_Base;
+template <class ELFT, bool isRela> struct Elf_Rel_Impl;
template <endianness TargetEndianness>
-struct Elf_Rel_Base<ELFType<TargetEndianness, false>, false> {
+struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Word r_info; // Symbol table index and type of relocation to apply
@@ -313,64 +333,46 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, false>, false> {
assert(!IsMips64EL);
r_info = R;
}
-};
-
-template <endianness TargetEndianness>
-struct Elf_Rel_Base<ELFType<TargetEndianness, true>, false> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Xword r_info; // Symbol table index and type of relocation to apply
- uint64_t getRInfo(bool isMips64EL) const {
- uint64_t t = r_info;
- if (!isMips64EL)
- return t;
- // Mips64 little endian has a "special" encoding of r_info. Instead of one
- // 64 bit little endian number, it is a little endian 32 bit number followed
- // by a 32 bit big endian number.
- return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
- ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
+ // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
+ // and ELF32_R_INFO macros defined in the ELF specification:
+ uint32_t getSymbol(bool isMips64EL) const {
+ return this->getRInfo(isMips64EL) >> 8;
}
- void setRInfo(uint64_t R, bool IsMips64EL) {
- if (IsMips64EL)
- r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
- ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
- else
- r_info = R;
+ unsigned char getType(bool isMips64EL) const {
+ return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
+ }
+ void setSymbol(uint32_t s, bool IsMips64EL) {
+ setSymbolAndType(s, getType(), IsMips64EL);
+ }
+ void setType(unsigned char t, bool IsMips64EL) {
+ setSymbolAndType(getSymbol(), t, IsMips64EL);
+ }
+ void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
+ this->setRInfo((s << 8) + t, IsMips64EL);
}
};
template <endianness TargetEndianness>
-struct Elf_Rel_Base<ELFType<TargetEndianness, false>, true> {
+struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true>
+ : public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Word r_info; // Symbol table index and type of relocation to apply
Elf_Sword r_addend; // Compute value for relocatable field by adding this
-
- uint32_t getRInfo(bool isMips64EL) const {
- assert(!isMips64EL);
- return r_info;
- }
- void setRInfo(uint32_t R, bool IsMips64EL) {
- assert(!IsMips64EL);
- r_info = R;
- }
};
template <endianness TargetEndianness>
-struct Elf_Rel_Base<ELFType<TargetEndianness, true>, true> {
+struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Xword r_info; // Symbol table index and type of relocation to apply
- Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
+ Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
+ Elf_Xword r_info; // Symbol table index and type of relocation to apply
uint64_t getRInfo(bool isMips64EL) const {
- // Mips64 little endian has a "special" encoding of r_info. Instead of one
- // 64 bit little endian number, it is a little endian 32 bit number followed
- // by a 32 bit big endian number.
uint64_t t = r_info;
if (!isMips64EL)
return t;
+ // Mips64 little endian has a "special" encoding of r_info. Instead of one
+ // 64 bit little endian number, it is a little endian 32 bit number followed
+ // by a 32 bit big endian number.
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
@@ -381,14 +383,6 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, true>, true> {
else
r_info = R;
}
-};
-
-template <class ELFT, bool isRela> struct Elf_Rel_Impl;
-
-template <endianness TargetEndianness, bool isRela>
-struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, isRela>
- : Elf_Rel_Base<ELFType<TargetEndianness, true>, isRela> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
// These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
// and ELF64_R_INFO macros defined in the ELF specification:
@@ -409,28 +403,11 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, isRela>
}
};
-template <endianness TargetEndianness, bool isRela>
-struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, isRela>
- : Elf_Rel_Base<ELFType<TargetEndianness, false>, isRela> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
-
- // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
- // and ELF32_R_INFO macros defined in the ELF specification:
- uint32_t getSymbol(bool isMips64EL) const {
- return this->getRInfo(isMips64EL) >> 8;
- }
- unsigned char getType(bool isMips64EL) const {
- return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
- }
- void setSymbol(uint32_t s, bool IsMips64EL) {
- setSymbolAndType(s, getType(), IsMips64EL);
- }
- void setType(unsigned char t, bool IsMips64EL) {
- setSymbolAndType(getSymbol(), t, IsMips64EL);
- }
- void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
- this->setRInfo((s << 8) + t, IsMips64EL);
- }
+template <endianness TargetEndianness>
+struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true>
+ : public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
+ Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
};
template <class ELFT>
diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h
index c9db1b8..aa320bb 100644
--- a/include/llvm/Object/Error.h
+++ b/include/llvm/Object/Error.h
@@ -27,6 +27,8 @@ enum class object_error {
invalid_file_type,
parse_failed,
unexpected_eof,
+ string_table_non_null_end,
+ invalid_section_index,
bitcode_section_not_found,
macho_small_load_command,
macho_load_segment_too_many_sections,
diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h
index f713570..ef65528 100644
--- a/include/llvm/Object/IRObjectFile.h
+++ b/include/llvm/Object/IRObjectFile.h
@@ -68,7 +68,7 @@ public:
static ErrorOr<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object,
LLVMContext &Context);
};
-} // namespace object
-} // namespace llvm
+}
+}
#endif
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 4350a75..f4edfd0 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -197,8 +197,9 @@ public:
std::error_code &EC);
void moveSymbolNext(DataRefImpl &Symb) const override;
- std::error_code getSymbolName(DataRefImpl Symb,
- StringRef &Res) const override;
+
+ uint64_t getNValue(DataRefImpl Sym) const;
+ ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
// MachO specific.
std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
@@ -206,13 +207,15 @@ public:
std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override;
+ uint64_t getSymbolValue(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
- uint64_t getSymbolSize(DataRefImpl Symb) const override;
- std::error_code getSymbolType(DataRefImpl Symb,
- SymbolRef::Type &Res) const override;
+ 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;
+ unsigned getSymbolSectionID(SymbolRef Symb) const;
+ unsigned getSectionID(SectionRef Sec) const;
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
@@ -226,24 +229,17 @@ public:
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
- bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
- std::error_code getRelocationAddress(DataRefImpl Rel,
- uint64_t &Res) const override;
- std::error_code getRelocationOffset(DataRefImpl Rel,
- uint64_t &Res) const override;
+ ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const override;
+ uint64_t getRelocationOffset(DataRefImpl Rel) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
section_iterator getRelocationSection(DataRefImpl Rel) const;
- std::error_code getRelocationType(DataRefImpl Rel,
- uint64_t &Res) const override;
- std::error_code
- getRelocationTypeName(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const override;
- std::error_code getRelocationHidden(DataRefImpl Rel,
- bool &Result) const override;
+ uint64_t getRelocationType(DataRefImpl Rel) const override;
+ void getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const override;
uint8_t getRelocationLength(DataRefImpl Rel) const;
// MachO specific.
@@ -503,8 +499,8 @@ inline const ObjectFile *DiceRef::getObjectFile() const {
return OwningObject;
}
-} // namespace object
-} // namespace llvm
+}
+}
#endif
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index ebc8b90..a11d381 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -109,10 +109,10 @@ public:
}
ErrorOr<std::unique_ptr<MachOObjectFile>>
- getObjectForArch(Triple::ArchType Arch) const;
+ getObjectForArch(StringRef ArchName) const;
};
-} // namespace object
-} // namespace llvm
+}
+}
#endif
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index e00fe0e..62eab10 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -35,8 +35,8 @@ class symbol_iterator;
class SectionRef;
typedef content_iterator<SectionRef> section_iterator;
-/// RelocationRef - This is a value type class that represents a single
-/// relocation in the list of relocations in the object file.
+/// This is a value type class that represents a single relocation in the list
+/// of relocations in the object file.
class RelocationRef {
DataRefImpl RelocationPimpl;
const ObjectFile *OwningObject;
@@ -50,29 +50,23 @@ public:
void moveNext();
- std::error_code getAddress(uint64_t &Result) const;
- std::error_code getOffset(uint64_t &Result) const;
+ ErrorOr<uint64_t> getAddress() const;
+ uint64_t getOffset() const;
symbol_iterator getSymbol() const;
- std::error_code getType(uint64_t &Result) const;
-
- /// @brief Indicates whether this relocation should hidden when listing
- /// relocations, usually because it is the trailing part of a multipart
- /// relocation that will be printed as part of the leading relocation.
- std::error_code getHidden(bool &Result) const;
+ uint64_t getType() const;
/// @brief Get a string that represents the type of this relocation.
///
/// This is for display purposes only.
- std::error_code getTypeName(SmallVectorImpl<char> &Result) const;
-
+ void getTypeName(SmallVectorImpl<char> &Result) const;
DataRefImpl getRawDataRefImpl() const;
- const ObjectFile *getObjectFile() const;
+ const ObjectFile *getObject() const;
};
typedef content_iterator<RelocationRef> relocation_iterator;
-/// SectionRef - This is a value type class that represents a single section in
-/// the list of sections in the object file.
+/// This is a value type class that represents a single section in the list of
+/// sections in the object file.
class SectionRef {
friend class SymbolRef;
DataRefImpl SectionPimpl;
@@ -116,8 +110,8 @@ public:
const ObjectFile *getObject() const;
};
-/// SymbolRef - This is a value type class that represents a single symbol in
-/// the list of symbols in the object file.
+/// This is a value type class that represents a single symbol in the list of
+/// symbols in the object file.
class SymbolRef : public BasicSymbolRef {
friend class SectionRef;
@@ -134,16 +128,23 @@ public:
};
SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
+ SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) {
+ assert(isa<ObjectFile>(BasicSymbolRef::getObject()));
+ }
- std::error_code getName(StringRef &Result) const;
+ ErrorOr<StringRef> getName() const;
/// Returns the symbol virtual address (i.e. address at which it will be
/// mapped).
std::error_code getAddress(uint64_t &Result) const;
+
+ /// Return the value of the symbol depending on the object this can be an
+ /// offset or a virtual address.
+ uint64_t getValue() const;
+
/// @brief Get the alignment of this symbol as the actual value (not log 2).
uint32_t getAlignment() const;
- uint64_t getSize() const;
- std::error_code getType(SymbolRef::Type &Result) const;
- std::error_code getOther(uint8_t &Result) const;
+ uint64_t getCommonSize() const;
+ SymbolRef::Type getType() const;
/// @brief Get section this symbol is defined in reference to. Result is
/// end_sections() if it is undefined or is an absolute symbol.
@@ -170,9 +171,9 @@ public:
}
};
-/// ObjectFile - This class is the base class for all object file types.
-/// Concrete instances of this object are created by createObjectFile, which
-/// figures out which type to create.
+/// This class is the base class for all object file types. Concrete instances
+/// of this object are created by createObjectFile, which figures out which type
+/// to create.
class ObjectFile : public SymbolicFile {
virtual void anchor();
ObjectFile() = delete;
@@ -194,22 +195,17 @@ protected:
// Implementations assume that the DataRefImpl is valid and has not been
// modified externally. It's UB otherwise.
friend class SymbolRef;
- virtual std::error_code getSymbolName(DataRefImpl Symb,
- StringRef &Res) const = 0;
+ virtual ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
std::error_code printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
virtual std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const = 0;
+ virtual uint64_t getSymbolValue(DataRefImpl Symb) const = 0;
virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
- virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
- virtual std::error_code getSymbolType(DataRefImpl Symb,
- SymbolRef::Type &Res) const = 0;
+ 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 std::error_code getSymbolOther(DataRefImpl Symb,
- uint8_t &Res) const {
- return object_error::invalid_file_type;
- }
// Same as above for SectionRef.
friend class SectionRef;
@@ -226,8 +222,6 @@ protected:
virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
// A section is 'virtual' if its contents aren't present in the object image.
virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
- virtual bool sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb) const = 0;
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
@@ -235,23 +229,19 @@ protected:
// Same as above for RelocationRef.
friend class RelocationRef;
virtual void moveRelocationNext(DataRefImpl &Rel) const = 0;
- virtual std::error_code getRelocationAddress(DataRefImpl Rel,
- uint64_t &Res) const = 0;
- virtual std::error_code getRelocationOffset(DataRefImpl Rel,
- uint64_t &Res) const = 0;
+ virtual ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const = 0;
+ virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0;
virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
- virtual std::error_code getRelocationType(DataRefImpl Rel,
- uint64_t &Res) const = 0;
- virtual std::error_code
- getRelocationTypeName(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const = 0;
- virtual std::error_code getRelocationHidden(DataRefImpl Rel,
- bool &Result) const {
- Result = false;
- return std::error_code();
- }
+ virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0;
+ virtual void getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const = 0;
public:
+ uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
+ assert(getSymbolFlags(Symb) & SymbolRef::SF_Common);
+ return getCommonSymbolSizeImpl(Symb);
+ }
+
typedef iterator_range<symbol_iterator> symbol_iterator_range;
symbol_iterator_range symbols() const {
return symbol_iterator_range(symbol_begin(), symbol_end());
@@ -314,32 +304,32 @@ public:
inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
: BasicSymbolRef(SymbolP, Owner) {}
-inline std::error_code SymbolRef::getName(StringRef &Result) const {
- return getObject()->getSymbolName(getRawDataRefImpl(), Result);
+inline ErrorOr<StringRef> SymbolRef::getName() const {
+ return getObject()->getSymbolName(getRawDataRefImpl());
}
inline std::error_code SymbolRef::getAddress(uint64_t &Result) const {
return getObject()->getSymbolAddress(getRawDataRefImpl(), Result);
}
+inline uint64_t SymbolRef::getValue() const {
+ return getObject()->getSymbolValue(getRawDataRefImpl());
+}
+
inline uint32_t SymbolRef::getAlignment() const {
return getObject()->getSymbolAlignment(getRawDataRefImpl());
}
-inline uint64_t SymbolRef::getSize() const {
- return getObject()->getSymbolSize(getRawDataRefImpl());
+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 std::error_code SymbolRef::getType(SymbolRef::Type &Result) const {
- return getObject()->getSymbolType(getRawDataRefImpl(), Result);
-}
-
-inline std::error_code SymbolRef::getOther(uint8_t &Result) const {
- return getObject()->getSymbolOther(getRawDataRefImpl(), Result);
+inline SymbolRef::Type SymbolRef::getType() const {
+ return getObject()->getSymbolType(getRawDataRefImpl());
}
inline const ObjectFile *SymbolRef::getObject() const {
@@ -406,11 +396,6 @@ inline bool SectionRef::isVirtual() const {
return OwningObject->isSectionVirtual(SectionPimpl);
}
-inline bool SectionRef::containsSymbol(SymbolRef S) const {
- return OwningObject->sectionContainsSymbol(SectionPimpl,
- S.getRawDataRefImpl());
-}
-
inline relocation_iterator SectionRef::relocation_begin() const {
return OwningObject->section_rel_begin(SectionPimpl);
}
@@ -445,36 +430,31 @@ inline void RelocationRef::moveNext() {
return OwningObject->moveRelocationNext(RelocationPimpl);
}
-inline std::error_code RelocationRef::getAddress(uint64_t &Result) const {
- return OwningObject->getRelocationAddress(RelocationPimpl, Result);
+inline ErrorOr<uint64_t> RelocationRef::getAddress() const {
+ return OwningObject->getRelocationAddress(RelocationPimpl);
}
-inline std::error_code RelocationRef::getOffset(uint64_t &Result) const {
- return OwningObject->getRelocationOffset(RelocationPimpl, Result);
+inline uint64_t RelocationRef::getOffset() const {
+ return OwningObject->getRelocationOffset(RelocationPimpl);
}
inline symbol_iterator RelocationRef::getSymbol() const {
return OwningObject->getRelocationSymbol(RelocationPimpl);
}
-inline std::error_code RelocationRef::getType(uint64_t &Result) const {
- return OwningObject->getRelocationType(RelocationPimpl, Result);
+inline uint64_t RelocationRef::getType() const {
+ return OwningObject->getRelocationType(RelocationPimpl);
}
-inline std::error_code
-RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
+inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
return OwningObject->getRelocationTypeName(RelocationPimpl, Result);
}
-inline std::error_code RelocationRef::getHidden(bool &Result) const {
- return OwningObject->getRelocationHidden(RelocationPimpl, Result);
-}
-
inline DataRefImpl RelocationRef::getRawDataRefImpl() const {
return RelocationPimpl;
}
-inline const ObjectFile *RelocationRef::getObjectFile() const {
+inline const ObjectFile *RelocationRef::getObject() const {
return OwningObject;
}
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index f80ee0a..950e2ed 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -240,16 +240,14 @@ private:
}
int64_t getELFAddend(RelocationRef R) {
- const auto *Obj = cast<ELFObjectFileBase>(R.getObjectFile());
- DataRefImpl DRI = R.getRawDataRefImpl();
- ErrorOr<int64_t> AddendOrErr = Obj->getRelocationAddend(DRI);
+ ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
if (std::error_code EC = AddendOrErr.getError())
report_fatal_error(EC.message());
return *AddendOrErr;
}
uint8_t getLengthMachO64(RelocationRef R) {
- const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObjectFile());
+ const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObject());
return Obj->getRelocationLength(R.getRawDataRefImpl());
}
@@ -267,8 +265,7 @@ private:
}
RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
- uint64_t Address;
- R.getOffset(Address);
+ uint64_t Address = R.getOffset();
return RelocToApply(Value - Address, 4);
}
@@ -282,8 +279,7 @@ private:
}
RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
int64_t Addend = getELFAddend(R);
- uint64_t Address;
- R.getOffset(Address);
+ uint64_t Address = R.getOffset();
return RelocToApply(Value + Addend - Address, 4);
}
RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
@@ -412,6 +408,6 @@ private:
}
};
-} // namespace object
-} // namespace llvm
+}
+}
#endif
diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h
new file mode 100644
index 0000000..276eab6
--- /dev/null
+++ b/include/llvm/Object/StackMapParser.h
@@ -0,0 +1,442 @@
+//===-------- StackMapParser.h - StackMap Parsing Support -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_STACKMAPPARSER_H
+#define LLVM_CODEGEN_STACKMAPPARSER_H
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+template <support::endianness Endianness>
+class StackMapV1Parser {
+public:
+
+ template <typename AccessorT>
+ class AccessorIterator {
+ public:
+
+ AccessorIterator(AccessorT A) : A(A) {}
+ AccessorIterator& operator++() { A = A.next(); return *this; }
+ AccessorIterator operator++(int) {
+ auto tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ bool operator==(const AccessorIterator &Other) {
+ return A.P == Other.A.P;
+ }
+
+ bool operator!=(const AccessorIterator &Other) { return !(*this == Other); }
+
+ AccessorT& operator*() { return A; }
+ AccessorT* operator->() { return &A; }
+
+ private:
+ AccessorT A;
+ };
+
+ /// Accessor for function records.
+ class FunctionAccessor {
+ friend class StackMapV1Parser;
+ public:
+
+ /// Get the function address.
+ uint64_t getFunctionAddress() const {
+ return read<uint64_t>(P);
+ }
+
+ /// Get the function's stack size.
+ uint32_t getStackSize() const {
+ return read<uint64_t>(P + sizeof(uint64_t));
+ }
+
+ private:
+ FunctionAccessor(const uint8_t *P) : P(P) {}
+
+ const static int FunctionAccessorSize = 2 * sizeof(uint64_t);
+
+ FunctionAccessor next() const {
+ return FunctionAccessor(P + FunctionAccessorSize);
+ }
+
+ const uint8_t *P;
+ };
+
+ /// Accessor for constants.
+ class ConstantAccessor {
+ friend class StackMapV1Parser;
+ public:
+
+ /// Return the value of this constant.
+ uint64_t getValue() const { return read<uint64_t>(P); }
+
+ private:
+
+ ConstantAccessor(const uint8_t *P) : P(P) {}
+
+ const static int ConstantAccessorSize = sizeof(uint64_t);
+
+ ConstantAccessor next() const {
+ return ConstantAccessor(P + ConstantAccessorSize);
+ }
+
+ const uint8_t *P;
+ };
+
+ // Forward-declare RecordAccessor so we can friend it below.
+ class RecordAccessor;
+
+ enum class LocationKind : uint8_t {
+ Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5
+ };
+
+
+ /// Accessor for location records.
+ class LocationAccessor {
+ friend class StackMapV1Parser;
+ friend class RecordAccessor;
+ public:
+
+ /// Get the Kind for this location.
+ LocationKind getKind() const {
+ return LocationKind(P[KindOffset]);
+ }
+
+ /// Get the Dwarf register number for this location.
+ uint16_t getDwarfRegNum() const {
+ return read<uint16_t>(P + DwarfRegNumOffset);
+ }
+
+ /// Get the small-constant for this location. (Kind must be Constant).
+ uint32_t getSmallConstant() const {
+ assert(getKind() == LocationKind::Constant && "Not a small constant.");
+ return read<uint32_t>(P + SmallConstantOffset);
+ }
+
+ /// Get the constant-index for this location. (Kind must be ConstantIndex).
+ uint32_t getConstantIndex() const {
+ assert(getKind() == LocationKind::ConstantIndex &&
+ "Not a constant-index.");
+ return read<uint32_t>(P + SmallConstantOffset);
+ }
+
+ /// Get the offset for this location. (Kind must be Direct or Indirect).
+ int32_t getOffset() const {
+ assert((getKind() == LocationKind::Direct ||
+ getKind() == LocationKind::Indirect) &&
+ "Not direct or indirect.");
+ return read<int32_t>(P + SmallConstantOffset);
+ }
+
+ private:
+
+ LocationAccessor(const uint8_t *P) : P(P) {}
+
+ LocationAccessor next() const {
+ return LocationAccessor(P + LocationAccessorSize);
+ }
+
+ static const int KindOffset = 0;
+ static const int DwarfRegNumOffset = KindOffset + sizeof(uint16_t);
+ static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint16_t);
+ static const int LocationAccessorSize = sizeof(uint64_t);
+
+ const uint8_t *P;
+ };
+
+ /// Accessor for stackmap live-out fields.
+ class LiveOutAccessor {
+ friend class StackMapV1Parser;
+ friend class RecordAccessor;
+ public:
+
+ /// Get the Dwarf register number for this live-out.
+ uint16_t getDwarfRegNum() const {
+ return read<uint16_t>(P + DwarfRegNumOffset);
+ }
+
+ /// Get the size in bytes of live [sub]register.
+ unsigned getSizeInBytes() const {
+ return read<uint8_t>(P + SizeOffset);
+ }
+
+ private:
+
+ LiveOutAccessor(const uint8_t *P) : P(P) {}
+
+ LiveOutAccessor next() const {
+ return LiveOutAccessor(P + LiveOutAccessorSize);
+ }
+
+ static const int DwarfRegNumOffset = 0;
+ static const int SizeOffset =
+ DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t);
+ static const int LiveOutAccessorSize = sizeof(uint32_t);
+
+ const uint8_t *P;
+ };
+
+ /// Accessor for stackmap records.
+ class RecordAccessor {
+ friend class StackMapV1Parser;
+ public:
+
+ typedef AccessorIterator<LocationAccessor> location_iterator;
+ typedef AccessorIterator<LiveOutAccessor> liveout_iterator;
+
+ /// Get the patchpoint/stackmap ID for this record.
+ uint64_t getID() const {
+ return read<uint64_t>(P + PatchpointIDOffset);
+ }
+
+ /// Get the instruction offset (from the start of the containing function)
+ /// for this record.
+ uint32_t getInstructionOffset() const {
+ return read<uint32_t>(P + InstructionOffsetOffset);
+ }
+
+ /// Get the number of locations contained in this record.
+ uint16_t getNumLocations() const {
+ return read<uint16_t>(P + NumLocationsOffset);
+ }
+
+ /// Get the location with the given index.
+ LocationAccessor getLocation(unsigned LocationIndex) const {
+ unsigned LocationOffset =
+ LocationListOffset + LocationIndex * LocationSize;
+ return LocationAccessor(P + LocationOffset);
+ }
+
+ /// Begin iterator for locations.
+ location_iterator location_begin() const {
+ return location_iterator(getLocation(0));
+ }
+
+ /// End iterator for locations.
+ location_iterator location_end() const {
+ return location_iterator(getLocation(getNumLocations()));
+ }
+
+ /// Iterator range for locations.
+ iterator_range<location_iterator> locations() const {
+ return make_range(location_begin(), location_end());
+ }
+
+ /// Get the number of liveouts contained in this record.
+ uint16_t getNumLiveOuts() const {
+ return read<uint16_t>(P + getNumLiveOutsOffset());
+ }
+
+ /// Get the live-out with the given index.
+ LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const {
+ unsigned LiveOutOffset =
+ getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize;
+ return LiveOutAccessor(P + LiveOutOffset);
+ }
+
+ /// Begin iterator for live-outs.
+ liveout_iterator liveouts_begin() const {
+ return liveout_iterator(getLiveOut(0));
+ }
+
+
+ /// End iterator for live-outs.
+ liveout_iterator liveouts_end() const {
+ return liveout_iterator(getLiveOut(getNumLiveOuts()));
+ }
+
+ /// Iterator range for live-outs.
+ iterator_range<liveout_iterator> liveouts() const {
+ return make_range(liveouts_begin(), liveouts_end());
+ }
+
+ private:
+
+ RecordAccessor(const uint8_t *P) : P(P) {}
+
+ unsigned getNumLiveOutsOffset() const {
+ return LocationListOffset + LocationSize * getNumLocations() +
+ sizeof(uint16_t);
+ }
+
+ unsigned getSizeInBytes() const {
+ unsigned RecordSize =
+ getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize;
+ return (RecordSize + 7) & ~0x7;
+ }
+
+ RecordAccessor next() const {
+ return RecordAccessor(P + getSizeInBytes());
+ }
+
+ static const unsigned PatchpointIDOffset = 0;
+ static const unsigned InstructionOffsetOffset =
+ PatchpointIDOffset + sizeof(uint64_t);
+ static const unsigned NumLocationsOffset =
+ InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
+ static const unsigned LocationListOffset =
+ NumLocationsOffset + sizeof(uint16_t);
+ static const unsigned LocationSize = sizeof(uint64_t);
+ static const unsigned LiveOutSize = sizeof(uint32_t);
+
+ const uint8_t *P;
+ };
+
+ /// Construct a parser for a version-1 stackmap. StackMap data will be read
+ /// from the given array.
+ StackMapV1Parser(ArrayRef<uint8_t> StackMapSection)
+ : StackMapSection(StackMapSection) {
+ ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
+
+ assert(StackMapSection[0] == 1 &&
+ "StackMapV1Parser can only parse version 1 stackmaps");
+
+ unsigned CurrentRecordOffset =
+ ConstantsListOffset + getNumConstants() * ConstantSize;
+
+ for (unsigned I = 0, E = getNumRecords(); I != E; ++I) {
+ StackMapRecordOffsets.push_back(CurrentRecordOffset);
+ CurrentRecordOffset +=
+ RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes();
+ }
+ }
+
+ typedef AccessorIterator<FunctionAccessor> function_iterator;
+ typedef AccessorIterator<ConstantAccessor> constant_iterator;
+ typedef AccessorIterator<RecordAccessor> record_iterator;
+
+ /// Get the version number of this stackmap. (Always returns 1).
+ unsigned getVersion() const { return 1; }
+
+ /// Get the number of functions in the stack map.
+ uint32_t getNumFunctions() const {
+ return read<uint32_t>(&StackMapSection[NumFunctionsOffset]);
+ }
+
+ /// Get the number of large constants in the stack map.
+ uint32_t getNumConstants() const {
+ return read<uint32_t>(&StackMapSection[NumConstantsOffset]);
+ }
+
+ /// Get the number of stackmap records in the stackmap.
+ uint32_t getNumRecords() const {
+ return read<uint32_t>(&StackMapSection[NumRecordsOffset]);
+ }
+
+ /// Return an FunctionAccessor for the given function index.
+ FunctionAccessor getFunction(unsigned FunctionIndex) const {
+ return FunctionAccessor(StackMapSection.data() +
+ getFunctionOffset(FunctionIndex));
+ }
+
+ /// Begin iterator for functions.
+ function_iterator functions_begin() const {
+ return function_iterator(getFunction(0));
+ }
+
+ /// End iterator for functions.
+ function_iterator functions_end() const {
+ return function_iterator(
+ FunctionAccessor(StackMapSection.data() +
+ getFunctionOffset(getNumFunctions())));
+ }
+
+ /// Iterator range for functions.
+ iterator_range<function_iterator> functions() const {
+ return make_range(functions_begin(), functions_end());
+ }
+
+ /// Return the large constant at the given index.
+ ConstantAccessor getConstant(unsigned ConstantIndex) const {
+ return ConstantAccessor(StackMapSection.data() +
+ getConstantOffset(ConstantIndex));
+ }
+
+ /// Begin iterator for constants.
+ constant_iterator constants_begin() const {
+ return constant_iterator(getConstant(0));
+ }
+
+ /// End iterator for constants.
+ constant_iterator constants_end() const {
+ return constant_iterator(
+ ConstantAccessor(StackMapSection.data() +
+ getConstantOffset(getNumConstants())));
+ }
+
+ /// Iterator range for constants.
+ iterator_range<constant_iterator> constants() const {
+ return make_range(constants_begin(), constants_end());
+ }
+
+ /// Return a RecordAccessor for the given record index.
+ RecordAccessor getRecord(unsigned RecordIndex) const {
+ std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex];
+ return RecordAccessor(StackMapSection.data() + RecordOffset);
+ }
+
+ /// Begin iterator for records.
+ record_iterator records_begin() const {
+ if (getNumRecords() == 0)
+ return record_iterator(RecordAccessor(nullptr));
+ return record_iterator(getRecord(0));
+ }
+
+ /// End iterator for records.
+ record_iterator records_end() const {
+ // Records need to be handled specially, since we cache the start addresses
+ // for them: We can't just compute the 1-past-the-end address, we have to
+ // look at the last record and use the 'next' method.
+ if (getNumRecords() == 0)
+ return record_iterator(RecordAccessor(nullptr));
+ return record_iterator(getRecord(getNumRecords() - 1).next());
+ }
+
+ /// Iterator range for records.
+ iterator_range<record_iterator> records() const {
+ return make_range(records_begin(), records_end());
+ }
+
+private:
+
+ template <typename T>
+ static T read(const uint8_t *P) {
+ return support::endian::read<T, Endianness, 1>(P);
+ }
+
+ static const unsigned HeaderOffset = 0;
+ static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t);
+ static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t);
+ static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
+ static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
+
+ static const unsigned FunctionSize = 2 * sizeof(uint64_t);
+ static const unsigned ConstantSize = sizeof(uint64_t);
+
+ std::size_t getFunctionOffset(unsigned FunctionIndex) const {
+ return FunctionListOffset + FunctionIndex * FunctionSize;
+ }
+
+ std::size_t getConstantOffset(unsigned ConstantIndex) const {
+ return ConstantsListOffset + ConstantIndex * ConstantSize;
+ }
+
+ ArrayRef<uint8_t> StackMapSection;
+ unsigned ConstantsListOffset;
+ std::vector<unsigned> StackMapRecordOffsets;
+};
+
+}
+
+#endif
diff --git a/include/llvm/Object/SymbolSize.h b/include/llvm/Object/SymbolSize.h
new file mode 100644
index 0000000..f2ce70f
--- /dev/null
+++ b/include/llvm/Object/SymbolSize.h
@@ -0,0 +1,23 @@
+//===- SymbolSize.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_SYMBOLSIZE_H
+#define LLVM_OBJECT_SYMBOLSIZE_H
+
+#include "llvm/Object/ObjectFile.h"
+
+namespace llvm {
+namespace object {
+std::vector<std::pair<SymbolRef, uint64_t>>
+computeSymbolSizes(const ObjectFile &O);
+}
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index bf46599..3a38231 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -115,7 +115,7 @@ public:
typedef content_iterator<BasicSymbolRef> basic_symbol_iterator;
-const uint64_t UnknownAddressOrSize = ~0ULL;
+const uint64_t UnknownAddress = ~0ULL;
class SymbolicFile : public Binary {
public:
@@ -195,7 +195,7 @@ inline const SymbolicFile *BasicSymbolRef::getObject() const {
return OwningObject;
}
-} // namespace object
-} // namespace llvm
+}
+}
#endif
OpenPOWER on IntegriCloud