return *this;
}
+ ELFEntityIterator &operator+(difference_type n) {
+ assert(Current && "Attempted to increment an invalid iterator!");
+ Current += (n * EntitySize);
+ return *this;
+ }
+
+ ELFEntityIterator &operator-(difference_type n) {
+ assert(Current && "Attempted to subtract an invalid iterator!");
+ Current -= (n * EntitySize);
+ return *this;
+ }
+
ELFEntityIterator operator ++(int) {
ELFEntityIterator Tmp = *this;
++*this;
return Tmp;
}
- ELFEntityIterator &operator =(const ELFEntityIterator &Other) {
- EntitySize = Other.EntitySize;
- Current = Other.Current;
- return *this;
- }
-
difference_type operator -(const ELFEntityIterator &Other) const {
assert(EntitySize == Other.EntitySize &&
"Subtracting iterators of different EntitySize!");
return *this;
}
- Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) {
- EntitySize = Other.EntitySize;
- Current = Other.Current;
- return *this;
- }
-
difference_type operator-(const Elf_Sym_Iter &Other) const {
assert(EntitySize == Other.EntitySize &&
"Subtracting iterators of different EntitySize!");
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.
std::pair<const Elf_Shdr *, const Elf_Sym *>
getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const;
- ELFFile(StringRef Object, std::error_code &ec);
+ ELFFile(StringRef Object, std::error_code &EC);
bool isMipsELF64() const {
return Header->e_machine == ELF::EM_MIPS &&
return Elf_Sym_Iter(0, nullptr, true);
}
+ Elf_Rela_Iter begin_dyn_rela() const {
+ if (DynRelaRegion.Addr)
+ return Elf_Rela_Iter(DynRelaRegion.EntSize,
+ (const char *)DynRelaRegion.Addr);
+ return Elf_Rela_Iter(0, nullptr);
+ }
+
+ Elf_Rela_Iter end_dyn_rela() 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 begin_rela(const Elf_Shdr *sec) const {
return Elf_Rela_Iter(sec->sh_entsize,
(const char *)(base() + sec->sh_offset));
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;
StringRef getLoadName() const;
};
-// Use an alignment of 2 for the typedefs since that is the worst case for
-// ELF files in archives.
-typedef ELFFile<ELFType<support::little, 2, false> > ELF32LEFile;
-typedef ELFFile<ELFType<support::little, 2, true> > ELF64LEFile;
-typedef ELFFile<ELFType<support::big, 2, false> > ELF32BEFile;
-typedef ELFFile<ELFType<support::big, 2, true> > ELF64BEFile;
+typedef ELFFile<ELFType<support::little, false>> ELF32LEFile;
+typedef ELFFile<ELFType<support::little, true>> ELF64LEFile;
+typedef ELFFile<ELFType<support::big, false>> ELF32BEFile;
+typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
// Iterate through the version definitions, and place each Elf_Verdef
// in the VersionMap according to its index.
}
template <class ELFT>
-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>
}
template <class ELFT>
-ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec)
+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),
dt_soname(nullptr) {
const uint64_t FileSize = Buf.size();
- if (sizeof(Elf_Ehdr) > FileSize)
- // FIXME: Proper error handling.
- report_fatal_error("File too short!");
+ if (sizeof(Elf_Ehdr) > FileSize) {
+ // File too short!
+ EC = object_error::parse_failed;
+ return;
+ }
Header = reinterpret_cast<const Elf_Ehdr *>(base());
const uint64_t SectionTableOffset = Header->e_shoff;
- if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
- // FIXME: Proper error handling.
- report_fatal_error("Section header table goes past end of file!");
+ if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) {
+ // Section header table goes past end of file!
+ EC = object_error::parse_failed;
+ return;
+ }
// The getNumSections() call below depends on SectionHeaderTable being set.
SectionHeaderTable =
reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize;
- if (SectionTableOffset + SectionTableSize > FileSize)
- // FIXME: Proper error handling.
- report_fatal_error("Section table goes past end of file!");
+ if (SectionTableOffset + SectionTableSize > FileSize) {
+ // Section table goes past end of file!
+ EC = object_error::parse_failed;
+ return;
+ }
// Scan sections for special sections.
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!");
+ if (SymbolTableSectionHeaderIndex) {
+ // More than one .symtab_shndx!
+ EC = object_error::parse_failed;
+ return;
+ }
SymbolTableSectionHeaderIndex = &Sec;
break;
case ELF::SHT_SYMTAB:
- if (dot_symtab_sec)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .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;
case ELF::SHT_DYNSYM: {
- if (DynSymRegion.Addr)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .dynsym!");
+ if (DynSymRegion.Addr) {
+ // 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;
break;
}
case ELF::SHT_DYNAMIC:
- if (DynamicRegion.Addr)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .dynamic!");
+ if (DynamicRegion.Addr) {
+ // More than one .dynamic!
+ EC = object_error::parse_failed;
+ return;
+ }
DynamicRegion.Addr = base() + Sec.sh_offset;
DynamicRegion.Size = Sec.sh_size;
DynamicRegion.EntSize = Sec.sh_entsize;
break;
case ELF::SHT_GNU_versym:
- if (dot_gnu_version_sec != nullptr)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .gnu.version section!");
+ if (dot_gnu_version_sec != nullptr) {
+ // More than one .gnu.version section!
+ EC = object_error::parse_failed;
+ return;
+ }
dot_gnu_version_sec = &Sec;
break;
case ELF::SHT_GNU_verdef:
- if (dot_gnu_version_d_sec != nullptr)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .gnu.version_d section!");
+ if (dot_gnu_version_d_sec != nullptr) {
+ // More than one .gnu.version_d section!
+ EC = object_error::parse_failed;
+ return;
+ }
dot_gnu_version_d_sec = &Sec;
break;
case ELF::SHT_GNU_verneed:
- if (dot_gnu_version_r_sec != nullptr)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .gnu.version_r section!");
+ if (dot_gnu_version_r_sec != nullptr) {
+ // More than one .gnu.version_r section!
+ EC = object_error::parse_failed;
+ return;
+ }
dot_gnu_version_r_sec = &Sec;
break;
}
}
}
- ec = std::error_code();
+ // Scan dynamic table.
+ for (Elf_Dyn_Iter DynI = begin_dynamic_table(), DynE = end_dynamic_table();
+ 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 = begin_program_headers(),
+ PhdrE = end_program_headers();
+ 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();
+ }
+ }
+
+ EC = std::error_code();
}
// Get the symbol table index in the symtab section given a symbol
template <class ELFT>
ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section,
const Elf_Sym *Symb) const {
- if (Symb->st_name == 0) {
- const Elf_Shdr *ContainingSec = getSection(Symb);
- if (ContainingSec)
- return getSectionName(ContainingSec);
- }
+ if (Symb->st_name == 0)
+ return StringRef("");
const Elf_Shdr *StrTab = getSection(Section->sh_link);
if (Symb->st_name >= StrTab->sh_size)