//===- 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_ELF_OBJECT_FILE_H #define LLVM_OBJECT_ELF_OBJECT_FILE_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 { template class ELFObjectFile : public ObjectFile { 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_Sym_Iter Elf_Sym_Iter; typedef typename ELFFile::Elf_Shdr_Iter Elf_Shdr_Iter; typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; protected: ELFFile EF; void moveSymbolNext(DataRefImpl &Symb) const override; error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const override; error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const override; error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const override; void moveSectionNext(DataRefImpl &Sec) const override; error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; error_code isSectionText(DataRefImpl Sec, bool &Res) const override; error_code isSectionData(DataRefImpl Sec, bool &Res) const override; error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; error_code isSectionRequiredForExecution(DataRefImpl Sec, bool &Res) const override; error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) 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; error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const override; error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const override; error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) 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); } 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(Symb.p & ~uintptr_t(1)), IsDynamic); return Elf_Sym_Iter(EF.begin_symbols().getEntSize(), reinterpret_cast(Symb.p), IsDynamic); } DataRefImpl toDRI(Elf_Sym_Iter Symb) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Symb.get()) | static_cast(Symb.isDynamic()); return DRI; } Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, reinterpret_cast(Sec.p)); } DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Sec.get()); return DRI; } DataRefImpl toDRI(const Elf_Shdr *Sec) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Sec); return DRI; } Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), reinterpret_cast(Dyn.p)); } DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Dyn.get()); return DRI; } // 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(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); 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; section_iterator section_begin() const override; section_iterator section_end() const override; library_iterator needed_library_begin() const override; library_iterator needed_library_end() const override; error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; StringRef getLoadName() const override; 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); } }; // Use an alignment of 2 for the typedefs since that is the worst case for // ELF files in archives. typedef ELFObjectFile > ELF32LEObjectFile; typedef ELFObjectFile > ELF64LEObjectFile; typedef ELFObjectFile > ELF32BEObjectFile; typedef ELFObjectFile > ELF64BEObjectFile; template void ELFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb = toDRI(++toELFSymIter(Symb)); } template error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, StringRef &Result) const { ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); if (!Name) return Name.getError(); Result = *Name; return object_error::success; } template error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, StringRef &Version, bool &IsDefault) const { DataRefImpl Symb = SymRef.getRawDataRefImpl(); const Elf_Sym *symb = getSymbol(Symb); ErrorOr Ver = EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); if (!Ver) return Ver.getError(); Version = *Ver; return object_error::success; } template error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); switch (EF.getSymbolTableIndex(ESym)) { case ELF::SHN_COMMON: case ELF::SHN_UNDEF: Result = UnknownAddressOrSize; return object_error::success; case ELF::SHN_ABS: Result = ESym->st_value; return object_error::success; default: break; } const Elf_Ehdr *Header = EF.getHeader(); Result = ESym->st_value; // Clear the ARM/Thumb indicator flag. if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC) Result &= ~1; if (Header->e_type == ELF::ET_REL) Result += EF.getSection(ESym)->sh_addr; return object_error::success; } template error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const { Elf_Sym_Iter Sym = toELFSymIter(Symb); if (Sym->st_shndx == ELF::SHN_COMMON) Res = Sym->st_value; else Res = 0; return object_error::success; } template error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, uint64_t &Result) const { Result = toELFSymIter(Symb)->st_size; return object_error::success; } template error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Result) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { case ELF::STT_NOTYPE: Result = SymbolRef::ST_Unknown; break; case ELF::STT_SECTION: Result = SymbolRef::ST_Debug; break; case ELF::STT_FILE: Result = SymbolRef::ST_File; break; case ELF::STT_FUNC: Result = SymbolRef::ST_Function; break; case ELF::STT_OBJECT: case ELF::STT_COMMON: case ELF::STT_TLS: Result = SymbolRef::ST_Data; break; default: Result = SymbolRef::ST_Other; break; } return object_error::success; } template uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { Elf_Sym_Iter EIter = toELFSymIter(Symb); const Elf_Sym *ESym = &*EIter; 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 || EIter == EF.begin_symbols() || EIter == EF.begin_dynamic_symbols()) Result |= SymbolRef::SF_FormatSpecific; if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) Result |= SymbolRef::SF_Undefined; if (ESym->getType() == ELF::STT_COMMON || EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; return Result; } template error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { const Elf_Sym *ESym = getSymbol(Symb); const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) Res = section_end(); else { DataRefImpl Sec; Sec.p = reinterpret_cast(ESec); Res = section_iterator(SectionRef(Sec, this)); } return object_error::success; } template void ELFObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec = toDRI(++toELFShdrIter(Sec)); } template error_code ELFObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); if (!Name) return Name.getError(); Result = *Name; return object_error::success; } template error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_addr; return object_error::success; } template error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_size; return object_error::success; } template error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); return object_error::success; } template error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_addralign; return object_error::success; } template error_code ELFObjectFile::isSectionText(DataRefImpl Sec, bool &Result) const { Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; return object_error::success; } template error_code ELFObjectFile::isSectionData(DataRefImpl Sec, bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_PROGBITS; return object_error::success; } template error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_NOBITS; return object_error::success; } template error_code ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, bool &Result) const { Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; return object_error::success; } template error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, bool &Result) const { Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; return object_error::success; } template error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Result) const { Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; return object_error::success; } template error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); return object_error::success; } template error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); uintX_t Index = ESym->st_shndx; bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); return object_error::success; } template relocation_iterator ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl RelData; uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; RelData.d.b = 0; return relocation_iterator(RelocationRef(RelData, this)); } template relocation_iterator ELFObjectFile::section_rel_end(DataRefImpl Sec) const { DataRefImpl RelData; uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); const Elf_Shdr *S = reinterpret_cast(Sec.p); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; 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 relocation_iterator(RelocationRef(RelData, this)); } template section_iterator ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader()->e_type != ELF::ET_REL) return section_end(); Elf_Shdr_Iter 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)); } // Relocations template void ELFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { ++Rel.d.b; } template symbol_iterator ELFObjectFile::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: { symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); break; } case ELF::SHT_RELA: { symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); break; } } if (!symbolIdx) return symbol_end(); const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); 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; } return symbol_iterator(SymbolRef(SymbolData, this)); } template error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) 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; } return object_error::success; } template error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Result) const { assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); Result = getROffset(Rel); return object_error::success; } template uint64_t ELFObjectFile::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: return getRel(Rel)->r_offset; case ELF::SHT_RELA: return getRela(Rel)->r_offset; } } template error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Result) 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 object_error::success; } template StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); } template error_code ELFObjectFile::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl &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; } } EF.getRelocationTypeName(type, Result); return object_error::success; } template error_code ELFObjectFile::getRelocationAddend(DataRefImpl Rel, int64_t &Result) 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 = 0; return object_error::success; } case ELF::SHT_RELA: { Result = getRela(Rel)->r_addend; return object_error::success; } } } template error_code ELFObjectFile::getRelocationValueString( DataRefImpl Rel, SmallVectorImpl &Result) const { const Elf_Shdr *sec = getRelSection(Rel); uint8_t type; StringRef res; int64_t addend = 0; uint16_t symbol_index = 0; switch (sec->sh_type) { default: return object_error::parse_failed; case ELF::SHT_REL: { type = getRel(Rel)->getType(EF.isMips64EL()); symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); // TODO: Read implicit addend from section data. break; } case ELF::SHT_RELA: { type = getRela(Rel)->getType(EF.isMips64EL()); symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); addend = getRela(Rel)->r_addend; break; } } const Elf_Sym *symb = EF.template getEntry(sec->sh_link, symbol_index); ErrorOr SymName = EF.getSymbolName(EF.getSection(sec->sh_link), symb); if (!SymName) return SymName.getError(); switch (EF.getHeader()->e_machine) { case ELF::EM_X86_64: switch (type) { case ELF::R_X86_64_PC8: case ELF::R_X86_64_PC16: case ELF::R_X86_64_PC32: { std::string fmtbuf; raw_string_ostream fmt(fmtbuf); fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); } break; case ELF::R_X86_64_8: case ELF::R_X86_64_16: case ELF::R_X86_64_32: case ELF::R_X86_64_32S: case ELF::R_X86_64_64: { std::string fmtbuf; raw_string_ostream fmt(fmtbuf); fmt << *SymName << (addend < 0 ? "" : "+") << addend; fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); } break; default: res = "Unknown"; } break; case ELF::EM_AARCH64: { std::string fmtbuf; raw_string_ostream fmt(fmtbuf); fmt << *SymName; if (addend != 0) fmt << (addend < 0 ? "" : "+") << addend; fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); break; } case ELF::EM_ARM: case ELF::EM_HEXAGON: case ELF::EM_MIPS: res = *SymName; break; default: res = "Unknown"; } if (Result.empty()) Result.append(res.begin(), res.end()); return object_error::success; } 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 { return EF.template getEntry(Rel.d.a, Rel.d.b); } template const typename ELFObjectFile::Elf_Rela * ELFObjectFile::getRela(DataRefImpl Rela) const { return EF.template getEntry(Rela.d.a, Rela.d.b); } template ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec, bool BufferOwned) : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), Object, BufferOwned), EF(Object, ec) {} template basic_symbol_iterator ELFObjectFile::symbol_begin_impl() const { return basic_symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); } template basic_symbol_iterator ELFObjectFile::symbol_end_impl() const { return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); } template symbol_iterator ELFObjectFile::dynamic_symbol_begin() const { return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); } template symbol_iterator ELFObjectFile::dynamic_symbol_end() const { return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); } template section_iterator ELFObjectFile::section_begin() const { return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); } template section_iterator ELFObjectFile::section_end() const { return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); } template StringRef ELFObjectFile::getLoadName() const { Elf_Dyn_Iter DI = EF.begin_dynamic_table(); Elf_Dyn_Iter DE = EF.end_dynamic_table(); while (DI != DE && DI->getTag() != ELF::DT_SONAME) ++DI; if (DI != DE) return EF.getDynamicString(DI->getVal()); return ""; } template library_iterator ELFObjectFile::needed_library_begin() const { Elf_Dyn_Iter DI = EF.begin_dynamic_table(); Elf_Dyn_Iter DE = EF.end_dynamic_table(); while (DI != DE && DI->getTag() != ELF::DT_SONAME) ++DI; return library_iterator(LibraryRef(toDRI(DI), this)); } template error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, LibraryRef &Result) const { Elf_Dyn_Iter DI = toELFDynIter(Data); Elf_Dyn_Iter DE = EF.end_dynamic_table(); // Skip to the next DT_NEEDED entry. do ++DI; while (DI != DE && DI->getTag() != ELF::DT_NEEDED); Result = LibraryRef(toDRI(DI), this); return object_error::success; } template error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, StringRef &Res) const { Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); return object_error::success; } template library_iterator ELFObjectFile::needed_library_end() const { return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); } template uint8_t ELFObjectFile::getBytesInAddress() const { return ELFT::Is64Bits ? 8 : 4; } template StringRef ELFObjectFile::getFileFormatName() const { 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 "ELF32-arm"; 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 "ELF64-aarch64"; 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 { 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: return (ELFT::TargetEndianness == support::little) ? Triple::mipsel : Triple::mips; case ELF::EM_PPC64: return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; default: return Triple::UnknownArch; } } /// FIXME: Maybe we should have a base ElfObjectFile that is not a template /// and make these member functions? inline error_code getELFRelocationAddend(const RelocationRef R, int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getRelocationAddend(DRI, Addend); // Big-endian 32-bit if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getRelocationAddend(DRI, Addend); // Little-endian 64-bit if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getRelocationAddend(DRI, Addend); // Big-endian 64-bit if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getRelocationAddend(DRI, Addend); llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); } inline std::pair getELFDynamicSymbolIterators(SymbolicFile *Obj) { if (const ELF32LEObjectFile *ELF = dyn_cast(Obj)) return std::make_pair(ELF->dynamic_symbol_begin(), ELF->dynamic_symbol_end()); if (const ELF64LEObjectFile *ELF = dyn_cast(Obj)) return std::make_pair(ELF->dynamic_symbol_begin(), ELF->dynamic_symbol_end()); if (const ELF32BEObjectFile *ELF = dyn_cast(Obj)) return std::make_pair(ELF->dynamic_symbol_begin(), ELF->dynamic_symbol_end()); if (const ELF64BEObjectFile *ELF = cast(Obj)) return std::make_pair(ELF->dynamic_symbol_begin(), ELF->dynamic_symbol_end()); llvm_unreachable( "Object passed to getELFDynamicSymbolIterators() is not ELF"); } /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. inline error_code GetELFSymbolVersion(const ObjectFile *Obj, const SymbolRef &Sym, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); } } } #endif