1//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file declares the ELFFile template class. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_OBJECT_ELF_H 15#define LLVM_OBJECT_ELF_H 16 17#include "llvm/ADT/ArrayRef.h" 18#include "llvm/ADT/SmallVector.h" 19#include "llvm/ADT/StringRef.h" 20#include "llvm/BinaryFormat/ELF.h" 21#include "llvm/Object/ELFTypes.h" 22#include "llvm/Object/Error.h" 23#include "llvm/Support/Endian.h" 24#include "llvm/Support/Error.h" 25#include <cassert> 26#include <cstddef> 27#include <cstdint> 28#include <limits> 29#include <utility> 30 31namespace llvm { 32namespace object { 33 34StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); 35StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); 36 37// Subclasses of ELFFile may need this for template instantiation 38inline std::pair<unsigned char, unsigned char> 39getElfArchType(StringRef Object) { 40 if (Object.size() < ELF::EI_NIDENT) 41 return std::make_pair((uint8_t)ELF::ELFCLASSNONE, 42 (uint8_t)ELF::ELFDATANONE); 43 return std::make_pair((uint8_t)Object[ELF::EI_CLASS], 44 (uint8_t)Object[ELF::EI_DATA]); 45} 46 47static inline Error createError(StringRef Err) { 48 return make_error<StringError>(Err, object_error::parse_failed); 49} 50 51template <class ELFT> 52class ELFFile { 53public: 54 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 55 using uintX_t = typename ELFT::uint; 56 using Elf_Ehdr = typename ELFT::Ehdr; 57 using Elf_Shdr = typename ELFT::Shdr; 58 using Elf_Sym = typename ELFT::Sym; 59 using Elf_Dyn = typename ELFT::Dyn; 60 using Elf_Phdr = typename ELFT::Phdr; 61 using Elf_Rel = typename ELFT::Rel; 62 using Elf_Rela = typename ELFT::Rela; 63 using Elf_Verdef = typename ELFT::Verdef; 64 using Elf_Verdaux = typename ELFT::Verdaux; 65 using Elf_Verneed = typename ELFT::Verneed; 66 using Elf_Vernaux = typename ELFT::Vernaux; 67 using Elf_Versym = typename ELFT::Versym; 68 using Elf_Hash = typename ELFT::Hash; 69 using Elf_GnuHash = typename ELFT::GnuHash; 70 using Elf_Dyn_Range = typename ELFT::DynRange; 71 using Elf_Shdr_Range = typename ELFT::ShdrRange; 72 using Elf_Sym_Range = typename ELFT::SymRange; 73 using Elf_Rel_Range = typename ELFT::RelRange; 74 using Elf_Rela_Range = typename ELFT::RelaRange; 75 using Elf_Phdr_Range = typename ELFT::PhdrRange; 76 77 const uint8_t *base() const { 78 return reinterpret_cast<const uint8_t *>(Buf.data()); 79 } 80 81 size_t getBufSize() const { return Buf.size(); } 82 83private: 84 StringRef Buf; 85 86 ELFFile(StringRef Object); 87 88public: 89 const Elf_Ehdr *getHeader() const { 90 return reinterpret_cast<const Elf_Ehdr *>(base()); 91 } 92 93 template <typename T> 94 Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; 95 template <typename T> 96 Expected<const T *> getEntry(const Elf_Shdr *Section, uint32_t Entry) const; 97 98 Expected<StringRef> getStringTable(const Elf_Shdr *Section) const; 99 Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; 100 Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, 101 Elf_Shdr_Range Sections) const; 102 103 Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; 104 Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, 105 Elf_Shdr_Range Sections) const; 106 107 void VerifyStrTab(const Elf_Shdr *sh) const; 108 109 StringRef getRelocationTypeName(uint32_t Type) const; 110 void getRelocationTypeName(uint32_t Type, 111 SmallVectorImpl<char> &Result) const; 112 113 /// \brief Get the symbol for a given relocation. 114 Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, 115 const Elf_Shdr *SymTab) const; 116 117 static Expected<ELFFile> create(StringRef Object); 118 119 bool isMipsELF64() const { 120 return getHeader()->e_machine == ELF::EM_MIPS && 121 getHeader()->getFileClass() == ELF::ELFCLASS64; 122 } 123 124 bool isMips64EL() const { 125 return isMipsELF64() && 126 getHeader()->getDataEncoding() == ELF::ELFDATA2LSB; 127 } 128 129 Expected<Elf_Shdr_Range> sections() const; 130 131 Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { 132 if (!Sec) 133 return makeArrayRef<Elf_Sym>(nullptr, nullptr); 134 return getSectionContentsAsArray<Elf_Sym>(Sec); 135 } 136 137 Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const { 138 return getSectionContentsAsArray<Elf_Rela>(Sec); 139 } 140 141 Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const { 142 return getSectionContentsAsArray<Elf_Rel>(Sec); 143 } 144 145 /// \brief Iterate over program header table. 146 Expected<Elf_Phdr_Range> program_headers() const { 147 if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) 148 return createError("invalid e_phentsize"); 149 if (getHeader()->e_phoff + 150 (getHeader()->e_phnum * getHeader()->e_phentsize) > 151 getBufSize()) 152 return createError("program headers longer than binary"); 153 auto *Begin = 154 reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff); 155 return makeArrayRef(Begin, Begin + getHeader()->e_phnum); 156 } 157 158 Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const; 159 Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, 160 ArrayRef<Elf_Word> ShndxTable) const; 161 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, 162 const Elf_Shdr *SymTab, 163 ArrayRef<Elf_Word> ShndxTable) const; 164 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, 165 Elf_Sym_Range Symtab, 166 ArrayRef<Elf_Word> ShndxTable) const; 167 Expected<const Elf_Shdr *> getSection(uint32_t Index) const; 168 169 Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, 170 uint32_t Index) const; 171 172 Expected<StringRef> getSectionName(const Elf_Shdr *Section) const; 173 Expected<StringRef> getSectionName(const Elf_Shdr *Section, 174 StringRef DotShstrtab) const; 175 template <typename T> 176 Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const; 177 Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const; 178}; 179 180using ELF32LEFile = ELFFile<ELFType<support::little, false>>; 181using ELF64LEFile = ELFFile<ELFType<support::little, true>>; 182using ELF32BEFile = ELFFile<ELFType<support::big, false>>; 183using ELF64BEFile = ELFFile<ELFType<support::big, true>>; 184 185template <class ELFT> 186inline Expected<const typename ELFT::Shdr *> 187getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { 188 if (Index >= Sections.size()) 189 return createError("invalid section index"); 190 return &Sections[Index]; 191} 192 193template <class ELFT> 194inline Expected<uint32_t> 195getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym, 196 const typename ELFT::Sym *FirstSym, 197 ArrayRef<typename ELFT::Word> ShndxTable) { 198 assert(Sym->st_shndx == ELF::SHN_XINDEX); 199 unsigned Index = Sym - FirstSym; 200 if (Index >= ShndxTable.size()) 201 return createError("index past the end of the symbol table"); 202 203 // The size of the table was checked in getSHNDXTable. 204 return ShndxTable[Index]; 205} 206 207template <class ELFT> 208Expected<uint32_t> 209ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, 210 ArrayRef<Elf_Word> ShndxTable) const { 211 uint32_t Index = Sym->st_shndx; 212 if (Index == ELF::SHN_XINDEX) { 213 auto ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>( 214 Sym, Syms.begin(), ShndxTable); 215 if (!ErrorOrIndex) 216 return ErrorOrIndex.takeError(); 217 return *ErrorOrIndex; 218 } 219 if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) 220 return 0; 221 return Index; 222} 223 224template <class ELFT> 225Expected<const typename ELFT::Shdr *> 226ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, 227 ArrayRef<Elf_Word> ShndxTable) const { 228 auto SymsOrErr = symbols(SymTab); 229 if (!SymsOrErr) 230 return SymsOrErr.takeError(); 231 return getSection(Sym, *SymsOrErr, ShndxTable); 232} 233 234template <class ELFT> 235Expected<const typename ELFT::Shdr *> 236ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols, 237 ArrayRef<Elf_Word> ShndxTable) const { 238 auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable); 239 if (!IndexOrErr) 240 return IndexOrErr.takeError(); 241 uint32_t Index = *IndexOrErr; 242 if (Index == 0) 243 return nullptr; 244 return getSection(Index); 245} 246 247template <class ELFT> 248inline Expected<const typename ELFT::Sym *> 249getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) { 250 if (Index >= Symbols.size()) 251 return createError("invalid symbol index"); 252 return &Symbols[Index]; 253} 254 255template <class ELFT> 256Expected<const typename ELFT::Sym *> 257ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { 258 auto SymtabOrErr = symbols(Sec); 259 if (!SymtabOrErr) 260 return SymtabOrErr.takeError(); 261 return object::getSymbol<ELFT>(*SymtabOrErr, Index); 262} 263 264template <class ELFT> 265template <typename T> 266Expected<ArrayRef<T>> 267ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { 268 if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1) 269 return createError("invalid sh_entsize"); 270 271 uintX_t Offset = Sec->sh_offset; 272 uintX_t Size = Sec->sh_size; 273 274 if (Size % sizeof(T)) 275 return createError("size is not a multiple of sh_entsize"); 276 if ((std::numeric_limits<uintX_t>::max() - Offset < Size) || 277 Offset + Size > Buf.size()) 278 return createError("invalid section offset"); 279 280 const T *Start = reinterpret_cast<const T *>(base() + Offset); 281 return makeArrayRef(Start, Size / sizeof(T)); 282} 283 284template <class ELFT> 285Expected<ArrayRef<uint8_t>> 286ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { 287 return getSectionContentsAsArray<uint8_t>(Sec); 288} 289 290template <class ELFT> 291StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { 292 return getELFRelocationTypeName(getHeader()->e_machine, Type); 293} 294 295template <class ELFT> 296void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, 297 SmallVectorImpl<char> &Result) const { 298 if (!isMipsELF64()) { 299 StringRef Name = getRelocationTypeName(Type); 300 Result.append(Name.begin(), Name.end()); 301 } else { 302 // The Mips N64 ABI allows up to three operations to be specified per 303 // relocation record. Unfortunately there's no easy way to test for the 304 // presence of N64 ELFs as they have no special flag that identifies them 305 // as being N64. We can safely assume at the moment that all Mips 306 // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough 307 // information to disambiguate between old vs new ABIs. 308 uint8_t Type1 = (Type >> 0) & 0xFF; 309 uint8_t Type2 = (Type >> 8) & 0xFF; 310 uint8_t Type3 = (Type >> 16) & 0xFF; 311 312 // Concat all three relocation type names. 313 StringRef Name = getRelocationTypeName(Type1); 314 Result.append(Name.begin(), Name.end()); 315 316 Name = getRelocationTypeName(Type2); 317 Result.append(1, '/'); 318 Result.append(Name.begin(), Name.end()); 319 320 Name = getRelocationTypeName(Type3); 321 Result.append(1, '/'); 322 Result.append(Name.begin(), Name.end()); 323 } 324} 325 326template <class ELFT> 327Expected<const typename ELFT::Sym *> 328ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, 329 const Elf_Shdr *SymTab) const { 330 uint32_t Index = Rel->getSymbol(isMips64EL()); 331 if (Index == 0) 332 return nullptr; 333 return getEntry<Elf_Sym>(SymTab, Index); 334} 335 336template <class ELFT> 337Expected<StringRef> 338ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const { 339 uint32_t Index = getHeader()->e_shstrndx; 340 if (Index == ELF::SHN_XINDEX) 341 Index = Sections[0].sh_link; 342 343 if (!Index) // no section string table. 344 return ""; 345 if (Index >= Sections.size()) 346 return createError("invalid section index"); 347 return getStringTable(&Sections[Index]); 348} 349 350template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} 351 352template <class ELFT> 353Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { 354 if (sizeof(Elf_Ehdr) > Object.size()) 355 return createError("Invalid buffer"); 356 return ELFFile(Object); 357} 358 359template <class ELFT> 360bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { 361 return VAddr < Phdr->p_vaddr; 362} 363 364template <class ELFT> 365Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { 366 const uintX_t SectionTableOffset = getHeader()->e_shoff; 367 if (SectionTableOffset == 0) 368 return ArrayRef<Elf_Shdr>(); 369 370 if (getHeader()->e_shentsize != sizeof(Elf_Shdr)) 371 return createError( 372 "invalid section header entry size (e_shentsize) in ELF header"); 373 374 const uint64_t FileSize = Buf.size(); 375 376 if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) 377 return createError("section header table goes past the end of the file"); 378 379 // Invalid address alignment of section headers 380 if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) 381 return createError("invalid alignment of section headers"); 382 383 const Elf_Shdr *First = 384 reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); 385 386 uintX_t NumSections = getHeader()->e_shnum; 387 if (NumSections == 0) 388 NumSections = First->sh_size; 389 390 if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) 391 return createError("section table goes past the end of file"); 392 393 const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); 394 395 // Section table goes past end of file! 396 if (SectionTableOffset + SectionTableSize > FileSize) 397 return createError("section table goes past the end of file"); 398 399 return makeArrayRef(First, NumSections); 400} 401 402template <class ELFT> 403template <typename T> 404Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, 405 uint32_t Entry) const { 406 auto SecOrErr = getSection(Section); 407 if (!SecOrErr) 408 return SecOrErr.takeError(); 409 return getEntry<T>(*SecOrErr, Entry); 410} 411 412template <class ELFT> 413template <typename T> 414Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, 415 uint32_t Entry) const { 416 if (sizeof(T) != Section->sh_entsize) 417 return createError("invalid sh_entsize"); 418 size_t Pos = Section->sh_offset + Entry * sizeof(T); 419 if (Pos + sizeof(T) > Buf.size()) 420 return createError("invalid section offset"); 421 return reinterpret_cast<const T *>(base() + Pos); 422} 423 424template <class ELFT> 425Expected<const typename ELFT::Shdr *> 426ELFFile<ELFT>::getSection(uint32_t Index) const { 427 auto TableOrErr = sections(); 428 if (!TableOrErr) 429 return TableOrErr.takeError(); 430 return object::getSection<ELFT>(*TableOrErr, Index); 431} 432 433template <class ELFT> 434Expected<StringRef> 435ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { 436 if (Section->sh_type != ELF::SHT_STRTAB) 437 return createError("invalid sh_type for string table, expected SHT_STRTAB"); 438 auto V = getSectionContentsAsArray<char>(Section); 439 if (!V) 440 return V.takeError(); 441 ArrayRef<char> Data = *V; 442 if (Data.empty()) 443 return createError("empty string table"); 444 if (Data.back() != '\0') 445 return createError("string table non-null terminated"); 446 return StringRef(Data.begin(), Data.size()); 447} 448 449template <class ELFT> 450Expected<ArrayRef<typename ELFT::Word>> 451ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { 452 auto SectionsOrErr = sections(); 453 if (!SectionsOrErr) 454 return SectionsOrErr.takeError(); 455 return getSHNDXTable(Section, *SectionsOrErr); 456} 457 458template <class ELFT> 459Expected<ArrayRef<typename ELFT::Word>> 460ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, 461 Elf_Shdr_Range Sections) const { 462 assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); 463 auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section); 464 if (!VOrErr) 465 return VOrErr.takeError(); 466 ArrayRef<Elf_Word> V = *VOrErr; 467 auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); 468 if (!SymTableOrErr) 469 return SymTableOrErr.takeError(); 470 const Elf_Shdr &SymTable = **SymTableOrErr; 471 if (SymTable.sh_type != ELF::SHT_SYMTAB && 472 SymTable.sh_type != ELF::SHT_DYNSYM) 473 return createError("invalid sh_type"); 474 if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym))) 475 return createError("invalid section contents size"); 476 return V; 477} 478 479template <class ELFT> 480Expected<StringRef> 481ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { 482 auto SectionsOrErr = sections(); 483 if (!SectionsOrErr) 484 return SectionsOrErr.takeError(); 485 return getStringTableForSymtab(Sec, *SectionsOrErr); 486} 487 488template <class ELFT> 489Expected<StringRef> 490ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, 491 Elf_Shdr_Range Sections) const { 492 493 if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) 494 return createError( 495 "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); 496 auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link); 497 if (!SectionOrErr) 498 return SectionOrErr.takeError(); 499 return getStringTable(*SectionOrErr); 500} 501 502template <class ELFT> 503Expected<StringRef> 504ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { 505 auto SectionsOrErr = sections(); 506 if (!SectionsOrErr) 507 return SectionsOrErr.takeError(); 508 auto Table = getSectionStringTable(*SectionsOrErr); 509 if (!Table) 510 return Table.takeError(); 511 return getSectionName(Section, *Table); 512} 513 514template <class ELFT> 515Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section, 516 StringRef DotShstrtab) const { 517 uint32_t Offset = Section->sh_name; 518 if (Offset == 0) 519 return StringRef(); 520 if (Offset >= DotShstrtab.size()) 521 return createError("invalid string offset"); 522 return StringRef(DotShstrtab.data() + Offset); 523} 524 525/// This function returns the hash value for a symbol in the .dynsym section 526/// Name of the API remains consistent as specified in the libelf 527/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash 528inline unsigned hashSysV(StringRef SymbolName) { 529 unsigned h = 0, g; 530 for (char C : SymbolName) { 531 h = (h << 4) + C; 532 g = h & 0xf0000000L; 533 if (g != 0) 534 h ^= g >> 24; 535 h &= ~g; 536 } 537 return h; 538} 539 540} // end namespace object 541} // end namespace llvm 542 543#endif // LLVM_OBJECT_ELF_H 544