1234285Sdim//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10263509Sdim// This file declares the ELFFile template class. 11234285Sdim// 12234285Sdim//===----------------------------------------------------------------------===// 13234285Sdim 14234285Sdim#ifndef LLVM_OBJECT_ELF_H 15234285Sdim#define LLVM_OBJECT_ELF_H 16234285Sdim 17263509Sdim#include "llvm/ADT/ArrayRef.h" 18252723Sdim#include "llvm/ADT/DenseMap.h" 19252723Sdim#include "llvm/ADT/PointerIntPair.h" 20234285Sdim#include "llvm/ADT/SmallVector.h" 21234285Sdim#include "llvm/ADT/StringSwitch.h" 22234285Sdim#include "llvm/ADT/Triple.h" 23263509Sdim#include "llvm/Object/ELFTypes.h" 24263509Sdim#include "llvm/Object/Error.h" 25234285Sdim#include "llvm/Support/Casting.h" 26234285Sdim#include "llvm/Support/ELF.h" 27234285Sdim#include "llvm/Support/Endian.h" 28234285Sdim#include "llvm/Support/ErrorHandling.h" 29263509Sdim#include "llvm/Support/ErrorOr.h" 30234285Sdim#include "llvm/Support/MemoryBuffer.h" 31234285Sdim#include "llvm/Support/raw_ostream.h" 32234285Sdim#include <algorithm> 33234285Sdim#include <limits> 34234285Sdim#include <utility> 35234285Sdim 36234285Sdimnamespace llvm { 37234285Sdimnamespace object { 38234285Sdim 39263509SdimStringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); 40252723Sdim 41263509Sdim// Subclasses of ELFFile may need this for template instantiation 42235633Sdiminline std::pair<unsigned char, unsigned char> 43235633SdimgetElfArchType(MemoryBuffer *Object) { 44235633Sdim if (Object->getBufferSize() < ELF::EI_NIDENT) 45235633Sdim return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 46263509Sdim return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], 47263509Sdim (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); 48235633Sdim} 49235633Sdim 50263509Sdimtemplate <class ELFT> 51263509Sdimclass ELFFile { 52263509Sdimpublic: 53252723Sdim LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 54263509Sdim typedef typename conditional<ELFT::Is64Bits, 55263509Sdim uint64_t, uint32_t>::type uintX_t; 56234285Sdim 57252723Sdim /// \brief Iterate over constant sized entities. 58263509Sdim template <class EntT> 59252723Sdim class ELFEntityIterator { 60245431Sdim public: 61252723Sdim typedef ptrdiff_t difference_type; 62252723Sdim typedef EntT value_type; 63252723Sdim typedef std::random_access_iterator_tag iterator_category; 64245431Sdim typedef value_type &reference; 65245431Sdim typedef value_type *pointer; 66245431Sdim 67245431Sdim /// \brief Default construct iterator. 68252723Sdim ELFEntityIterator() : EntitySize(0), Current(0) {} 69263509Sdim ELFEntityIterator(uintX_t EntSize, const char *Start) 70263509Sdim : EntitySize(EntSize), Current(Start) {} 71245431Sdim 72245431Sdim reference operator *() { 73245431Sdim assert(Current && "Attempted to dereference an invalid iterator!"); 74252723Sdim return *reinterpret_cast<pointer>(Current); 75245431Sdim } 76245431Sdim 77245431Sdim pointer operator ->() { 78245431Sdim assert(Current && "Attempted to dereference an invalid iterator!"); 79252723Sdim return reinterpret_cast<pointer>(Current); 80245431Sdim } 81245431Sdim 82252723Sdim bool operator ==(const ELFEntityIterator &Other) { 83252723Sdim return Current == Other.Current; 84245431Sdim } 85245431Sdim 86252723Sdim bool operator !=(const ELFEntityIterator &Other) { 87245431Sdim return !(*this == Other); 88245431Sdim } 89245431Sdim 90252723Sdim ELFEntityIterator &operator ++() { 91245431Sdim assert(Current && "Attempted to increment an invalid iterator!"); 92252723Sdim Current += EntitySize; 93245431Sdim return *this; 94245431Sdim } 95245431Sdim 96252723Sdim ELFEntityIterator operator ++(int) { 97252723Sdim ELFEntityIterator Tmp = *this; 98245431Sdim ++*this; 99245431Sdim return Tmp; 100245431Sdim } 101245431Sdim 102252723Sdim ELFEntityIterator &operator =(const ELFEntityIterator &Other) { 103252723Sdim EntitySize = Other.EntitySize; 104252723Sdim Current = Other.Current; 105252723Sdim return *this; 106252723Sdim } 107252723Sdim 108252723Sdim difference_type operator -(const ELFEntityIterator &Other) const { 109252723Sdim assert(EntitySize == Other.EntitySize && 110263509Sdim "Subtracting iterators of different EntitySize!"); 111252723Sdim return (Current - Other.Current) / EntitySize; 112252723Sdim } 113252723Sdim 114252723Sdim const char *get() const { return Current; } 115252723Sdim 116263509Sdim uintX_t getEntSize() const { return EntitySize; } 117263509Sdim 118245431Sdim private: 119263509Sdim uintX_t EntitySize; 120245431Sdim const char *Current; 121245431Sdim }; 122245431Sdim 123252723Sdim typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; 124252723Sdim typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; 125252723Sdim typedef Elf_Sym_Impl<ELFT> Elf_Sym; 126252723Sdim typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; 127252723Sdim typedef Elf_Phdr_Impl<ELFT> Elf_Phdr; 128252723Sdim typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; 129252723Sdim typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; 130252723Sdim typedef Elf_Verdef_Impl<ELFT> Elf_Verdef; 131252723Sdim typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; 132252723Sdim typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; 133252723Sdim typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; 134252723Sdim typedef Elf_Versym_Impl<ELFT> Elf_Versym; 135263509Sdim typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter; 136252723Sdim typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; 137252723Sdim typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter; 138263509Sdim typedef ELFEntityIterator<const Elf_Shdr> Elf_Shdr_Iter; 139252723Sdim 140263509Sdim /// \brief Archive files are 2 byte aligned, so we need this for 141263509Sdim /// PointerIntPair to work. 142263509Sdim template <typename T> 143263509Sdim class ArchivePointerTypeTraits { 144263509Sdim public: 145263509Sdim static inline const void *getAsVoidPointer(T *P) { return P; } 146263509Sdim static inline T *getFromVoidPointer(const void *P) { 147263509Sdim return static_cast<T *>(P); 148263509Sdim } 149263509Sdim enum { NumLowBitsAvailable = 1 }; 150263509Sdim }; 151252723Sdim 152263509Sdim class Elf_Sym_Iter { 153263509Sdim public: 154263509Sdim typedef ptrdiff_t difference_type; 155263509Sdim typedef const Elf_Sym value_type; 156263509Sdim typedef std::random_access_iterator_tag iterator_category; 157263509Sdim typedef value_type &reference; 158263509Sdim typedef value_type *pointer; 159263509Sdim 160263509Sdim /// \brief Default construct iterator. 161263509Sdim Elf_Sym_Iter() : EntitySize(0), Current(0, false) {} 162263509Sdim Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic) 163263509Sdim : EntitySize(EntSize), Current(Start, IsDynamic) {} 164263509Sdim 165263509Sdim reference operator*() { 166263509Sdim assert(Current.getPointer() && 167263509Sdim "Attempted to dereference an invalid iterator!"); 168263509Sdim return *reinterpret_cast<pointer>(Current.getPointer()); 169263509Sdim } 170263509Sdim 171263509Sdim pointer operator->() { 172263509Sdim assert(Current.getPointer() && 173263509Sdim "Attempted to dereference an invalid iterator!"); 174263509Sdim return reinterpret_cast<pointer>(Current.getPointer()); 175263509Sdim } 176263509Sdim 177263509Sdim bool operator==(const Elf_Sym_Iter &Other) { 178263509Sdim return Current == Other.Current; 179263509Sdim } 180263509Sdim 181263509Sdim bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); } 182263509Sdim 183263509Sdim Elf_Sym_Iter &operator++() { 184263509Sdim assert(Current.getPointer() && 185263509Sdim "Attempted to increment an invalid iterator!"); 186263509Sdim Current.setPointer(Current.getPointer() + EntitySize); 187263509Sdim return *this; 188263509Sdim } 189263509Sdim 190263509Sdim Elf_Sym_Iter operator++(int) { 191263509Sdim Elf_Sym_Iter Tmp = *this; 192263509Sdim ++*this; 193263509Sdim return Tmp; 194263509Sdim } 195263509Sdim 196263509Sdim Elf_Sym_Iter operator+(difference_type Dist) { 197263509Sdim assert(Current.getPointer() && 198263509Sdim "Attempted to increment an invalid iterator!"); 199263509Sdim Current.setPointer(Current.getPointer() + EntitySize * Dist); 200263509Sdim return *this; 201263509Sdim } 202263509Sdim 203263509Sdim Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) { 204263509Sdim EntitySize = Other.EntitySize; 205263509Sdim Current = Other.Current; 206263509Sdim return *this; 207263509Sdim } 208263509Sdim 209263509Sdim difference_type operator-(const Elf_Sym_Iter &Other) const { 210263509Sdim assert(EntitySize == Other.EntitySize && 211263509Sdim "Subtracting iterators of different EntitySize!"); 212263509Sdim return (Current.getPointer() - Other.Current.getPointer()) / EntitySize; 213263509Sdim } 214263509Sdim 215263509Sdim const char *get() const { return Current.getPointer(); } 216263509Sdim 217263509Sdim bool isDynamic() const { return Current.getInt(); } 218263509Sdim 219263509Sdim uintX_t getEntSize() const { return EntitySize; } 220263509Sdim 221263509Sdim private: 222263509Sdim uintX_t EntitySize; 223263509Sdim PointerIntPair<const char *, 1, bool, 224263509Sdim ArchivePointerTypeTraits<const char> > Current; 225263509Sdim }; 226263509Sdim 227245431Sdimprivate: 228252723Sdim typedef SmallVector<const Elf_Shdr *, 2> Sections_t; 229252723Sdim typedef DenseMap<unsigned, unsigned> IndexMap_t; 230252723Sdim 231263509Sdim MemoryBuffer *Buf; 232263509Sdim 233263509Sdim const uint8_t *base() const { 234263509Sdim return reinterpret_cast<const uint8_t *>(Buf->getBufferStart()); 235263509Sdim } 236263509Sdim 237252723Sdim const Elf_Ehdr *Header; 238252723Sdim const Elf_Shdr *SectionHeaderTable; 239252723Sdim const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 240252723Sdim const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 241263509Sdim const Elf_Shdr *dot_symtab_sec; // Symbol table section. 242252723Sdim 243263509Sdim const Elf_Shdr *SymbolTableSectionHeaderIndex; 244263509Sdim DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable; 245252723Sdim 246252723Sdim const Elf_Shdr *dot_gnu_version_sec; // .gnu.version 247252723Sdim const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r 248252723Sdim const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d 249252723Sdim 250263509Sdim /// \brief Represents a region described by entries in the .dynamic table. 251263509Sdim struct DynRegionInfo { 252263509Sdim DynRegionInfo() : Addr(0), Size(0), EntSize(0) {} 253263509Sdim /// \brief Address in current address space. 254263509Sdim const void *Addr; 255263509Sdim /// \brief Size in bytes of the region. 256263509Sdim uintX_t Size; 257263509Sdim /// \brief Size of each entity in the region. 258263509Sdim uintX_t EntSize; 259263509Sdim }; 260263509Sdim 261263509Sdim DynRegionInfo DynamicRegion; 262263509Sdim DynRegionInfo DynHashRegion; 263263509Sdim DynRegionInfo DynStrRegion; 264263509Sdim DynRegionInfo DynSymRegion; 265263509Sdim 266252723Sdim // Pointer to SONAME entry in dynamic string table 267252723Sdim // This is set the first time getLoadName is called. 268252723Sdim mutable const char *dt_soname; 269252723Sdim 270234285Sdim // Records for each version index the corresponding Verdef or Vernaux entry. 271234285Sdim // This is filled the first time LoadVersionMap() is called. 272234285Sdim class VersionMapEntry : public PointerIntPair<const void*, 1> { 273234285Sdim public: 274234285Sdim // If the integer is 0, this is an Elf_Verdef*. 275234285Sdim // If the integer is 1, this is an Elf_Vernaux*. 276234285Sdim VersionMapEntry() : PointerIntPair<const void*, 1>(NULL, 0) { } 277234285Sdim VersionMapEntry(const Elf_Verdef *verdef) 278234285Sdim : PointerIntPair<const void*, 1>(verdef, 0) { } 279234285Sdim VersionMapEntry(const Elf_Vernaux *vernaux) 280234285Sdim : PointerIntPair<const void*, 1>(vernaux, 1) { } 281234285Sdim bool isNull() const { return getPointer() == NULL; } 282234285Sdim bool isVerdef() const { return !isNull() && getInt() == 0; } 283234285Sdim bool isVernaux() const { return !isNull() && getInt() == 1; } 284234285Sdim const Elf_Verdef *getVerdef() const { 285234285Sdim return isVerdef() ? (const Elf_Verdef*)getPointer() : NULL; 286234285Sdim } 287234285Sdim const Elf_Vernaux *getVernaux() const { 288234285Sdim return isVernaux() ? (const Elf_Vernaux*)getPointer() : NULL; 289234285Sdim } 290234285Sdim }; 291234285Sdim mutable SmallVector<VersionMapEntry, 16> VersionMap; 292234285Sdim void LoadVersionDefs(const Elf_Shdr *sec) const; 293234285Sdim void LoadVersionNeeds(const Elf_Shdr *ec) const; 294234285Sdim void LoadVersionMap() const; 295234285Sdim 296252723Sdimpublic: 297234285Sdim template<typename T> 298263509Sdim const T *getEntry(uint32_t Section, uint32_t Entry) const; 299263509Sdim template <typename T> 300263509Sdim const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; 301234285Sdim const char *getString(uint32_t section, uint32_t offset) const; 302234285Sdim const char *getString(const Elf_Shdr *section, uint32_t offset) const; 303263509Sdim const char *getDynamicString(uintX_t Offset) const; 304263509Sdim ErrorOr<StringRef> getSymbolVersion(const Elf_Shdr *section, 305263509Sdim const Elf_Sym *Symb, 306263509Sdim bool &IsDefault) const; 307234285Sdim void VerifyStrTab(const Elf_Shdr *sh) const; 308234285Sdim 309263509Sdim StringRef getRelocationTypeName(uint32_t Type) const; 310263509Sdim void getRelocationTypeName(uint32_t Type, 311263509Sdim SmallVectorImpl<char> &Result) const; 312234285Sdim 313263509Sdim /// \brief Get the symbol table section and symbol for a given relocation. 314263509Sdim template <class RelT> 315263509Sdim std::pair<const Elf_Shdr *, const Elf_Sym *> 316263509Sdim getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; 317234285Sdim 318263509Sdim ELFFile(MemoryBuffer *Object, error_code &ec); 319234285Sdim 320252723Sdim bool isMips64EL() const { 321252723Sdim return Header->e_machine == ELF::EM_MIPS && 322252723Sdim Header->getFileClass() == ELF::ELFCLASS64 && 323252723Sdim Header->getDataEncoding() == ELF::ELFDATA2LSB; 324252723Sdim } 325252723Sdim 326263509Sdim Elf_Shdr_Iter begin_sections() const; 327263509Sdim Elf_Shdr_Iter end_sections() const; 328234285Sdim 329263509Sdim Elf_Sym_Iter begin_symbols() const; 330263509Sdim Elf_Sym_Iter end_symbols() const; 331234285Sdim 332263509Sdim Elf_Dyn_Iter begin_dynamic_table() const; 333252723Sdim /// \param NULLEnd use one past the first DT_NULL entry as the end instead of 334252723Sdim /// the section size. 335263509Sdim Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; 336252723Sdim 337263509Sdim Elf_Sym_Iter begin_dynamic_symbols() const { 338263509Sdim if (DynSymRegion.Addr) 339263509Sdim return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, 340263509Sdim true); 341263509Sdim return Elf_Sym_Iter(0, 0, true); 342245431Sdim } 343245431Sdim 344263509Sdim Elf_Sym_Iter end_dynamic_symbols() const { 345263509Sdim if (DynSymRegion.Addr) 346263509Sdim return Elf_Sym_Iter(DynSymRegion.EntSize, 347263509Sdim (const char *)DynSymRegion.Addr + DynSymRegion.Size, 348263509Sdim true); 349263509Sdim return Elf_Sym_Iter(0, 0, true); 350252723Sdim } 351252723Sdim 352263509Sdim Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { 353252723Sdim return Elf_Rela_Iter(sec->sh_entsize, 354252723Sdim (const char *)(base() + sec->sh_offset)); 355252723Sdim } 356252723Sdim 357263509Sdim Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { 358263509Sdim return Elf_Rela_Iter( 359263509Sdim sec->sh_entsize, 360263509Sdim (const char *)(base() + sec->sh_offset + sec->sh_size)); 361245431Sdim } 362245431Sdim 363263509Sdim Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { 364252723Sdim return Elf_Rel_Iter(sec->sh_entsize, 365252723Sdim (const char *)(base() + sec->sh_offset)); 366245431Sdim } 367245431Sdim 368263509Sdim Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { 369263509Sdim return Elf_Rel_Iter(sec->sh_entsize, 370263509Sdim (const char *)(base() + sec->sh_offset + sec->sh_size)); 371245431Sdim } 372245431Sdim 373252723Sdim /// \brief Iterate over program header table. 374252723Sdim typedef ELFEntityIterator<const Elf_Phdr> Elf_Phdr_Iter; 375252723Sdim 376252723Sdim Elf_Phdr_Iter begin_program_headers() const { 377252723Sdim return Elf_Phdr_Iter(Header->e_phentsize, 378252723Sdim (const char*)base() + Header->e_phoff); 379252723Sdim } 380252723Sdim 381252723Sdim Elf_Phdr_Iter end_program_headers() const { 382252723Sdim return Elf_Phdr_Iter(Header->e_phentsize, 383252723Sdim (const char*)base() + 384252723Sdim Header->e_phoff + 385252723Sdim (Header->e_phnum * Header->e_phentsize)); 386252723Sdim } 387252723Sdim 388234285Sdim uint64_t getNumSections() const; 389263509Sdim uintX_t getStringTableIndex() const; 390234285Sdim ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; 391263509Sdim const Elf_Ehdr *getHeader() const { return Header; } 392234285Sdim const Elf_Shdr *getSection(const Elf_Sym *symb) const; 393263509Sdim const Elf_Shdr *getSection(uint32_t Index) const; 394263509Sdim const Elf_Sym *getSymbol(uint32_t index) const; 395234285Sdim 396263509Sdim ErrorOr<StringRef> getSymbolName(Elf_Sym_Iter Sym) const; 397263509Sdim 398263509Sdim /// \brief Get the name of \p Symb. 399263509Sdim /// \param SymTab The symbol table section \p Symb is contained in. 400263509Sdim /// \param Symb The symbol to get the name of. 401263509Sdim /// 402263509Sdim /// \p SymTab is used to lookup the string table to use to get the symbol's 403263509Sdim /// name. 404263509Sdim ErrorOr<StringRef> getSymbolName(const Elf_Shdr *SymTab, 405263509Sdim const Elf_Sym *Symb) const; 406263509Sdim ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const; 407263509Sdim uint64_t getSymbolIndex(const Elf_Sym *sym) const; 408263509Sdim ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const; 409263509Sdim StringRef getLoadName() const; 410234285Sdim}; 411234285Sdim 412263509Sdim// Use an alignment of 2 for the typedefs since that is the worst case for 413263509Sdim// ELF files in archives. 414263509Sdimtypedef ELFFile<ELFType<support::little, 2, false> > ELF32LEFile; 415263509Sdimtypedef ELFFile<ELFType<support::little, 2, true> > ELF64LEFile; 416263509Sdimtypedef ELFFile<ELFType<support::big, 2, false> > ELF32BEFile; 417263509Sdimtypedef ELFFile<ELFType<support::big, 2, true> > ELF64BEFile; 418263509Sdim 419234285Sdim// Iterate through the version definitions, and place each Elf_Verdef 420234285Sdim// in the VersionMap according to its index. 421263509Sdimtemplate <class ELFT> 422263509Sdimvoid ELFFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { 423263509Sdim unsigned vd_size = sec->sh_size; // Size of section in bytes 424234285Sdim unsigned vd_count = sec->sh_info; // Number of Verdef entries 425234285Sdim const char *sec_start = (const char*)base() + sec->sh_offset; 426234285Sdim const char *sec_end = sec_start + vd_size; 427234285Sdim // The first Verdef entry is at the start of the section. 428234285Sdim const char *p = sec_start; 429234285Sdim for (unsigned i = 0; i < vd_count; i++) { 430234285Sdim if (p + sizeof(Elf_Verdef) > sec_end) 431234285Sdim report_fatal_error("Section ended unexpectedly while scanning " 432234285Sdim "version definitions."); 433234285Sdim const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p); 434234285Sdim if (vd->vd_version != ELF::VER_DEF_CURRENT) 435234285Sdim report_fatal_error("Unexpected verdef version"); 436234285Sdim size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; 437234285Sdim if (index >= VersionMap.size()) 438263509Sdim VersionMap.resize(index + 1); 439234285Sdim VersionMap[index] = VersionMapEntry(vd); 440234285Sdim p += vd->vd_next; 441234285Sdim } 442234285Sdim} 443234285Sdim 444234285Sdim// Iterate through the versions needed section, and place each Elf_Vernaux 445234285Sdim// in the VersionMap according to its index. 446263509Sdimtemplate <class ELFT> 447263509Sdimvoid ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { 448263509Sdim unsigned vn_size = sec->sh_size; // Size of section in bytes 449234285Sdim unsigned vn_count = sec->sh_info; // Number of Verneed entries 450263509Sdim const char *sec_start = (const char *)base() + sec->sh_offset; 451234285Sdim const char *sec_end = sec_start + vn_size; 452234285Sdim // The first Verneed entry is at the start of the section. 453234285Sdim const char *p = sec_start; 454234285Sdim for (unsigned i = 0; i < vn_count; i++) { 455234285Sdim if (p + sizeof(Elf_Verneed) > sec_end) 456234285Sdim report_fatal_error("Section ended unexpectedly while scanning " 457234285Sdim "version needed records."); 458234285Sdim const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p); 459234285Sdim if (vn->vn_version != ELF::VER_NEED_CURRENT) 460234285Sdim report_fatal_error("Unexpected verneed version"); 461234285Sdim // Iterate through the Vernaux entries 462234285Sdim const char *paux = p + vn->vn_aux; 463234285Sdim for (unsigned j = 0; j < vn->vn_cnt; j++) { 464234285Sdim if (paux + sizeof(Elf_Vernaux) > sec_end) 465234285Sdim report_fatal_error("Section ended unexpected while scanning auxiliary " 466234285Sdim "version needed records."); 467234285Sdim const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux); 468234285Sdim size_t index = vna->vna_other & ELF::VERSYM_VERSION; 469234285Sdim if (index >= VersionMap.size()) 470263509Sdim VersionMap.resize(index + 1); 471234285Sdim VersionMap[index] = VersionMapEntry(vna); 472234285Sdim paux += vna->vna_next; 473234285Sdim } 474234285Sdim p += vn->vn_next; 475234285Sdim } 476234285Sdim} 477234285Sdim 478263509Sdimtemplate <class ELFT> 479263509Sdimvoid ELFFile<ELFT>::LoadVersionMap() const { 480234285Sdim // If there is no dynamic symtab or version table, there is nothing to do. 481263509Sdim if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL) 482234285Sdim return; 483234285Sdim 484234285Sdim // Has the VersionMap already been loaded? 485234285Sdim if (VersionMap.size() > 0) 486234285Sdim return; 487234285Sdim 488234285Sdim // The first two version indexes are reserved. 489234285Sdim // Index 0 is LOCAL, index 1 is GLOBAL. 490234285Sdim VersionMap.push_back(VersionMapEntry()); 491234285Sdim VersionMap.push_back(VersionMapEntry()); 492234285Sdim 493234285Sdim if (dot_gnu_version_d_sec) 494234285Sdim LoadVersionDefs(dot_gnu_version_d_sec); 495234285Sdim 496234285Sdim if (dot_gnu_version_r_sec) 497234285Sdim LoadVersionNeeds(dot_gnu_version_r_sec); 498234285Sdim} 499234285Sdim 500263509Sdimtemplate <class ELFT> 501263509SdimELF::Elf64_Word ELFFile<ELFT>::getSymbolTableIndex(const Elf_Sym *symb) const { 502234285Sdim if (symb->st_shndx == ELF::SHN_XINDEX) 503234285Sdim return ExtendedSymbolTable.lookup(symb); 504234285Sdim return symb->st_shndx; 505234285Sdim} 506234285Sdim 507263509Sdimtemplate <class ELFT> 508263509Sdimconst typename ELFFile<ELFT>::Elf_Shdr * 509263509SdimELFFile<ELFT>::getSection(const Elf_Sym *symb) const { 510234285Sdim if (symb->st_shndx == ELF::SHN_XINDEX) 511234285Sdim return getSection(ExtendedSymbolTable.lookup(symb)); 512234285Sdim if (symb->st_shndx >= ELF::SHN_LORESERVE) 513234285Sdim return 0; 514234285Sdim return getSection(symb->st_shndx); 515234285Sdim} 516234285Sdim 517263509Sdimtemplate <class ELFT> 518263509Sdimconst typename ELFFile<ELFT>::Elf_Sym * 519263509SdimELFFile<ELFT>::getSymbol(uint32_t Index) const { 520263509Sdim return &*(begin_symbols() + Index); 521252723Sdim} 522252723Sdim 523263509Sdimtemplate <class ELFT> 524263509SdimErrorOr<ArrayRef<uint8_t> > 525263509SdimELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { 526263509Sdim if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) 527263509Sdim return object_error::parse_failed; 528263509Sdim const uint8_t *Start = base() + Sec->sh_offset; 529263509Sdim return ArrayRef<uint8_t>(Start, Sec->sh_size); 530245431Sdim} 531245431Sdim 532263509Sdimtemplate <class ELFT> 533263509SdimStringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { 534263509Sdim return getELFRelocationTypeName(Header->e_machine, Type); 535245431Sdim} 536245431Sdim 537263509Sdimtemplate <class ELFT> 538263509Sdimvoid ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, 539263509Sdim SmallVectorImpl<char> &Result) const { 540252723Sdim if (!isMips64EL()) { 541263509Sdim StringRef Name = getRelocationTypeName(Type); 542252723Sdim Result.append(Name.begin(), Name.end()); 543252723Sdim } else { 544263509Sdim uint8_t Type1 = (Type >> 0) & 0xFF; 545263509Sdim uint8_t Type2 = (Type >> 8) & 0xFF; 546263509Sdim uint8_t Type3 = (Type >> 16) & 0xFF; 547252723Sdim 548252723Sdim // Concat all three relocation type names. 549252723Sdim StringRef Name = getRelocationTypeName(Type1); 550252723Sdim Result.append(Name.begin(), Name.end()); 551252723Sdim 552252723Sdim Name = getRelocationTypeName(Type2); 553252723Sdim Result.append(1, '/'); 554252723Sdim Result.append(Name.begin(), Name.end()); 555252723Sdim 556252723Sdim Name = getRelocationTypeName(Type3); 557252723Sdim Result.append(1, '/'); 558252723Sdim Result.append(Name.begin(), Name.end()); 559252723Sdim } 560252723Sdim} 561252723Sdim 562263509Sdimtemplate <class ELFT> 563263509Sdimtemplate <class RelT> 564263509Sdimstd::pair<const typename ELFFile<ELFT>::Elf_Shdr *, 565263509Sdim const typename ELFFile<ELFT>::Elf_Sym *> 566263509SdimELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { 567263509Sdim if (!Sec->sh_link) 568263509Sdim return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0); 569263509Sdim const Elf_Shdr *SymTable = getSection(Sec->sh_link); 570263509Sdim return std::make_pair( 571263509Sdim SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL()))); 572234285Sdim} 573234285Sdim 574234285Sdim// Verify that the last byte in the string table in a null. 575263509Sdimtemplate <class ELFT> 576263509Sdimvoid ELFFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { 577263509Sdim const char *strtab = (const char *)base() + sh->sh_offset; 578234285Sdim if (strtab[sh->sh_size - 1] != 0) 579234285Sdim // FIXME: Proper error handling. 580234285Sdim report_fatal_error("String table must end with a null terminator!"); 581234285Sdim} 582234285Sdim 583263509Sdimtemplate <class ELFT> 584263509Sdimuint64_t ELFFile<ELFT>::getNumSections() const { 585263509Sdim assert(Header && "Header not initialized!"); 586263509Sdim if (Header->e_shnum == ELF::SHN_UNDEF) { 587263509Sdim assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); 588263509Sdim return SectionHeaderTable->sh_size; 589263509Sdim } 590263509Sdim return Header->e_shnum; 591263509Sdim} 592234285Sdim 593263509Sdimtemplate <class ELFT> 594263509Sdimtypename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const { 595263509Sdim if (Header->e_shnum == ELF::SHN_UNDEF) { 596263509Sdim if (Header->e_shstrndx == ELF::SHN_HIRESERVE) 597263509Sdim return SectionHeaderTable->sh_link; 598263509Sdim if (Header->e_shstrndx >= getNumSections()) 599263509Sdim return 0; 600263509Sdim } 601263509Sdim return Header->e_shstrndx; 602263509Sdim} 603234285Sdim 604263509Sdimtemplate <class ELFT> 605263509SdimELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec) 606263509Sdim : Buf(Object), 607263509Sdim SectionHeaderTable(0), 608263509Sdim dot_shstrtab_sec(0), 609263509Sdim dot_strtab_sec(0), 610263509Sdim dot_symtab_sec(0), 611263509Sdim SymbolTableSectionHeaderIndex(0), 612263509Sdim dot_gnu_version_sec(0), 613263509Sdim dot_gnu_version_r_sec(0), 614263509Sdim dot_gnu_version_d_sec(0), 615263509Sdim dt_soname(0) { 616263509Sdim const uint64_t FileSize = Buf->getBufferSize(); 617263509Sdim 618234285Sdim if (sizeof(Elf_Ehdr) > FileSize) 619234285Sdim // FIXME: Proper error handling. 620234285Sdim report_fatal_error("File too short!"); 621234285Sdim 622234285Sdim Header = reinterpret_cast<const Elf_Ehdr *>(base()); 623234285Sdim 624234285Sdim if (Header->e_shoff == 0) 625234285Sdim return; 626234285Sdim 627234285Sdim const uint64_t SectionTableOffset = Header->e_shoff; 628234285Sdim 629234285Sdim if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) 630234285Sdim // FIXME: Proper error handling. 631234285Sdim report_fatal_error("Section header table goes past end of file!"); 632234285Sdim 633234285Sdim // The getNumSections() call below depends on SectionHeaderTable being set. 634234285Sdim SectionHeaderTable = 635234285Sdim reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); 636234285Sdim const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; 637234285Sdim 638234285Sdim if (SectionTableOffset + SectionTableSize > FileSize) 639234285Sdim // FIXME: Proper error handling. 640234285Sdim report_fatal_error("Section table goes past end of file!"); 641234285Sdim 642263509Sdim // Scan sections for special sections. 643234285Sdim 644263509Sdim for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections(); 645263509Sdim SecI != SecE; ++SecI) { 646263509Sdim switch (SecI->sh_type) { 647263509Sdim case ELF::SHT_SYMTAB_SHNDX: 648234285Sdim if (SymbolTableSectionHeaderIndex) 649234285Sdim // FIXME: Proper error handling. 650234285Sdim report_fatal_error("More than one .symtab_shndx!"); 651263509Sdim SymbolTableSectionHeaderIndex = &*SecI; 652234285Sdim break; 653263509Sdim case ELF::SHT_SYMTAB: 654263509Sdim if (dot_symtab_sec) 655263509Sdim // FIXME: Proper error handling. 656263509Sdim report_fatal_error("More than one .symtab!"); 657263509Sdim dot_symtab_sec = &*SecI; 658263509Sdim dot_strtab_sec = getSection(SecI->sh_link); 659234285Sdim break; 660234285Sdim case ELF::SHT_DYNSYM: { 661263509Sdim if (DynSymRegion.Addr) 662234285Sdim // FIXME: Proper error handling. 663234285Sdim report_fatal_error("More than one .dynsym!"); 664263509Sdim DynSymRegion.Addr = base() + SecI->sh_offset; 665263509Sdim DynSymRegion.Size = SecI->sh_size; 666263509Sdim DynSymRegion.EntSize = SecI->sh_entsize; 667263509Sdim const Elf_Shdr *DynStr = getSection(SecI->sh_link); 668263509Sdim DynStrRegion.Addr = base() + DynStr->sh_offset; 669263509Sdim DynStrRegion.Size = DynStr->sh_size; 670263509Sdim DynStrRegion.EntSize = DynStr->sh_entsize; 671234285Sdim break; 672234285Sdim } 673263509Sdim case ELF::SHT_DYNAMIC: 674263509Sdim if (DynamicRegion.Addr) 675234285Sdim // FIXME: Proper error handling. 676234285Sdim report_fatal_error("More than one .dynamic!"); 677263509Sdim DynamicRegion.Addr = base() + SecI->sh_offset; 678263509Sdim DynamicRegion.Size = SecI->sh_size; 679263509Sdim DynamicRegion.EntSize = SecI->sh_entsize; 680234285Sdim break; 681263509Sdim case ELF::SHT_GNU_versym: 682234285Sdim if (dot_gnu_version_sec != NULL) 683234285Sdim // FIXME: Proper error handling. 684234285Sdim report_fatal_error("More than one .gnu.version section!"); 685263509Sdim dot_gnu_version_sec = &*SecI; 686234285Sdim break; 687263509Sdim case ELF::SHT_GNU_verdef: 688234285Sdim if (dot_gnu_version_d_sec != NULL) 689234285Sdim // FIXME: Proper error handling. 690234285Sdim report_fatal_error("More than one .gnu.version_d section!"); 691263509Sdim dot_gnu_version_d_sec = &*SecI; 692234285Sdim break; 693263509Sdim case ELF::SHT_GNU_verneed: 694234285Sdim if (dot_gnu_version_r_sec != NULL) 695234285Sdim // FIXME: Proper error handling. 696234285Sdim report_fatal_error("More than one .gnu.version_r section!"); 697263509Sdim dot_gnu_version_r_sec = &*SecI; 698234285Sdim break; 699234285Sdim } 700234285Sdim } 701234285Sdim 702234285Sdim // Get string table sections. 703234285Sdim dot_shstrtab_sec = getSection(getStringTableIndex()); 704234285Sdim if (dot_shstrtab_sec) { 705234285Sdim // Verify that the last byte in the string table in a null. 706234285Sdim VerifyStrTab(dot_shstrtab_sec); 707234285Sdim } 708234285Sdim 709234285Sdim // Build symbol name side-mapping if there is one. 710234285Sdim if (SymbolTableSectionHeaderIndex) { 711234285Sdim const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() + 712234285Sdim SymbolTableSectionHeaderIndex->sh_offset); 713263509Sdim for (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE; 714263509Sdim ++SI) { 715234285Sdim if (*ShndxTable != ELF::SHN_UNDEF) 716263509Sdim ExtendedSymbolTable[&*SI] = *ShndxTable; 717234285Sdim ++ShndxTable; 718234285Sdim } 719234285Sdim } 720263509Sdim 721263509Sdim // Scan program headers. 722263509Sdim for (Elf_Phdr_Iter PhdrI = begin_program_headers(), 723263509Sdim PhdrE = end_program_headers(); 724263509Sdim PhdrI != PhdrE; ++PhdrI) { 725263509Sdim if (PhdrI->p_type == ELF::PT_DYNAMIC) { 726263509Sdim DynamicRegion.Addr = base() + PhdrI->p_offset; 727263509Sdim DynamicRegion.Size = PhdrI->p_filesz; 728263509Sdim DynamicRegion.EntSize = sizeof(Elf_Dyn); 729263509Sdim break; 730263509Sdim } 731263509Sdim } 732263509Sdim 733263509Sdim ec = error_code::success(); 734234285Sdim} 735234285Sdim 736252723Sdim// Get the symbol table index in the symtab section given a symbol 737263509Sdimtemplate <class ELFT> 738263509Sdimuint64_t ELFFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { 739252723Sdim uintptr_t SymLoc = uintptr_t(Sym); 740263509Sdim uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); 741252723Sdim assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); 742252723Sdim uint64_t SymOffset = SymLoc - SymTabLoc; 743263509Sdim assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && 744252723Sdim "Symbol not multiple of symbol size!"); 745263509Sdim return SymOffset / dot_symtab_sec->sh_entsize; 746252723Sdim} 747252723Sdim 748263509Sdimtemplate <class ELFT> 749263509Sdimtypename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::begin_sections() const { 750263509Sdim return Elf_Shdr_Iter(Header->e_shentsize, 751263509Sdim (const char *)base() + Header->e_shoff); 752234285Sdim} 753234285Sdim 754263509Sdimtemplate <class ELFT> 755263509Sdimtypename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::end_sections() const { 756263509Sdim return Elf_Shdr_Iter(Header->e_shentsize, 757263509Sdim (const char *)base() + Header->e_shoff + 758263509Sdim (getNumSections() * Header->e_shentsize)); 759234285Sdim} 760234285Sdim 761263509Sdimtemplate <class ELFT> 762263509Sdimtypename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const { 763263509Sdim if (!dot_symtab_sec) 764263509Sdim return Elf_Sym_Iter(0, 0, false); 765263509Sdim return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, 766263509Sdim (const char *)base() + dot_symtab_sec->sh_offset, false); 767234285Sdim} 768234285Sdim 769263509Sdimtemplate <class ELFT> 770263509Sdimtypename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::end_symbols() const { 771263509Sdim if (!dot_symtab_sec) 772263509Sdim return Elf_Sym_Iter(0, 0, false); 773263509Sdim return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, 774263509Sdim (const char *)base() + dot_symtab_sec->sh_offset + 775263509Sdim dot_symtab_sec->sh_size, 776263509Sdim false); 777234285Sdim} 778234285Sdim 779263509Sdimtemplate <class ELFT> 780263509Sdimtypename ELFFile<ELFT>::Elf_Dyn_Iter 781263509SdimELFFile<ELFT>::begin_dynamic_table() const { 782263509Sdim if (DynamicRegion.Addr) 783263509Sdim return Elf_Dyn_Iter(DynamicRegion.EntSize, 784263509Sdim (const char *)DynamicRegion.Addr); 785263509Sdim return Elf_Dyn_Iter(0, 0); 786234285Sdim} 787234285Sdim 788263509Sdimtemplate <class ELFT> 789263509Sdimtypename ELFFile<ELFT>::Elf_Dyn_Iter 790263509SdimELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const { 791263509Sdim if (!DynamicRegion.Addr) 792263509Sdim return Elf_Dyn_Iter(0, 0); 793263509Sdim Elf_Dyn_Iter Ret(DynamicRegion.EntSize, 794263509Sdim (const char *)DynamicRegion.Addr + DynamicRegion.Size); 795234285Sdim 796263509Sdim if (NULLEnd) { 797263509Sdim Elf_Dyn_Iter Start = begin_dynamic_table(); 798263509Sdim while (Start != Ret && Start->getTag() != ELF::DT_NULL) 799263509Sdim ++Start; 800234285Sdim 801263509Sdim // Include the DT_NULL. 802263509Sdim if (Start != Ret) 803263509Sdim ++Start; 804263509Sdim Ret = Start; 805234285Sdim } 806263509Sdim return Ret; 807234285Sdim} 808234285Sdim 809263509Sdimtemplate <class ELFT> 810263509SdimStringRef ELFFile<ELFT>::getLoadName() const { 811234285Sdim if (!dt_soname) { 812234285Sdim // Find the DT_SONAME entry 813263509Sdim Elf_Dyn_Iter it = begin_dynamic_table(); 814263509Sdim Elf_Dyn_Iter ie = end_dynamic_table(); 815252723Sdim while (it != ie && it->getTag() != ELF::DT_SONAME) 816252723Sdim ++it; 817252723Sdim 818234285Sdim if (it != ie) { 819263509Sdim dt_soname = getDynamicString(it->getVal()); 820234285Sdim } else { 821234285Sdim dt_soname = ""; 822234285Sdim } 823234285Sdim } 824234285Sdim return dt_soname; 825234285Sdim} 826234285Sdim 827263509Sdimtemplate <class ELFT> 828263509Sdimtemplate <typename T> 829263509Sdimconst T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { 830234285Sdim return getEntry<T>(getSection(Section), Entry); 831234285Sdim} 832234285Sdim 833263509Sdimtemplate <class ELFT> 834263509Sdimtemplate <typename T> 835263509Sdimconst T *ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, 836263509Sdim uint32_t Entry) const { 837263509Sdim return reinterpret_cast<const T *>(base() + Section->sh_offset + 838263509Sdim (Entry * Section->sh_entsize)); 839234285Sdim} 840234285Sdim 841263509Sdimtemplate <class ELFT> 842263509Sdimconst typename ELFFile<ELFT>::Elf_Shdr * 843263509SdimELFFile<ELFT>::getSection(uint32_t index) const { 844234285Sdim if (index == 0) 845234285Sdim return 0; 846234285Sdim if (!SectionHeaderTable || index >= getNumSections()) 847234285Sdim // FIXME: Proper error handling. 848234285Sdim report_fatal_error("Invalid section index!"); 849234285Sdim 850234285Sdim return reinterpret_cast<const Elf_Shdr *>( 851234285Sdim reinterpret_cast<const char *>(SectionHeaderTable) 852234285Sdim + (index * Header->e_shentsize)); 853234285Sdim} 854234285Sdim 855263509Sdimtemplate <class ELFT> 856263509Sdimconst char *ELFFile<ELFT>::getString(uint32_t section, 857263509Sdim ELF::Elf32_Word offset) const { 858234285Sdim return getString(getSection(section), offset); 859234285Sdim} 860234285Sdim 861263509Sdimtemplate <class ELFT> 862263509Sdimconst char *ELFFile<ELFT>::getString(const Elf_Shdr *section, 863263509Sdim ELF::Elf32_Word offset) const { 864234285Sdim assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 865234285Sdim if (offset >= section->sh_size) 866234285Sdim // FIXME: Proper error handling. 867234285Sdim report_fatal_error("Symbol name offset outside of string table!"); 868234285Sdim return (const char *)base() + section->sh_offset + offset; 869234285Sdim} 870234285Sdim 871263509Sdimtemplate <class ELFT> 872263509Sdimconst char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const { 873263509Sdim if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) 874263509Sdim return 0; 875263509Sdim return (const char *)DynStrRegion.Addr + Offset; 876263509Sdim} 877263509Sdim 878263509Sdimtemplate <class ELFT> 879263509SdimErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(Elf_Sym_Iter Sym) const { 880263509Sdim if (!Sym.isDynamic()) 881263509Sdim return getSymbolName(dot_symtab_sec, &*Sym); 882263509Sdim 883263509Sdim if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size) 884263509Sdim return object_error::parse_failed; 885263509Sdim return StringRef(getDynamicString(Sym->st_name)); 886263509Sdim} 887263509Sdim 888263509Sdimtemplate <class ELFT> 889263509SdimErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section, 890263509Sdim const Elf_Sym *Symb) const { 891263509Sdim if (Symb->st_name == 0) { 892263509Sdim const Elf_Shdr *ContainingSec = getSection(Symb); 893263509Sdim if (ContainingSec) 894263509Sdim return getSectionName(ContainingSec); 895234285Sdim } 896234285Sdim 897263509Sdim const Elf_Shdr *StrTab = getSection(Section->sh_link); 898263509Sdim if (Symb->st_name >= StrTab->sh_size) 899263509Sdim return object_error::parse_failed; 900263509Sdim return StringRef(getString(StrTab, Symb->st_name)); 901234285Sdim} 902234285Sdim 903263509Sdimtemplate <class ELFT> 904263509SdimErrorOr<StringRef> 905263509SdimELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { 906263509Sdim if (Section->sh_name >= dot_shstrtab_sec->sh_size) 907263509Sdim return object_error::parse_failed; 908263509Sdim return StringRef(getString(dot_shstrtab_sec, Section->sh_name)); 909245431Sdim} 910245431Sdim 911263509Sdimtemplate <class ELFT> 912263509SdimErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, 913263509Sdim const Elf_Sym *symb, 914263509Sdim bool &IsDefault) const { 915234285Sdim // Handle non-dynamic symbols. 916263509Sdim if (section != DynSymRegion.Addr && section != 0) { 917234285Sdim // Non-dynamic symbols can have versions in their names 918234285Sdim // A name of the form 'foo@V1' indicates version 'V1', non-default. 919234285Sdim // A name of the form 'foo@@V2' indicates version 'V2', default version. 920263509Sdim ErrorOr<StringRef> SymName = getSymbolName(section, symb); 921263509Sdim if (!SymName) 922263509Sdim return SymName; 923263509Sdim StringRef Name = *SymName; 924234285Sdim size_t atpos = Name.find('@'); 925234285Sdim if (atpos == StringRef::npos) { 926234285Sdim IsDefault = false; 927263509Sdim return StringRef(""); 928234285Sdim } 929234285Sdim ++atpos; 930234285Sdim if (atpos < Name.size() && Name[atpos] == '@') { 931234285Sdim IsDefault = true; 932234285Sdim ++atpos; 933234285Sdim } else { 934234285Sdim IsDefault = false; 935234285Sdim } 936263509Sdim return Name.substr(atpos); 937234285Sdim } 938234285Sdim 939234285Sdim // This is a dynamic symbol. Look in the GNU symbol version table. 940234285Sdim if (dot_gnu_version_sec == NULL) { 941234285Sdim // No version table. 942234285Sdim IsDefault = false; 943263509Sdim return StringRef(""); 944234285Sdim } 945234285Sdim 946234285Sdim // Determine the position in the symbol table of this entry. 947263509Sdim size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / 948263509Sdim DynSymRegion.EntSize; 949234285Sdim 950234285Sdim // Get the corresponding version index entry 951234285Sdim const Elf_Versym *vs = getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index); 952234285Sdim size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; 953234285Sdim 954234285Sdim // Special markers for unversioned symbols. 955234285Sdim if (version_index == ELF::VER_NDX_LOCAL || 956234285Sdim version_index == ELF::VER_NDX_GLOBAL) { 957234285Sdim IsDefault = false; 958263509Sdim return StringRef(""); 959234285Sdim } 960234285Sdim 961234285Sdim // Lookup this symbol in the version table 962234285Sdim LoadVersionMap(); 963234285Sdim if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) 964263509Sdim return object_error::parse_failed; 965234285Sdim const VersionMapEntry &entry = VersionMap[version_index]; 966234285Sdim 967234285Sdim // Get the version name string 968234285Sdim size_t name_offset; 969234285Sdim if (entry.isVerdef()) { 970234285Sdim // The first Verdaux entry holds the name. 971234285Sdim name_offset = entry.getVerdef()->getAux()->vda_name; 972234285Sdim } else { 973234285Sdim name_offset = entry.getVernaux()->vna_name; 974234285Sdim } 975234285Sdim 976234285Sdim // Set IsDefault 977234285Sdim if (entry.isVerdef()) { 978234285Sdim IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN); 979234285Sdim } else { 980234285Sdim IsDefault = false; 981234285Sdim } 982234285Sdim 983263509Sdim if (name_offset >= DynStrRegion.Size) 984263509Sdim return object_error::parse_failed; 985263509Sdim return StringRef(getDynamicString(name_offset)); 986234285Sdim} 987234285Sdim 988252723Sdim/// This function returns the hash value for a symbol in the .dynsym section 989252723Sdim/// Name of the API remains consistent as specified in the libelf 990252723Sdim/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash 991252723Sdimstatic inline unsigned elf_hash(StringRef &symbolName) { 992252723Sdim unsigned h = 0, g; 993252723Sdim for (unsigned i = 0, j = symbolName.size(); i < j; i++) { 994252723Sdim h = (h << 4) + symbolName[i]; 995252723Sdim g = h & 0xf0000000L; 996252723Sdim if (g != 0) 997252723Sdim h ^= g >> 24; 998252723Sdim h &= ~g; 999252723Sdim } 1000252723Sdim return h; 1001234285Sdim} 1002263509Sdim} // end namespace object 1003263509Sdim} // end namespace llvm 1004252723Sdim 1005234285Sdim#endif 1006