diff options
Diffstat (limited to 'contrib/llvm/include/llvm/Object/ELFObjectFile.h')
-rw-r--r-- | contrib/llvm/include/llvm/Object/ELFObjectFile.h | 258 |
1 files changed, 80 insertions, 178 deletions
diff --git a/contrib/llvm/include/llvm/Object/ELFObjectFile.h b/contrib/llvm/include/llvm/Object/ELFObjectFile.h index c2d6438..7fc56ad 100644 --- a/contrib/llvm/include/llvm/Object/ELFObjectFile.h +++ b/contrib/llvm/include/llvm/Object/ELFObjectFile.h @@ -40,14 +40,15 @@ protected: ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); public: - virtual std::error_code getRelocationAddend(DataRefImpl Rel, - int64_t &Res) const = 0; + virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; + + // FIXME: This is a bit of a hack. Every caller should know if it expecting + // and addend or not. + virtual bool hasRelocationAddend(DataRefImpl Rel) const = 0; + virtual std::pair<symbol_iterator, symbol_iterator> getELFDynamicSymbolIterators() const = 0; - virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const = 0; - virtual uint64_t getSectionFlags(SectionRef Sec) const = 0; virtual uint32_t getSectionType(SectionRef Sec) const = 0; @@ -79,13 +80,13 @@ protected: StringRef &Res) const override; std::error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; - std::error_code getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const override; - std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getSymbolSize(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override; std::error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const override; + section_iterator getSymbolSection(const Elf_Sym *Symb) const; std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; @@ -117,9 +118,6 @@ protected: std::error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -177,6 +175,20 @@ protected: 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. @@ -196,10 +208,8 @@ public: section_iterator section_begin() const override; section_iterator section_end() const override; - std::error_code getRelocationAddend(DataRefImpl Rel, - int64_t &Res) const override; - std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const override; + ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const override; + bool hasRelocationAddend(DataRefImpl Rel) const override; uint64_t getSectionFlags(SectionRef Sec) const override; uint32_t getSectionType(SectionRef Sec) const override; @@ -211,7 +221,7 @@ public: std::error_code getPlatformFlags(unsigned &Result) const override { Result = EF.getHeader()->e_flags; - return object_error::success; + return std::error_code(); } const ELFFile<ELFT> *getELFFile() const { return &EF; } @@ -228,12 +238,10 @@ public: 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<ELFType<support::little, 2, false> > ELF32LEObjectFile; -typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile; -typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile; -typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile; +typedef ELFObjectFile<ELFType<support::little, false>> ELF32LEObjectFile; +typedef ELFObjectFile<ELFType<support::little, true>> ELF64LEObjectFile; +typedef ELFObjectFile<ELFType<support::big, false>> ELF32BEObjectFile; +typedef ELFObjectFile<ELFType<support::big, true>> ELF64BEObjectFile; template <class ELFT> void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const { @@ -247,21 +255,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, if (!Name) return Name.getError(); Result = *Name; - return object_error::success; -} - -template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { - DataRefImpl Symb = SymRef.getRawDataRefImpl(); - const Elf_Sym *symb = getSymbol(Symb); - ErrorOr<StringRef> Ver = - EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); - if (!Ver) - return Ver.getError(); - Version = *Ver; - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -284,10 +278,10 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, case ELF::SHN_COMMON: case ELF::SHN_UNDEF: Result = UnknownAddressOrSize; - return object_error::success; + return std::error_code(); case ELF::SHN_ABS: Result = ESym->st_value; - return object_error::success; + return std::error_code(); default: break; } @@ -300,35 +294,33 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, 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) { + const typename ELFFile<ELFT>::Elf_Shdr * Section = EF.getSection(ESym); + if (Section != nullptr) + Result += Section->sh_addr; + } - return object_error::success; + return std::error_code(); } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { +uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) 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; + return Sym->st_value; + return 0; } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { - Result = toELFSymIter(Symb)->st_size; - return object_error::success; +uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb) const { + return toELFSymIter(Symb)->st_size; } template <class ELFT> std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb, uint8_t &Result) const { Result = toELFSymIter(Symb)->st_other; - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -359,7 +351,7 @@ ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, Result = SymbolRef::ST_Other; break; } - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -389,23 +381,34 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const { EF.getSymbolTableIndex(ESym) == 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 <class ELFT> -std::error_code -ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const Elf_Sym *ESym = getSymbol(Symb); +section_iterator +ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const { const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) - Res = section_end(); + return section_end(); else { DataRefImpl Sec; Sec.p = reinterpret_cast<intptr_t>(ESec); - Res = section_iterator(SectionRef(Sec, this)); + return section_iterator(SectionRef(Sec, this)); } - return object_error::success; +} + +template <class ELFT> +std::error_code +ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + Res = getSymbolSection(getSymbol(Symb)); + return std::error_code(); } template <class ELFT> @@ -420,7 +423,7 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, if (!Name) return Name.getError(); Result = *Name; - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -439,7 +442,7 @@ ELFObjectFile<ELFT>::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; + return std::error_code(); } template <class ELFT> @@ -580,7 +583,7 @@ ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, Result = ROffset; } - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -590,7 +593,7 @@ ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); Result = getROffset(Rel); - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -622,7 +625,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, break; } } - return object_error::success; + return std::error_code(); } template <class ELFT> @@ -649,107 +652,20 @@ std::error_code ELFObjectFile<ELFT>::getRelocationTypeName( } EF.getRelocationTypeName(type, Result); - return object_error::success; + return std::error_code(); } template <class ELFT> -std::error_code -ELFObjectFile<ELFT>::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; - } - } +ErrorOr<int64_t> +ELFObjectFile<ELFT>::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 <class ELFT> -std::error_code ELFObjectFile<ELFT>::getRelocationValueString( - DataRefImpl Rel, SmallVectorImpl<char> &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<Elf_Sym>(sec->sh_link, symbol_index); - ErrorOr<StringRef> 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_386: - 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; +bool ELFObjectFile<ELFT>::hasRelocationAddend(DataRefImpl Rel) const { + return getRelSection(Rel)->sh_type == ELF::SHT_RELA; } template <class ELFT> @@ -908,7 +824,7 @@ unsigned ELFObjectFile<ELFT>::getArch() const { case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: - return Triple::sparc; + return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; @@ -927,26 +843,12 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { return EF.getHeader()->e_type == ELF::ET_REL; } -inline std::error_code getELFRelocationAddend(const RelocationRef R, - int64_t &Addend) { - const ObjectFile *Obj = R.getObjectFile(); - DataRefImpl DRI = R.getRawDataRefImpl(); - return cast<ELFObjectFileBase>(Obj)->getRelocationAddend(DRI, Addend); -} - inline std::pair<symbol_iterator, symbol_iterator> getELFDynamicSymbolIterators(const SymbolicFile *Obj) { return cast<ELFObjectFileBase>(Obj)->getELFDynamicSymbolIterators(); } -inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { - return cast<ELFObjectFileBase>(Obj) - ->getSymbolVersion(Sym, Version, IsDefault); -} -} -} +} // namespace object +} // namespace llvm #endif |