diff options
| author | Stephen Hines <srhines@google.com> | 2013-06-12 13:32:42 -0700 |
|---|---|---|
| committer | Stephen Hines <srhines@google.com> | 2013-06-12 13:32:42 -0700 |
| commit | 1878f9a7874b1ff569d745c0269f49d3daf7203d (patch) | |
| tree | 19a8dbaaedf6a056c617e87596b32d3f452af137 /include/llvm/Object/ELF.h | |
| parent | 7a57f27b857ec4b243d83d392a399f02fc196c0a (diff) | |
| parent | 100fbdd06be7590b23c4707a98cd605bdb519498 (diff) | |
| download | external_llvm-1878f9a7874b1ff569d745c0269f49d3daf7203d.zip external_llvm-1878f9a7874b1ff569d745c0269f49d3daf7203d.tar.gz external_llvm-1878f9a7874b1ff569d745c0269f49d3daf7203d.tar.bz2 | |
Merge commit '100fbdd06be7590b23c4707a98cd605bdb519498' into merge_20130612
Diffstat (limited to 'include/llvm/Object/ELF.h')
| -rw-r--r-- | include/llvm/Object/ELF.h | 405 |
1 files changed, 240 insertions, 165 deletions
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 491a17e..eb8e22e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -55,8 +55,8 @@ inline std::pair<unsigned char, unsigned char> getElfArchType(MemoryBuffer *Object) { if (Object->getBufferSize() < ELF::EI_NIDENT) return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] - , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); + return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], + (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. @@ -318,8 +318,8 @@ struct Elf_Rel_Base; template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply uint32_t getRInfo(bool isMips64EL) const { assert(!isMips64EL); @@ -333,19 +333,18 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply uint64_t getRInfo(bool isMips64EL) const { uint64_t t = r_info; if (!isMips64EL) return t; - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed // by a 32 bit big endian number. return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - return r_info; } void setRInfo(uint64_t R) { // FIXME: Add mips64el support. @@ -356,9 +355,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - Elf_Sword r_addend; // Compute value for relocatable field by adding this + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Sword r_addend; // Compute value for relocatable field by adding this uint32_t getRInfo(bool isMips64EL) const { assert(!isMips64EL); @@ -372,13 +371,13 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. uint64_t getRInfo(bool isMips64EL) const { - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed // by a 32 bit big endian number. uint64_t t = r_info; if (!isMips64EL) @@ -583,20 +582,14 @@ protected: bool isDyldELFObject; private: - typedef SmallVector<const Elf_Shdr *, 2> Sections_t; - typedef DenseMap<unsigned, unsigned> IndexMap_t; - typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; - const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable; const Elf_Shdr *dot_shstrtab_sec; // Section header string table. const Elf_Shdr *dot_strtab_sec; // Symbol header string table. const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; + int SymbolTableIndex; + int DynamicSymbolTableIndex; DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; const Elf_Shdr *dot_dynamic_sec; // .dynamic @@ -637,19 +630,15 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Map sections to an array of relocation sections that reference - /// them sorted by section index. - RelocMap_t SectionRelocMap; - /// @brief Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.w.b); + return getSection(Rel.d.a); } public: bool isRelocationHasAddend(DataRefImpl Rel) const; template<typename T> - const T *getEntry(uint16_t Section, uint32_t Entry) const; + const T *getEntry(uint32_t Section, uint32_t Entry) const; template<typename T> const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const Elf_Shdr *getSection(DataRefImpl index) const; @@ -665,7 +654,7 @@ public: void VerifyStrTab(const Elf_Shdr *sh) const; protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? + const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? void validateSymbol(DataRefImpl Symb) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -679,6 +668,7 @@ public: error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const; uint64_t getSymbolIndex(const Elf_Sym *sym) const; + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; @@ -688,7 +678,8 @@ protected: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; @@ -714,6 +705,7 @@ protected: bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -721,14 +713,11 @@ protected: uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; @@ -754,7 +743,7 @@ public: virtual library_iterator end_libraries_needed() const; const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { - return SymbolTableSections[0]; + return getSection(DynamicSymbolTableIndex); } const Elf_Shdr *getDynamicStringTableSectionHeader() const { @@ -767,7 +756,7 @@ public: Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; Elf_Sym_iterator begin_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; + const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); if (DynSymtab) return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + DynSymtab->sh_offset); @@ -775,7 +764,7 @@ public: } Elf_Sym_iterator end_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; + const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); if (DynSymtab) return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + DynSymtab->sh_offset + DynSymtab->sh_size); @@ -842,6 +831,13 @@ public: } }; +// 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; + // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. template<class ELFT> @@ -904,7 +900,8 @@ void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { template<class ELFT> void ELFObjectFile<ELFT>::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) + if (getDynamicStringTableSectionHeader() == NULL || + dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -927,7 +924,7 @@ template<class ELFT> void ELFObjectFile<ELFT>::validateSymbol(DataRefImpl Symb) const { #ifndef NDEBUG const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; + const Elf_Shdr *SymbolTableSection = getSection(Symb.d.b); // FIXME: We really need to do proper error handling in the case of an invalid // input file. Because we don't use exceptions, I think we'll just pass // an error object around. @@ -947,25 +944,7 @@ template<class ELFT> error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, SymbolRef &Result) const { validateSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - ++Symb.d.a; - // Check to see if we are at the end of this symbol table. - if (Symb.d.a >= SymbolTableSection->getEntityCount()) { - // We are at the end. If there are other symbol tables, jump to them. - // If the symbol table is .dynsym, we are iterating dynamic symbols, - // and there is only one table of these. - if (Symb.d.b != 0) { - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - } - // Otherwise return the terminator. - if (Symb.d.b == 0 || Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits<uint32_t>::max(); - Symb.d.b = std::numeric_limits<uint32_t>::max(); - } - } - Result = SymbolRef(Symb, this); return object_error::success; } @@ -975,7 +954,7 @@ error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); + return getSymbolName(getSection(Symb.d.b), symb, Result); } template<class ELFT> @@ -985,8 +964,7 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, DataRefImpl Symb = SymRef.getRawDataRefImpl(); validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - return getSymbolVersion(SymbolTableSections[Symb.d.b], symb, - Version, IsDefault); + return getSymbolVersion(getSection(Symb.d.b), symb, Version, IsDefault); } template<class ELFT> @@ -1031,7 +1009,7 @@ const typename ELFObjectFile<ELFT>::Elf_Sym * ELFObjectFile<ELFT>::getElfSymbol(uint32_t index) const { DataRefImpl SymbolData; SymbolData.d.a = index; - SymbolData.d.b = 1; + SymbolData.d.b = SymbolTableIndex; return getSymbol(SymbolData); } @@ -1455,13 +1433,9 @@ template<class ELFT> relocation_iterator ELFObjectFile<ELFT>::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_info; - RelData.w.b = ittr->second[0]; - RelData.w.c = 0; - } + uintptr_t SHT = reinterpret_cast<uintptr_t>(SectionHeaderTable); + RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; + RelData.d.b = 0; return relocation_iterator(RelocationRef(RelData, this)); } @@ -1469,53 +1443,49 @@ template<class ELFT> relocation_iterator ELFObjectFile<ELFT>::getSectionRelEnd(DataRefImpl Sec) const { DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - // Get the index of the last relocation section for this section. - std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; - const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_info; - RelData.w.b = relocsecindex; - RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; - } + uintptr_t SHT = reinterpret_cast<uintptr_t>(SectionHeaderTable); + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + RelData.d.a = (Sec.p - SHT) / Header->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 <class ELFT> +section_iterator +ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { + if (Header->e_type != ELF::ET_REL) + return end_sections(); + + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + unsigned sh_type = S->sh_type; + if (sh_type != ELF::SHT_RELA && sh_type != ELF::SHT_REL) + return end_sections(); + + assert(S->sh_info != 0); + const Elf_Shdr *R = getSection(S->sh_info); + DataRefImpl D; + D.p = reinterpret_cast<uintptr_t>(R); + return section_iterator(SectionRef(D, this)); +} + // Relocations template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, RelocationRef &Result) const { - ++Rel.w.c; - const Elf_Shdr *relocsec = getSection(Rel.w.b); - if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { - // We have reached the end of the relocations for this section. See if there - // is another relocation section. - typename RelocMap_t::mapped_type relocseclist = - SectionRelocMap.lookup(getSection(Rel.w.a)); - - // Do a binary search for the current reloc section index (which must be - // present). Then get the next one. - typename RelocMap_t::mapped_type::const_iterator loc = - std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); - ++loc; - - // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel - // to the end iterator. - if (loc != relocseclist.end()) { - Rel.w.b = *loc; - Rel.w.a = 0; - } - } + ++Rel.d.b; Result = RelocationRef(Rel, this); return object_error::success; } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { +template <class ELFT> +symbol_iterator +ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { uint32_t symbolIdx; - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -1528,14 +1498,13 @@ error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, break; } } + if (!symbolIdx) + return end_symbols(); + DataRefImpl SymbolData; - IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); - if (it == SymbolTableSectionsIndexMap.end()) - report_fatal_error("Relocation symbol table not found!"); SymbolData.d.a = symbolIdx; - SymbolData.d.b = it->second; - Result = SymbolRef(SymbolData, this); - return object_error::success; + SymbolData.d.b = sec->sh_link; + return symbol_iterator(SymbolRef(SymbolData, this)); } template<class ELFT> @@ -1558,7 +1527,7 @@ error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, template<class ELFT> uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default: report_fatal_error("Invalid section type in Rel!"); @@ -1572,7 +1541,7 @@ uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, uint64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -2071,10 +2040,18 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRNTAKEN); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); @@ -2104,6 +2081,73 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { default: break; } break; + case ELF::EM_S390: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); + default: break; + } + break; default: break; } return Res; @@ -2114,7 +2158,7 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); uint32_t type; switch (sec->sh_type) { default : @@ -2154,9 +2198,9 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( } template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( +error_code ELFObjectFile<ELFT>::getRelocationAddend( DataRefImpl Rel, int64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -2174,7 +2218,7 @@ error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationValueString( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); uint8_t type; StringRef res; int64_t addend = 0; @@ -2298,8 +2342,8 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; const Elf_Shdr* sh = SectionHeaderTable; - // Reserve SymbolTableSections[0] for .dynsym - SymbolTableSections.push_back(NULL); + SymbolTableIndex = -1; + DynamicSymbolTableIndex = -1; for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { switch (sh->sh_type) { @@ -2311,23 +2355,21 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) break; } case ELF::SHT_SYMTAB: { - SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); - SymbolTableSections.push_back(sh); + if (SymbolTableIndex != -1) + report_fatal_error("More than one SHT_SYMTAB!"); + SymbolTableIndex = i; break; } case ELF::SHT_DYNSYM: { - if (SymbolTableSections[0] != NULL) + if (DynamicSymbolTableIndex != -1) // FIXME: Proper error handling. - report_fatal_error("More than one .dynsym!"); - SymbolTableSectionsIndexMap[i] = 0; - SymbolTableSections[0] = sh; + report_fatal_error("More than one SHT_DYNSYM!"); + DynamicSymbolTableIndex = i; break; } case ELF::SHT_REL: - case ELF::SHT_RELA: { - SectionRelocMap[getSection(sh->sh_info)].push_back(i); + case ELF::SHT_RELA: break; - } case ELF::SHT_DYNAMIC: { if (dot_dynamic_sec != NULL) // FIXME: Proper error handling. @@ -2360,12 +2402,6 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) ++sh; } - // Sort section relocation lists by index. - for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), - e = SectionRelocMap.end(); i != e; ++i) { - std::sort(i->second.begin(), i->second.end()); - } - // Get string table sections. dot_shstrtab_sec = getSection(getStringTableIndex()); if (dot_shstrtab_sec) { @@ -2415,8 +2451,7 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) // Get the symbol table index in the symtab section given a symbol template<class ELFT> uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { - assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); - const Elf_Shdr *SymTab = *SymbolTableSections.begin(); + const Elf_Shdr *SymTab = getSection(SymbolTableIndex); uintptr_t SymLoc = uintptr_t(Sym); uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); @@ -2429,12 +2464,12 @@ uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { DataRefImpl SymbolData; - if (SymbolTableSections.size() <= 1) { - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (SymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 1; // The 0th table is .dynsym + SymbolData.d.a = 0; + SymbolData.d.b = SymbolTableIndex; } return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -2442,20 +2477,26 @@ symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (SymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; + } else { + const Elf_Shdr *SymbolTableSection = getSection(SymbolTableIndex); + SymbolData.d.a = SymbolTableSection->getEntityCount(); + SymbolData.d.b = SymbolTableIndex; + } return symbol_iterator(SymbolRef(SymbolData, this)); } template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { DataRefImpl SymbolData; - if (SymbolTableSections[0] == NULL) { - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (DynamicSymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 0; // The 0th table is .dynsym + SymbolData.d.a = 0; + SymbolData.d.b = DynamicSymbolTableIndex; } return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -2463,8 +2504,14 @@ symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (DynamicSymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; + } else { + const Elf_Shdr *SymbolTableSection = getSection(DynamicSymbolTableIndex); + SymbolData.d.a = SymbolTableSection->getEntityCount(); + SymbolData.d.b = DynamicSymbolTableIndex; + } return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -2618,6 +2665,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-hexagon"; case ELF::EM_MIPS: return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; default: return "ELF32-unknown"; } @@ -2631,6 +2680,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-aarch64"; case ELF::EM_PPC64: return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; default: return "ELF64-unknown"; } @@ -2658,6 +2709,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { Triple::mipsel : Triple::mips; case ELF::EM_PPC64: return Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; default: return Triple::UnknownArch; } @@ -2688,7 +2741,7 @@ ELFObjectFile<ELFT>::getStringTableIndex() const { template<class ELFT> template<typename T> inline const T * -ELFObjectFile<ELFT>::getEntry(uint16_t Section, uint32_t Entry) const { +ELFObjectFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry<T>(getSection(Section), Entry); } @@ -2705,19 +2758,19 @@ ELFObjectFile<ELFT>::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Sym * ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { - return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); + return getEntry<Elf_Sym>(Symb.d.b, Symb.d.a); } template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rel * ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { - return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); + return getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); } template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rela * ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { - return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); + return getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); } template<class ELFT> @@ -2773,7 +2826,8 @@ error_code ELFObjectFile<ELFT>::getSymbolName(const Elf_Shdr *section, return object_error::success; } - if (section == SymbolTableSections[0]) { + if (DynamicSymbolTableIndex != -1 && + section == getSection(DynamicSymbolTableIndex)) { // Symbol is in .dynsym, use .dynstr string table Result = getString(dot_dynstr_sec, symb->st_name); } else { @@ -2796,7 +2850,7 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, StringRef &Version, bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != SymbolTableSections[0]) { + if (section != getSection(DynamicSymbolTableIndex)) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. @@ -2872,6 +2926,31 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, return object_error::success; } +/// FIXME: Maybe we should have a base ElfObjectFile that is not a template +/// and make these member functions? +static 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<ELF32LEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); +} + /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, @@ -2879,23 +2958,19 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit - if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj)) + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit - if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj)) + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit - if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj)) + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit - if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj)) + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); |
