X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FObject%2FELFObjectFile.h;h=d345c96a404a68231851a19b3e90c17f5e8348fb;hb=4d79d2fcbfe2eb8110a118bc88dc06660f169cb1;hp=256f3c7630ca612a827140b8cd3200512ff9138b;hpb=67c46d286f6a56aade98c3b7296270b54ae8dc7e;p=oota-llvm.git diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 256f3c7630c..d345c96a404 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H -#define LLVM_OBJECT_ELF_OBJECT_FILE_H +#ifndef LLVM_OBJECT_ELFOBJECTFILE_H +#define LLVM_OBJECT_ELFOBJECTFILE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" @@ -35,8 +35,148 @@ namespace llvm { namespace object { -template -class ELFObjectFile : public ObjectFile { +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) @@ -49,113 +189,104 @@ public: 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; + const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. + const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section. + 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; + 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; - 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; + uint8_t getSymbolOther(DataRefImpl Symb) const override; + uint8_t getSymbolELFType(DataRefImpl Symb) const override; + SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; + ErrorOr getSymbolSection(const Elf_Sym *Symb) const; + ErrorOr getSymbolSection(DataRefImpl Symb) 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; + 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; - error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) 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 getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; - uint64_t getROffset(DataRefImpl Rel) const; + 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); + return *EF.getSection(Rel.d.a); } - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; + 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); - 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); - } + uintptr_t SHT = reinterpret_cast(EF.section_begin()); + unsigned SymTableIndex = + (reinterpret_cast(SymTable) - SHT) / sizeof(Elf_Shdr); - DataRefImpl toDRI(Elf_Sym_Iter Symb) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast(Symb.get()) | - static_cast(Symb.isDynamic()); + DRI.d.a = SymTableIndex; + DRI.d.b = SymbolNum; return DRI; } - Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { - return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, - reinterpret_cast(Sec.p)); + const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { + return reinterpret_cast(Sec.p); } - DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { + DataRefImpl toDRI(const Elf_Shdr *Sec) const { DataRefImpl DRI; - DRI.p = reinterpret_cast(Sec.get()); + DRI.p = reinterpret_cast(Sec); return DRI; } - DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl toDRI(const Elf_Dyn *Dyn) const { DataRefImpl DRI; - DRI.p = reinterpret_cast(Sec); + DRI.p = reinterpret_cast(Dyn); return DRI; } - Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { - return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), - reinterpret_cast(Dyn.p)); - } + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); - DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast(Dyn.get()); - return DRI; + // 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 @@ -164,31 +295,38 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); + 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 Sym) const { + return EF.template getEntry(Sym.d.a, Sym.d.b); + } - const Elf_Sym *getSymbol(DataRefImpl Symb) const; + const Elf_Shdr *getSection(DataRefImpl Sec) const { + return reinterpret_cast(Sec.p); + } 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; - 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; - + ErrorOr getRelocationAddend(DataRefImpl Rel) const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - StringRef getLoadName() const override; + + std::error_code getPlatformFlags(unsigned &Result) const override { + Result = EF.getHeader()->e_flags; + return std::error_code(); + } const ELFFile *getELFFile() const { return &EF; } @@ -197,125 +335,136 @@ public: return v->getType() == getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits); } + + elf_symbol_iterator_range getDynamicSymbolIterators() const override; + + bool isRelocatableObject() const override; }; -// 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; +typedef ELFObjectFile> ELF32LEObjectFile; +typedef ELFObjectFile> ELF64LEObjectFile; +typedef ELFObjectFile> ELF32BEObjectFile; +typedef ELFObjectFile> ELF64BEObjectFile; template -void ELFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { - Symb = toDRI(++toELFSymIter(Symb)); +void ELFObjectFile::moveSymbolNext(DataRefImpl &Sym) const { + ++Sym.d.b; } 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; +ErrorOr ELFObjectFile::getSymbolName(DataRefImpl Sym) const { + const Elf_Sym *ESym = getSymbol(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 getSection(Sec)->sh_flags; +} + +template +uint32_t ELFObjectFile::getSectionType(DataRefImpl Sec) const { + return getSection(Sec)->sh_type; } 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; +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 -error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { +ErrorOr +ELFObjectFile::getSymbolAddress(DataRefImpl Symb) const { + uint64_t Result = getSymbolValue(Symb); 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 object_error::success; case ELF::SHN_ABS: - Result = ESym->st_value; - return object_error::success; - default: - break; + return Result; } 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; + 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 object_error::success; + return Result; } template -error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { - Elf_Sym_Iter Sym = toELFSymIter(Symb); +uint32_t ELFObjectFile::getSymbolAlignment(DataRefImpl Symb) const { + const Elf_Sym *Sym = getSymbol(Symb); if (Sym->st_shndx == ELF::SHN_COMMON) - Res = Sym->st_value; - else - Res = 0; - return object_error::success; + return Sym->st_value; + return 0; +} + +template +uint64_t ELFObjectFile::getSymbolSize(DataRefImpl Sym) const { + return getSymbol(Sym)->st_size; +} + +template +uint64_t ELFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { + return getSymbol(Symb)->st_size; +} + +template +uint8_t ELFObjectFile::getSymbolOther(DataRefImpl Symb) const { + return getSymbol(Symb)->st_other; } template -error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { - Result = toELFSymIter(Symb)->st_size; - return object_error::success; +uint8_t ELFObjectFile::getSymbolELFType(DataRefImpl Symb) const { + return getSymbol(Symb)->getType(); } template -error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +SymbolRef::Type ELFObjectFile::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 object_error::success; } template -uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { - Elf_Sym_Iter EIter = toELFSymIter(Symb); - const Elf_Sym *ESym = &*EIter; +uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { + const Elf_Sym *ESym = getSymbol(Sym); uint32_t Result = SymbolRef::SF_None; @@ -329,168 +478,155 @@ uint32_t ELFObjectFile::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(DotSymtabSec) || + ESym == EF.symbol_begin(DotDynSymSec)) Result |= SymbolRef::SF_FormatSpecific; - if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + 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 || - 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)) + Result |= SymbolRef::SF_Exported; + + if (ESym->getVisibility() == ELF::STV_HIDDEN) + Result |= SymbolRef::SF_Hidden; + 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); +ErrorOr +ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const { + ErrorOr ESecOrErr = EF.getSection(ESym); + if (std::error_code EC = ESecOrErr.getError()) + return EC; + + const Elf_Shdr *ESec = *ESecOrErr; if (!ESec) - Res = section_end(); - else { - DataRefImpl Sec; - Sec.p = reinterpret_cast(ESec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; + return section_end(); + + DataRefImpl Sec; + Sec.p = reinterpret_cast(ESec); + return section_iterator(SectionRef(Sec, this)); +} + +template +ErrorOr +ELFObjectFile::getSymbolSection(DataRefImpl Symb) const { + return getSymbolSection(getSymbol(Symb)); } template void ELFObjectFile::moveSectionNext(DataRefImpl &Sec) const { - Sec = toDRI(++toELFShdrIter(Sec)); + const Elf_Shdr *ESec = getSection(Sec); + Sec = toDRI(++ESec); } template -error_code ELFObjectFile::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); +std::error_code ELFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ErrorOr Name = EF.getSectionName(&*getSection(Sec)); if (!Name) return Name.getError(); Result = *Name; - return object_error::success; + return std::error_code(); } template -error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_addr; - return object_error::success; +uint64_t ELFObjectFile::getSectionAddress(DataRefImpl Sec) const { + return getSection(Sec)->sh_addr; } template -error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_size; - return object_error::success; +uint64_t ELFObjectFile::getSectionSize(DataRefImpl Sec) const { + return getSection(Sec)->sh_size; } template -error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); +std::error_code +ELFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + const Elf_Shdr *EShdr = getSection(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; + return std::error_code(); } template -error_code -ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; - return object_error::success; +uint64_t ELFObjectFile::getSectionAlignment(DataRefImpl Sec) const { + return getSection(Sec)->sh_addralign; } template -error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; - return object_error::success; +bool ELFObjectFile::isSectionText(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; } template -error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; - return object_error::success; +bool ELFObjectFile::isSectionData(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; } 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; +bool ELFObjectFile::isSectionBSS(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; } 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; +bool ELFObjectFile::isSectionVirtual(DataRefImpl Sec) const { + return getSection(Sec)->sh_type == ELF::SHT_NOBITS; } template relocation_iterator ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl RelData; - uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + 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 { - 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; + 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)); } @@ -500,19 +636,21 @@ ELFObjectFile::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 = getSection(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 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; + Rel.d.b += 2; } template @@ -520,87 +658,40 @@ 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: { + 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(DotDynSymSec, symbolIdx); + else + SymbolData = toDRI(DotSymtabSec, symbolIdx); return symbol_iterator(SymbolRef(SymbolData, this)); } template -error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - assert((EF.getHeader()->e_type == ELF::ET_EXEC || - EF.getHeader()->e_type == ELF::ET_DYN) && - "Only executable and shared objects files have relocation addresses"); - Result = getROffset(Rel); - return object_error::success; -} - -template -error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { +uint64_t ELFObjectFile::getRelocationOffset(DataRefImpl Rel) 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: + 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 -error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { +uint64_t ELFObjectFile::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 object_error::success; + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->getType(EF.isMips64EL()); + else + return getRela(Rel)->getType(EF.isMips64EL()); } template @@ -609,231 +700,102 @@ StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { } template -error_code ELFObjectFile::getRelocationTypeName( +void 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; - } - } - + uint32_t type = getRelocationType(Rel); 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: +ErrorOr +ELFObjectFile::getRelocationAddend(DataRefImpl Rel) const { + if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) 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); + return (int64_t)getRela(Rel)->r_addend; } template const typename ELFObjectFile::Elf_Rel * ELFObjectFile::getRel(DataRefImpl Rel) const { - return EF.template getEntry(Rel.d.a, Rel.d.b); + 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 { - return EF.template getEntry(Rela.d.a, Rela.d.b); + 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(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), + Object), + EF(Data.getBuffer(), EC) { + if (EC) + return; + for (const Elf_Shdr &Sec : EF.sections()) { + switch (Sec.sh_type) { + case ELF::SHT_DYNSYM: { + if (DotDynSymSec) { + // More than one .dynsym! + EC = object_error::parse_failed; + return; + } + DotDynSymSec = &Sec; + break; + } + case ELF::SHT_SYMTAB: { + if (DotSymtabSec) { + // More than one .dynsym! + EC = object_error::parse_failed; + return; + } + DotSymtabSec = &Sec; + break; + } + } + } } -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)); + DataRefImpl Sym = toDRI(DotSymtabSec, 0); + return basic_symbol_iterator(SymbolRef(Sym, this)); } template basic_symbol_iterator ELFObjectFile::symbol_end_impl() const { - return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); + const Elf_Shdr *SymTab = DotSymtabSec; + if (!SymTab) + return symbol_begin_impl(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); } template -symbol_iterator ELFObjectFile::dynamic_symbol_begin() const { - return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); +elf_symbol_iterator ELFObjectFile::dynamic_symbol_begin() const { + DataRefImpl Sym = toDRI(DotDynSymSec, 0); + return symbol_iterator(SymbolRef(Sym, this)); } template -symbol_iterator ELFObjectFile::dynamic_symbol_end() const { - return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); +elf_symbol_iterator ELFObjectFile::dynamic_symbol_end() const { + const Elf_Shdr *SymTab = DotDynSymSec; + 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.begin_sections()), this)); + return section_iterator(SectionRef(toDRI(EF.section_begin()), 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)); + return section_iterator(SectionRef(toDRI(EF.section_end()), this)); } template @@ -843,6 +805,7 @@ uint8_t ELFObjectFile::getBytesInAddress() const { 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) { @@ -851,7 +814,7 @@ StringRef ELFObjectFile::getFileFormatName() const { case ELF::EM_X86_64: return "ELF32-x86-64"; case ELF::EM_ARM: - return "ELF32-arm"; + return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big"); case ELF::EM_HEXAGON: return "ELF32-hexagon"; case ELF::EM_MIPS: @@ -871,7 +834,7 @@ StringRef ELFObjectFile::getFileFormatName() const { case ELF::EM_X86_64: return "ELF64-x86-64"; case ELF::EM_AARCH64: - return "ELF64-aarch64"; + return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big"); case ELF::EM_PPC64: return "ELF64-ppc64"; case ELF::EM_S390: @@ -891,6 +854,7 @@ StringRef ELFObjectFile::getFileFormatName() const { template unsigned ELFObjectFile::getArch() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_machine) { case ELF::EM_386: return Triple::x86; @@ -903,17 +867,24 @@ unsigned ELFObjectFile::getArch() const { case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: - return (ELFT::TargetEndianness == support::little) ? Triple::mipsel - : Triple::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 (ELFT::TargetEndianness == support::little) ? Triple::ppc64le - : Triple::ppc64; + return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: - return Triple::sparc; + return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; @@ -922,73 +893,16 @@ unsigned ELFObjectFile::getArch() const { } } -/// 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"); +template +ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFile::getDynamicSymbolIterators() const { + return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); } -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"); +template bool ELFObjectFile::isRelocatableObject() const { + return EF.getHeader()->e_type == ELF::ET_REL; } -/// 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"); -} } }