diff options
Diffstat (limited to 'include/llvm/Object/ELFObjectFile.h')
-rw-r--r-- | include/llvm/Object/ELFObjectFile.h | 146 |
1 files changed, 90 insertions, 56 deletions
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 5d826da4c2fc2..07c6364a68949 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -14,23 +14,28 @@ #ifndef LLVM_OBJECT_ELFOBJECTFILE_H #define LLVM_OBJECT_ELFOBJECTFILE_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/ELF.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cctype> -#include <limits> -#include <utility> +#include <cassert> +#include <cstdint> +#include <system_error> namespace llvm { namespace object { @@ -47,6 +52,7 @@ class ELFObjectFileBase : public ObjectFile { protected: ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + virtual uint16_t getEMachine() const = 0; virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; @@ -55,14 +61,16 @@ protected: virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; -public: +public: typedef iterator_range<elf_symbol_iterator> 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(); } + + SubtargetFeatures getFeatures() const override; }; class ELFSectionRef : public SectionRef { @@ -175,6 +183,7 @@ ELFObjectFileBase::symbols() const { } template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { + uint16_t getEMachine() const override; uint64_t getSymbolSize(DataRefImpl Sym) const override; public: @@ -197,18 +206,18 @@ protected: ArrayRef<Elf_Word> ShndxTable; void moveSymbolNext(DataRefImpl &Symb) const override; - ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; - ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> 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; - ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb, - const Elf_Shdr *SymTab) const; - ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, + const Elf_Shdr *SymTab) const; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, @@ -218,6 +227,7 @@ protected: std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; @@ -284,11 +294,9 @@ protected: // 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; + return ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && + (Visibility == ELF::STV_DEFAULT || + Visibility == ELF::STV_PROTECTED)); } // This flag is used for classof, to distinguish ELFObjectFile from @@ -354,7 +362,7 @@ void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { } template <class ELFT> -ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { +Expected<StringRef> ELFObjectFile<ELFT>::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); @@ -389,7 +397,7 @@ uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { } template <class ELFT> -ErrorOr<uint64_t> +Expected<uint64_t> ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { uint64_t Result = getSymbolValue(Symb); const Elf_Sym *ESym = getSymbol(Symb); @@ -407,7 +415,7 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { ErrorOr<const Elf_Shdr *> SectionOrErr = EF.getSection(ESym, SymTab, ShndxTable); if (std::error_code EC = SectionOrErr.getError()) - return EC; + return errorCodeToError(EC); const Elf_Shdr *Section = *SectionOrErr; if (Section) Result += Section->sh_addr; @@ -425,6 +433,11 @@ uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const { } template <class ELFT> +uint16_t ELFObjectFile<ELFT>::getEMachine() const { + return EF.getHeader()->e_machine; +} + +template <class ELFT> uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { return getSymbol(Sym)->st_size; } @@ -445,7 +458,8 @@ uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const { } template <class ELFT> -SymbolRef::Type ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { +Expected<SymbolRef::Type> +ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { @@ -487,12 +501,17 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { Result |= SymbolRef::SF_FormatSpecific; if (EF.getHeader()->e_machine == ELF::EM_ARM) { - if (ErrorOr<StringRef> NameOrErr = getSymbolName(Sym)) { + if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) { StringRef Name = *NameOrErr; if (Name.startswith("$d") || Name.startswith("$t") || Name.startswith("$a")) Result |= SymbolRef::SF_FormatSpecific; + } else { + // TODO: Actually report errors helpfully. + consumeError(NameOrErr.takeError()); } + if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) + Result |= SymbolRef::SF_Thumb; } if (ESym->st_shndx == ELF::SHN_UNDEF) @@ -511,12 +530,12 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { } template <class ELFT> -ErrorOr<section_iterator> +Expected<section_iterator> ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, const Elf_Shdr *SymTab) const { ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable); if (std::error_code EC = ESecOrErr.getError()) - return EC; + return errorCodeToError(EC); const Elf_Shdr *ESec = *ESecOrErr; if (!ESec) @@ -528,7 +547,7 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, } template <class ELFT> -ErrorOr<section_iterator> +Expected<section_iterator> ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { const Elf_Sym *Sym = getSymbol(Symb); const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a); @@ -576,6 +595,11 @@ uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { } template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED; +} + +template <class ELFT> bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; } @@ -606,22 +630,6 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; RelData.d.b = 0; - - const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(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<const Elf_Shdr *> 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)); } @@ -633,7 +641,14 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { 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; + const Elf_Shdr *RelSec = getRelSection(RelData); + + // Error check sh_link here so that getRelocationSymbol can just use it. + ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link); + if (std::error_code EC = SymSecOrErr.getError()) + report_fatal_error(EC.message()); + + RelData.d.b += S->sh_size / S->sh_entsize; return relocation_iterator(RelocationRef(RelData, this)); } @@ -657,7 +672,7 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { // Relocations template <class ELFT> void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { - Rel.d.b += 2; + ++Rel.d.b; } template <class ELFT> @@ -672,12 +687,10 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { if (!symbolIdx) return symbol_end(); - bool IsDyn = Rel.d.b & 1; + // FIXME: error check symbolIdx DataRefImpl SymbolData; - if (IsDyn) - SymbolData = toDRI(DotDynSymSec, symbolIdx); - else - SymbolData = toDRI(DotSymtabSec, symbolIdx); + SymbolData.d.a = sec->sh_link; + SymbolData.d.b = symbolIdx; return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -725,14 +738,14 @@ template <class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rel * ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); - return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b >> 1); + return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); } template <class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rela * ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); - return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b >> 1); + return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); } template <class ELFT> @@ -835,6 +848,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-avr"; case ELF::EM_HEXAGON: return "ELF32-hexagon"; + case ELF::EM_LANAI: + return "ELF32-lanai"; case ELF::EM_MIPS: return "ELF32-mips"; case ELF::EM_PPC: @@ -844,6 +859,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-sparc"; case ELF::EM_WEBASSEMBLY: return "ELF32-wasm"; + case ELF::EM_AMDGPU: + return "ELF32-amdgpu"; default: return "ELF32-unknown"; } @@ -865,6 +882,12 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-mips"; case ELF::EM_WEBASSEMBLY: return "ELF64-wasm"; + case ELF::EM_AMDGPU: + return (EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA + && IsLittleEndian) ? + "ELF64-amdgpu-hsacobj" : "ELF64-amdgpu"; + case ELF::EM_BPF: + return "ELF64-BPF"; default: return "ELF64-unknown"; } @@ -891,6 +914,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { return Triple::avr; case ELF::EM_HEXAGON: return Triple::hexagon; + case ELF::EM_LANAI: + return Triple::lanai; case ELF::EM_MIPS: switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: @@ -919,6 +944,15 @@ unsigned ELFObjectFile<ELFT>::getArch() const { default: return Triple::UnknownArch; } + case ELF::EM_AMDGPU: + return (EF.getHeader()->e_ident[ELF::EI_CLASS] == ELF::ELFCLASS64 + && EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA + && IsLittleEndian) ? + Triple::amdgcn : Triple::UnknownArch; + + case ELF::EM_BPF: + return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; + default: return Triple::UnknownArch; } @@ -934,7 +968,7 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { return EF.getHeader()->e_type == ELF::ET_REL; } -} -} +} // end namespace object +} // end namespace llvm -#endif +#endif // LLVM_OBJECT_ELFOBJECTFILE_H |