aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/Object/ELF.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object/ELF.h')
-rw-r--r--include/llvm/Object/ELF.h112
1 files changed, 63 insertions, 49 deletions
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 824e06e..ee97d4e 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -60,12 +60,12 @@ public:
public:
typedef ptrdiff_t difference_type;
typedef EntT value_type;
- typedef std::random_access_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef value_type &reference;
typedef value_type *pointer;
/// \brief Default construct iterator.
- ELFEntityIterator() : EntitySize(0), Current(0) {}
+ ELFEntityIterator() : EntitySize(0), Current(nullptr) {}
ELFEntityIterator(uintX_t EntSize, const char *Start)
: EntitySize(EntSize), Current(Start) {}
@@ -136,6 +136,7 @@ public:
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;
/// \brief Archive files are 2 byte aligned, so we need this for
/// PointerIntPair to work.
@@ -249,7 +250,7 @@ private:
/// \brief Represents a region described by entries in the .dynamic table.
struct DynRegionInfo {
- DynRegionInfo() : Addr(0), Size(0), EntSize(0) {}
+ DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
/// \brief Address in current address space.
const void *Addr;
/// \brief Size in bytes of the region.
@@ -273,19 +274,19 @@ private:
public:
// If the integer is 0, this is an Elf_Verdef*.
// If the integer is 1, this is an Elf_Vernaux*.
- VersionMapEntry() : PointerIntPair<const void*, 1>(NULL, 0) { }
+ VersionMapEntry() : PointerIntPair<const void*, 1>(nullptr, 0) { }
VersionMapEntry(const Elf_Verdef *verdef)
: PointerIntPair<const void*, 1>(verdef, 0) { }
VersionMapEntry(const Elf_Vernaux *vernaux)
: PointerIntPair<const void*, 1>(vernaux, 1) { }
- bool isNull() const { return getPointer() == NULL; }
+ bool isNull() const { return getPointer() == nullptr; }
bool isVerdef() const { return !isNull() && getInt() == 0; }
bool isVernaux() const { return !isNull() && getInt() == 1; }
const Elf_Verdef *getVerdef() const {
- return isVerdef() ? (const Elf_Verdef*)getPointer() : NULL;
+ return isVerdef() ? (const Elf_Verdef*)getPointer() : nullptr;
}
const Elf_Vernaux *getVernaux() const {
- return isVernaux() ? (const Elf_Vernaux*)getPointer() : NULL;
+ return isVernaux() ? (const Elf_Vernaux*)getPointer() : nullptr;
}
};
mutable SmallVector<VersionMapEntry, 16> VersionMap;
@@ -317,6 +318,11 @@ public:
ELFFile(MemoryBuffer *Object, error_code &ec);
+ bool isMipsELF64() const {
+ return Header->e_machine == ELF::EM_MIPS &&
+ Header->getFileClass() == ELF::ELFCLASS64;
+ }
+
bool isMips64EL() const {
return Header->e_machine == ELF::EM_MIPS &&
Header->getFileClass() == ELF::ELFCLASS64 &&
@@ -325,6 +331,9 @@ public:
Elf_Shdr_Iter begin_sections() const;
Elf_Shdr_Iter end_sections() const;
+ Elf_Shdr_Range sections() const {
+ return make_range(begin_sections(), end_sections());
+ }
Elf_Sym_Iter begin_symbols() const;
Elf_Sym_Iter end_symbols() const;
@@ -338,7 +347,7 @@ public:
if (DynSymRegion.Addr)
return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr,
true);
- return Elf_Sym_Iter(0, 0, true);
+ return Elf_Sym_Iter(0, nullptr, true);
}
Elf_Sym_Iter end_dynamic_symbols() const {
@@ -346,7 +355,7 @@ public:
return Elf_Sym_Iter(DynSymRegion.EntSize,
(const char *)DynSymRegion.Addr + DynSymRegion.Size,
true);
- return Elf_Sym_Iter(0, 0, true);
+ return Elf_Sym_Iter(0, nullptr, true);
}
Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const {
@@ -478,7 +487,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 == NULL || dot_gnu_version_sec == NULL)
+ if (!DynSymRegion.Addr || !dot_gnu_version_sec)
return;
// Has the VersionMap already been loaded?
@@ -510,7 +519,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym *symb) const {
if (symb->st_shndx == ELF::SHN_XINDEX)
return getSection(ExtendedSymbolTable.lookup(symb));
if (symb->st_shndx >= ELF::SHN_LORESERVE)
- return 0;
+ return nullptr;
return getSection(symb->st_shndx);
}
@@ -537,10 +546,16 @@ StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
template <class ELFT>
void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
SmallVectorImpl<char> &Result) const {
- if (!isMips64EL()) {
+ if (!isMipsELF64()) {
StringRef Name = getRelocationTypeName(Type);
Result.append(Name.begin(), Name.end());
} else {
+ // The Mips N64 ABI allows up to three operations to be specified per
+ // relocation record. Unfortunately there's no easy way to test for the
+ // presence of N64 ELFs as they have no special flag that identifies them
+ // as being N64. We can safely assume at the moment that all Mips
+ // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough
+ // information to disambiguate between old vs new ABIs.
uint8_t Type1 = (Type >> 0) & 0xFF;
uint8_t Type2 = (Type >> 8) & 0xFF;
uint8_t Type3 = (Type >> 16) & 0xFF;
@@ -565,7 +580,7 @@ std::pair<const typename ELFFile<ELFT>::Elf_Shdr *,
const typename ELFFile<ELFT>::Elf_Sym *>
ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const {
if (!Sec->sh_link)
- return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0);
+ return std::make_pair(nullptr, nullptr);
const Elf_Shdr *SymTable = getSection(Sec->sh_link);
return std::make_pair(
SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL())));
@@ -604,15 +619,15 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const {
template <class ELFT>
ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec)
: Buf(Object),
- SectionHeaderTable(0),
- dot_shstrtab_sec(0),
- dot_strtab_sec(0),
- dot_symtab_sec(0),
- SymbolTableSectionHeaderIndex(0),
- dot_gnu_version_sec(0),
- dot_gnu_version_r_sec(0),
- dot_gnu_version_d_sec(0),
- dt_soname(0) {
+ 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) {
const uint64_t FileSize = Buf->getBufferSize();
if (sizeof(Elf_Ehdr) > FileSize)
@@ -641,30 +656,29 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec)
// Scan sections for special sections.
- for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections();
- SecI != SecE; ++SecI) {
- switch (SecI->sh_type) {
+ for (const Elf_Shdr &Sec : sections()) {
+ switch (Sec.sh_type) {
case ELF::SHT_SYMTAB_SHNDX:
if (SymbolTableSectionHeaderIndex)
// FIXME: Proper error handling.
report_fatal_error("More than one .symtab_shndx!");
- SymbolTableSectionHeaderIndex = &*SecI;
+ SymbolTableSectionHeaderIndex = &Sec;
break;
case ELF::SHT_SYMTAB:
if (dot_symtab_sec)
// FIXME: Proper error handling.
report_fatal_error("More than one .symtab!");
- dot_symtab_sec = &*SecI;
- dot_strtab_sec = getSection(SecI->sh_link);
+ dot_symtab_sec = &Sec;
+ dot_strtab_sec = getSection(Sec.sh_link);
break;
case ELF::SHT_DYNSYM: {
if (DynSymRegion.Addr)
// FIXME: Proper error handling.
report_fatal_error("More than one .dynsym!");
- DynSymRegion.Addr = base() + SecI->sh_offset;
- DynSymRegion.Size = SecI->sh_size;
- DynSymRegion.EntSize = SecI->sh_entsize;
- const Elf_Shdr *DynStr = getSection(SecI->sh_link);
+ 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;
@@ -674,27 +688,27 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec)
if (DynamicRegion.Addr)
// FIXME: Proper error handling.
report_fatal_error("More than one .dynamic!");
- DynamicRegion.Addr = base() + SecI->sh_offset;
- DynamicRegion.Size = SecI->sh_size;
- DynamicRegion.EntSize = SecI->sh_entsize;
+ DynamicRegion.Addr = base() + Sec.sh_offset;
+ DynamicRegion.Size = Sec.sh_size;
+ DynamicRegion.EntSize = Sec.sh_entsize;
break;
case ELF::SHT_GNU_versym:
- if (dot_gnu_version_sec != NULL)
+ if (dot_gnu_version_sec != nullptr)
// FIXME: Proper error handling.
report_fatal_error("More than one .gnu.version section!");
- dot_gnu_version_sec = &*SecI;
+ dot_gnu_version_sec = &Sec;
break;
case ELF::SHT_GNU_verdef:
- if (dot_gnu_version_d_sec != NULL)
+ if (dot_gnu_version_d_sec != nullptr)
// FIXME: Proper error handling.
report_fatal_error("More than one .gnu.version_d section!");
- dot_gnu_version_d_sec = &*SecI;
+ dot_gnu_version_d_sec = &Sec;
break;
case ELF::SHT_GNU_verneed:
- if (dot_gnu_version_r_sec != NULL)
+ if (dot_gnu_version_r_sec != nullptr)
// FIXME: Proper error handling.
report_fatal_error("More than one .gnu.version_r section!");
- dot_gnu_version_r_sec = &*SecI;
+ dot_gnu_version_r_sec = &Sec;
break;
}
}
@@ -761,7 +775,7 @@ typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::end_sections() const {
template <class ELFT>
typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const {
if (!dot_symtab_sec)
- return Elf_Sym_Iter(0, 0, false);
+ 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);
}
@@ -769,7 +783,7 @@ typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const {
template <class ELFT>
typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::end_symbols() const {
if (!dot_symtab_sec)
- return Elf_Sym_Iter(0, 0, false);
+ 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,
@@ -782,14 +796,14 @@ ELFFile<ELFT>::begin_dynamic_table() const {
if (DynamicRegion.Addr)
return Elf_Dyn_Iter(DynamicRegion.EntSize,
(const char *)DynamicRegion.Addr);
- return Elf_Dyn_Iter(0, 0);
+ return Elf_Dyn_Iter(0, nullptr);
}
template <class ELFT>
typename ELFFile<ELFT>::Elf_Dyn_Iter
ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const {
if (!DynamicRegion.Addr)
- return Elf_Dyn_Iter(0, 0);
+ return Elf_Dyn_Iter(0, nullptr);
Elf_Dyn_Iter Ret(DynamicRegion.EntSize,
(const char *)DynamicRegion.Addr + DynamicRegion.Size);
@@ -842,7 +856,7 @@ template <class ELFT>
const typename ELFFile<ELFT>::Elf_Shdr *
ELFFile<ELFT>::getSection(uint32_t index) const {
if (index == 0)
- return 0;
+ return nullptr;
if (!SectionHeaderTable || index >= getNumSections())
// FIXME: Proper error handling.
report_fatal_error("Invalid section index!");
@@ -871,7 +885,7 @@ const char *ELFFile<ELFT>::getString(const Elf_Shdr *section,
template <class ELFT>
const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const {
if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size)
- return 0;
+ return nullptr;
return (const char *)DynStrRegion.Addr + Offset;
}
@@ -913,7 +927,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
const Elf_Sym *symb,
bool &IsDefault) const {
// Handle non-dynamic symbols.
- if (section != DynSymRegion.Addr && section != 0) {
+ if (section != DynSymRegion.Addr && 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.
@@ -937,7 +951,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
}
// This is a dynamic symbol. Look in the GNU symbol version table.
- if (dot_gnu_version_sec == NULL) {
+ if (!dot_gnu_version_sec) {
// No version table.
IsDefault = false;
return StringRef("");