//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file declares the ELFObjectFile template class. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_ELFOBJECTFILE_H #define LLVM_OBJECT_ELFOBJECTFILE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include #include #include #include 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); virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; virtual ErrorOr getRelocationAddend(DataRefImpl Rel) const = 0; public: typedef iterator_range 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(SectionRef::getObject())); } const ELFObjectFileBase *getObject() const { return cast(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(B->getObject())); } const ELFSectionRef *operator->() const { return static_cast(section_iterator::operator->()); } const ELFSectionRef &operator*() const { return static_cast(section_iterator::operator*()); } }; class ELFSymbolRef : public SymbolRef { public: ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) { assert(isa(SymbolRef::getObject())); } const ELFObjectFileBase *getObject() const { return cast(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(B->getObject()))) {} const ELFSymbolRef *operator->() const { return static_cast(symbol_iterator::operator->()); } const ELFSymbolRef &operator*() const { return static_cast(symbol_iterator::operator*()); } }; class ELFRelocationRef : public RelocationRef { public: ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) { assert(isa(RelocationRef::getObject())); } const ELFObjectFileBase *getObject() const { return cast(RelocationRef::getObject()); } ErrorOr 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(B->getObject()))) {} const ELFRelocationRef *operator->() const { return static_cast( relocation_iterator::operator->()); } const ELFRelocationRef &operator*() const { return static_cast( relocation_iterator::operator*()); } }; inline ELFObjectFileBase::elf_symbol_iterator_range ELFObjectFileBase::symbols() const { return elf_symbol_iterator_range(symbol_begin(), symbol_end()); } template class ELFObjectFile : public ELFObjectFileBase { uint64_t getSymbolSize(DataRefImpl Sym) const override; public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) typedef typename ELFFile::uintX_t uintX_t; typedef typename ELFFile::Elf_Sym Elf_Sym; typedef typename ELFFile::Elf_Shdr Elf_Shdr; typedef typename ELFFile::Elf_Ehdr Elf_Ehdr; typedef typename ELFFile::Elf_Rel Elf_Rel; typedef typename ELFFile::Elf_Rela Elf_Rela; typedef typename ELFFile::Elf_Dyn Elf_Dyn; typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; protected: ELFFile EF; void moveSymbolNext(DataRefImpl &Symb) const override; ErrorOr getSymbolName(DataRefImpl Symb) const override; ErrorOr getSymbolAddress(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) 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; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; section_iterator getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; uint64_t getRelocationType(DataRefImpl Rel) const override; void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const override; uint32_t getSectionType(DataRefImpl Sec) const override; uint64_t getSectionFlags(DataRefImpl Sec) const override; 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); } const Elf_Sym *toELFSymIter(DataRefImpl Sym) const { return EF.template getEntry(Sym.d.a, Sym.d.b); } DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { DataRefImpl 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); uintptr_t SHT = reinterpret_cast(EF.section_begin()); unsigned SymTableIndex = (reinterpret_cast(SymTable) - SHT) / sizeof(Elf_Shdr); DRI.d.a = SymTableIndex; DRI.d.b = SymbolNum; return DRI; } const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { return reinterpret_cast(Sec.p); } DataRefImpl toDRI(const Elf_Shdr *Sec) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Sec); return DRI; } DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Dyn.get()); return DRI; } bool isExportedToOtherDSO(const Elf_Sym *ESym) const { unsigned char Binding = ESym->getBinding(); unsigned char Visibility = ESym->getVisibility(); // A symbol is exported if its binding is either GLOBAL or WEAK, and its // visibility is either DEFAULT or PROTECTED. All other symbols are not // exported. if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)) return true; return false; } // This flag is used for classof, to distinguish ELFObjectFile from // its subclass. If more subclasses will be created, this flag will // have to become an enum. bool isDyldELFObject; 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; 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 getRelocationAddend(DataRefImpl Rel) const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; StringRef getLoadName() const; std::error_code getPlatformFlags(unsigned &Result) const override { Result = EF.getHeader()->e_flags; return std::error_code(); } const ELFFile *getELFFile() const { return &EF; } bool isDyldType() const { return isDyldELFObject; } static inline bool classof(const Binary *v) { return v->getType() == getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits); } elf_symbol_iterator_range getDynamicSymbolIterators() const override; bool isRelocatableObject() const override; }; typedef ELFObjectFile> ELF32LEObjectFile; typedef ELFObjectFile> ELF64LEObjectFile; typedef ELFObjectFile> ELF32BEObjectFile; typedef ELFObjectFile> ELF64BEObjectFile; template void ELFObjectFile::moveSymbolNext(DataRefImpl &Sym) const { ++Sym.d.b; } template ErrorOr ELFObjectFile::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 uint64_t ELFObjectFile::getSectionFlags(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_flags; } template uint32_t ELFObjectFile::getSectionType(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_type; } template uint64_t ELFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); uint64_t Ret = ESym->st_value; if (ESym->st_shndx == ELF::SHN_ABS) return Ret; const Elf_Ehdr *Header = EF.getHeader(); // 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) Ret &= ~1; return Ret; } template ErrorOr ELFObjectFile::getSymbolAddress(DataRefImpl Symb) const { uint64_t 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 Result; } const Elf_Ehdr *Header = EF.getHeader(); if (Header->e_type == ELF::ET_REL) { ErrorOr SectionOrErr = EF.getSection(ESym); if (std::error_code EC = SectionOrErr.getError()) return EC; const Elf_Shdr *Section = *SectionOrErr; if (Section) Result += Section->sh_addr; } return Result; } template uint32_t ELFObjectFile::getSymbolAlignment(DataRefImpl Symb) const { const Elf_Sym *Sym = toELFSymIter(Symb); if (Sym->st_shndx == ELF::SHN_COMMON) return Sym->st_value; return 0; } template uint64_t ELFObjectFile::getSymbolSize(DataRefImpl Sym) const { return toELFSymIter(Sym)->st_size; } template uint64_t ELFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { return toELFSymIter(Symb)->st_size; } template uint8_t ELFObjectFile::getSymbolOther(DataRefImpl Symb) const { return toELFSymIter(Symb)->st_other; } template uint8_t ELFObjectFile::getSymbolELFType(DataRefImpl Symb) const { return toELFSymIter(Symb)->getType(); } template SymbolRef::Type ELFObjectFile::getSymbolType(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { case ELF::STT_NOTYPE: return SymbolRef::ST_Unknown; case ELF::STT_SECTION: return SymbolRef::ST_Debug; case ELF::STT_FILE: return SymbolRef::ST_File; case ELF::STT_FUNC: return SymbolRef::ST_Function; case ELF::STT_OBJECT: case ELF::STT_COMMON: case ELF::STT_TLS: return SymbolRef::ST_Data; default: return SymbolRef::ST_Other; } } template uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { const Elf_Sym *ESym = toELFSymIter(Sym); uint32_t Result = SymbolRef::SF_None; if (ESym->getBinding() != ELF::STB_LOCAL) Result |= SymbolRef::SF_Global; if (ESym->getBinding() == ELF::STB_WEAK) Result |= SymbolRef::SF_Weak; if (ESym->st_shndx == ELF::SHN_ABS) Result |= SymbolRef::SF_Absolute; if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || ESym == EF.symbol_begin() || ESym == EF.dynamic_symbol_begin()) Result |= SymbolRef::SF_FormatSpecific; if (EF.getHeader()->e_machine == ELF::EM_ARM) { if (ErrorOr 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 || ESym->st_shndx == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; if (isExportedToOtherDSO(ESym)) Result |= SymbolRef::SF_Exported; if (ESym->getVisibility() == ELF::STV_HIDDEN) Result |= SymbolRef::SF_Hidden; return Result; } template section_iterator ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const { ErrorOr 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(); DataRefImpl Sec; Sec.p = reinterpret_cast(ESec); return section_iterator(SectionRef(Sec, this)); } template std::error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { Res = getSymbolSection(getSymbol(Symb)); return std::error_code(); } template void ELFObjectFile::moveSectionNext(DataRefImpl &Sec) const { const Elf_Shdr *ESec = toELFShdrIter(Sec); Sec = toDRI(++ESec); } template std::error_code ELFObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); if (!Name) return Name.getError(); Result = *Name; return std::error_code(); } template uint64_t ELFObjectFile::getSectionAddress(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_addr; } template uint64_t ELFObjectFile::getSectionSize(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_size; } template std::error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Result) const { const Elf_Shdr *EShdr = toELFShdrIter(Sec); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); return std::error_code(); } template uint64_t ELFObjectFile::getSectionAlignment(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_addralign; } template bool ELFObjectFile::isSectionText(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; } template bool ELFObjectFile::isSectionData(DataRefImpl Sec) const { const Elf_Shdr *EShdr = toELFShdrIter(Sec); return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_PROGBITS; } template bool ELFObjectFile::isSectionBSS(DataRefImpl Sec) const { const Elf_Shdr *EShdr = toELFShdrIter(Sec); return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_NOBITS; } template bool ELFObjectFile::isSectionVirtual(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; } template relocation_iterator ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl RelData; uintptr_t SHT = reinterpret_cast(EF.section_begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; RelData.d.b = 0; const Elf_Shdr *S = reinterpret_cast(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 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 relocation_iterator ELFObjectFile::section_rel_end(DataRefImpl Sec) const { const Elf_Shdr *S = reinterpret_cast(Sec.p); relocation_iterator Begin = section_rel_begin(Sec); if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) return Begin; DataRefImpl RelData = Begin->getRawDataRefImpl(); RelData.d.b += (S->sh_size / S->sh_entsize) << 1; return relocation_iterator(RelocationRef(RelData, this)); } template section_iterator ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader()->e_type != ELF::ET_REL) return section_end(); const Elf_Shdr *EShdr = toELFShdrIter(Sec); uintX_t Type = EShdr->sh_type; if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) return section_end(); ErrorOr 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 void ELFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b += 2; } template symbol_iterator ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { uint32_t symbolIdx; const Elf_Shdr *sec = getRelSection(Rel); if (sec->sh_type == ELF::SHT_REL) symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); else symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); if (!symbolIdx) return symbol_end(); bool IsDyn = Rel.d.b & 1; DataRefImpl SymbolData; if (IsDyn) SymbolData = toDRI(EF.getDotDynSymSec(), symbolIdx); else SymbolData = toDRI(EF.getDotSymtabSec(), symbolIdx); return symbol_iterator(SymbolRef(SymbolData, this)); } template uint64_t ELFObjectFile::getRelocationOffset(DataRefImpl Rel) const { assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); const Elf_Shdr *sec = getRelSection(Rel); if (sec->sh_type == ELF::SHT_REL) return getRel(Rel)->r_offset; return getRela(Rel)->r_offset; } template uint64_t ELFObjectFile::getRelocationType(DataRefImpl Rel) const { const Elf_Shdr *sec = getRelSection(Rel); if (sec->sh_type == ELF::SHT_REL) return getRel(Rel)->getType(EF.isMips64EL()); else return getRela(Rel)->getType(EF.isMips64EL()); } template StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); } template void ELFObjectFile::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl &Result) const { uint32_t type = getRelocationType(Rel); EF.getRelocationTypeName(type, Result); } template ErrorOr ELFObjectFile::getRelocationAddend(DataRefImpl Rel) const { if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) return object_error::parse_failed; return (int64_t)getRela(Rel)->r_addend; } template const typename ELFFile::Elf_Sym * ELFObjectFile::getSymbol(DataRefImpl Symb) const { return &*toELFSymIter(Symb); } template const typename ELFObjectFile::Elf_Rel * ELFObjectFile::getRel(DataRefImpl Rel) const { assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); return EF.template getEntry(Rel.d.a, Rel.d.b >> 1); } template const typename ELFObjectFile::Elf_Rela * ELFObjectFile::getRela(DataRefImpl Rela) const { assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); return EF.template getEntry(Rela.d.a, Rela.d.b >> 1); } template ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) : ELFObjectFileBase( getELFType(static_cast(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), Object), EF(Data.getBuffer(), EC) {} template basic_symbol_iterator ELFObjectFile::symbol_begin_impl() const { DataRefImpl Sym = toDRI(EF.getDotSymtabSec(), 0); return basic_symbol_iterator(SymbolRef(Sym, this)); } template basic_symbol_iterator ELFObjectFile::symbol_end_impl() const { 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 elf_symbol_iterator ELFObjectFile::dynamic_symbol_begin() const { DataRefImpl Sym = toDRI(EF.getDotDynSymSec(), 0); return symbol_iterator(SymbolRef(Sym, this)); } template elf_symbol_iterator ELFObjectFile::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 section_iterator ELFObjectFile::section_begin() const { return section_iterator(SectionRef(toDRI(EF.section_begin()), this)); } template section_iterator ELFObjectFile::section_end() const { return section_iterator(SectionRef(toDRI(EF.section_end()), this)); } template StringRef ELFObjectFile::getLoadName() const { Elf_Dyn_Iter DI = EF.dynamic_table_begin(); Elf_Dyn_Iter DE = EF.dynamic_table_end(); while (DI != DE && DI->getTag() != ELF::DT_SONAME) ++DI; if (DI != DE) return EF.getDynamicString(DI->getVal()); return ""; } template uint8_t ELFObjectFile::getBytesInAddress() const { return ELFT::Is64Bits ? 8 : 4; } template StringRef ELFObjectFile::getFileFormatName() const { bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch (EF.getHeader()->e_machine) { case ELF::EM_386: return "ELF32-i386"; case ELF::EM_X86_64: return "ELF32-x86-64"; case ELF::EM_ARM: return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big"); case ELF::EM_HEXAGON: return "ELF32-hexagon"; case ELF::EM_MIPS: return "ELF32-mips"; case ELF::EM_PPC: return "ELF32-ppc"; case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return "ELF32-sparc"; default: return "ELF32-unknown"; } case ELF::ELFCLASS64: switch (EF.getHeader()->e_machine) { case ELF::EM_386: return "ELF64-i386"; case ELF::EM_X86_64: return "ELF64-x86-64"; case ELF::EM_AARCH64: return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big"); case ELF::EM_PPC64: return "ELF64-ppc64"; case ELF::EM_S390: return "ELF64-s390"; case ELF::EM_SPARCV9: return "ELF64-sparc"; case ELF::EM_MIPS: return "ELF64-mips"; default: return "ELF64-unknown"; } default: // FIXME: Proper error handling. report_fatal_error("Invalid ELFCLASS!"); } } template unsigned ELFObjectFile::getArch() const { bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_machine) { case ELF::EM_386: return Triple::x86; case ELF::EM_X86_64: return Triple::x86_64; case ELF::EM_AARCH64: return Triple::aarch64; case ELF::EM_ARM: return Triple::arm; case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: return IsLittleEndian ? Triple::mipsel : Triple::mips; case ELF::ELFCLASS64: return IsLittleEndian ? Triple::mips64el : Triple::mips64; default: report_fatal_error("Invalid ELFCLASS!"); } case ELF::EM_PPC: return Triple::ppc; case ELF::EM_PPC64: return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; default: return Triple::UnknownArch; } } template ELFObjectFileBase::elf_symbol_iterator_range ELFObjectFile::getDynamicSymbolIterators() const { return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); } template bool ELFObjectFile::isRelocatableObject() const { return EF.getHeader()->e_type == ELF::ET_REL; } } } #endif