1//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file declares the ELFFile template class. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef LLVM_OBJECT_ELF_H 14#define LLVM_OBJECT_ELF_H 15 16#include "llvm/ADT/ArrayRef.h" 17#include "llvm/ADT/SmallVector.h" 18#include "llvm/ADT/StringRef.h" 19#include "llvm/BinaryFormat/ELF.h" 20#include "llvm/Object/ELFTypes.h" 21#include "llvm/Object/Error.h" 22#include "llvm/Support/Endian.h" 23#include "llvm/Support/Error.h" 24#include <cassert> 25#include <cstddef> 26#include <cstdint> 27#include <limits> 28#include <utility> 29 30namespace llvm { 31namespace object { 32 33StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); 34uint32_t getELFRelativeRelocationType(uint32_t Machine); 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(const Twine &Err) { 48 return make_error<StringError>(Err, object_error::parse_failed); 49} 50 51template <class ELFT> class ELFFile; 52 53template <class ELFT> 54std::string getSecIndexForError(const ELFFile<ELFT> *Obj, 55 const typename ELFT::Shdr *Sec) { 56 auto TableOrErr = Obj->sections(); 57 if (TableOrErr) 58 return "[index " + std::to_string(Sec - &TableOrErr->front()) + "]"; 59 // To make this helper be more convenient for error reporting purposes we 60 // drop the error. But really it should never be triggered. Before this point, 61 // our code should have called 'sections()' and reported a proper error on 62 // failure. 63 llvm::consumeError(TableOrErr.takeError()); 64 return "[unknown index]"; 65} 66 67static inline Error defaultWarningHandler(const Twine &Msg) { 68 return createError(Msg); 69} 70 71template <class ELFT> 72class ELFFile { 73public: 74 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 75 using uintX_t = typename ELFT::uint; 76 using Elf_Ehdr = typename ELFT::Ehdr; 77 using Elf_Shdr = typename ELFT::Shdr; 78 using Elf_Sym = typename ELFT::Sym; 79 using Elf_Dyn = typename ELFT::Dyn; 80 using Elf_Phdr = typename ELFT::Phdr; 81 using Elf_Rel = typename ELFT::Rel; 82 using Elf_Rela = typename ELFT::Rela; 83 using Elf_Relr = typename ELFT::Relr; 84 using Elf_Verdef = typename ELFT::Verdef; 85 using Elf_Verdaux = typename ELFT::Verdaux; 86 using Elf_Verneed = typename ELFT::Verneed; 87 using Elf_Vernaux = typename ELFT::Vernaux; 88 using Elf_Versym = typename ELFT::Versym; 89 using Elf_Hash = typename ELFT::Hash; 90 using Elf_GnuHash = typename ELFT::GnuHash; 91 using Elf_Nhdr = typename ELFT::Nhdr; 92 using Elf_Note = typename ELFT::Note; 93 using Elf_Note_Iterator = typename ELFT::NoteIterator; 94 using Elf_Dyn_Range = typename ELFT::DynRange; 95 using Elf_Shdr_Range = typename ELFT::ShdrRange; 96 using Elf_Sym_Range = typename ELFT::SymRange; 97 using Elf_Rel_Range = typename ELFT::RelRange; 98 using Elf_Rela_Range = typename ELFT::RelaRange; 99 using Elf_Relr_Range = typename ELFT::RelrRange; 100 using Elf_Phdr_Range = typename ELFT::PhdrRange; 101 102 // This is a callback that can be passed to a number of functions. 103 // It can be used to ignore non-critical errors (warnings), which is 104 // useful for dumpers, like llvm-readobj. 105 // It accepts a warning message string and returns a success 106 // when the warning should be ignored or an error otherwise. 107 using WarningHandler = llvm::function_ref<Error(const Twine &Msg)>; 108 109 const uint8_t *base() const { return Buf.bytes_begin(); } 110 111 size_t getBufSize() const { return Buf.size(); } 112 113private: 114 StringRef Buf; 115 116 ELFFile(StringRef Object); 117 118public: 119 const Elf_Ehdr *getHeader() const { 120 return reinterpret_cast<const Elf_Ehdr *>(base()); 121 } 122 123 template <typename T> 124 Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; 125 template <typename T> 126 Expected<const T *> getEntry(const Elf_Shdr *Section, uint32_t Entry) const; 127 128 Expected<StringRef> 129 getStringTable(const Elf_Shdr *Section, 130 WarningHandler WarnHandler = &defaultWarningHandler) const; 131 Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; 132 Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, 133 Elf_Shdr_Range Sections) const; 134 135 Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; 136 Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, 137 Elf_Shdr_Range Sections) const; 138 139 StringRef getRelocationTypeName(uint32_t Type) const; 140 void getRelocationTypeName(uint32_t Type, 141 SmallVectorImpl<char> &Result) const; 142 uint32_t getRelativeRelocationType() const; 143 144 std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const; 145 std::string getDynamicTagAsString(uint64_t Type) const; 146 147 /// Get the symbol for a given relocation. 148 Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, 149 const Elf_Shdr *SymTab) const; 150 151 static Expected<ELFFile> create(StringRef Object); 152 153 bool isLE() const { 154 return getHeader()->getDataEncoding() == ELF::ELFDATA2LSB; 155 } 156 157 bool isMipsELF64() const { 158 return getHeader()->e_machine == ELF::EM_MIPS && 159 getHeader()->getFileClass() == ELF::ELFCLASS64; 160 } 161 162 bool isMips64EL() const { return isMipsELF64() && isLE(); } 163 164 Expected<Elf_Shdr_Range> sections() const; 165 166 Expected<Elf_Dyn_Range> dynamicEntries() const; 167 168 Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const; 169 170 Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { 171 if (!Sec) 172 return makeArrayRef<Elf_Sym>(nullptr, nullptr); 173 return getSectionContentsAsArray<Elf_Sym>(Sec); 174 } 175 176 Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const { 177 return getSectionContentsAsArray<Elf_Rela>(Sec); 178 } 179 180 Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const { 181 return getSectionContentsAsArray<Elf_Rel>(Sec); 182 } 183 184 Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const { 185 return getSectionContentsAsArray<Elf_Relr>(Sec); 186 } 187 188 Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const; 189 190 Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const; 191 192 /// Iterate over program header table. 193 Expected<Elf_Phdr_Range> program_headers() const { 194 if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) 195 return createError("invalid e_phentsize: " + 196 Twine(getHeader()->e_phentsize)); 197 if (getHeader()->e_phoff + 198 (getHeader()->e_phnum * getHeader()->e_phentsize) > 199 getBufSize()) 200 return createError("program headers are longer than binary of size " + 201 Twine(getBufSize()) + ": e_phoff = 0x" + 202 Twine::utohexstr(getHeader()->e_phoff) + 203 ", e_phnum = " + Twine(getHeader()->e_phnum) + 204 ", e_phentsize = " + Twine(getHeader()->e_phentsize)); 205 auto *Begin = 206 reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff); 207 return makeArrayRef(Begin, Begin + getHeader()->e_phnum); 208 } 209 210 /// Get an iterator over notes in a program header. 211 /// 212 /// The program header must be of type \c PT_NOTE. 213 /// 214 /// \param Phdr the program header to iterate over. 215 /// \param Err [out] an error to support fallible iteration, which should 216 /// be checked after iteration ends. 217 Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { 218 assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE"); 219 ErrorAsOutParameter ErrAsOutParam(&Err); 220 if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { 221 Err = createError("PT_NOTE header has invalid offset (0x" + 222 Twine::utohexstr(Phdr.p_offset) + ") or size (0x" + 223 Twine::utohexstr(Phdr.p_filesz) + ")"); 224 return Elf_Note_Iterator(Err); 225 } 226 return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err); 227 } 228 229 /// Get an iterator over notes in a section. 230 /// 231 /// The section must be of type \c SHT_NOTE. 232 /// 233 /// \param Shdr the section to iterate over. 234 /// \param Err [out] an error to support fallible iteration, which should 235 /// be checked after iteration ends. 236 Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { 237 assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE"); 238 ErrorAsOutParameter ErrAsOutParam(&Err); 239 if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { 240 Err = createError("SHT_NOTE section " + getSecIndexForError(this, &Shdr) + 241 " has invalid offset (0x" + 242 Twine::utohexstr(Shdr.sh_offset) + ") or size (0x" + 243 Twine::utohexstr(Shdr.sh_size) + ")"); 244 return Elf_Note_Iterator(Err); 245 } 246 return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err); 247 } 248 249 /// Get the end iterator for notes. 250 Elf_Note_Iterator notes_end() const { 251 return Elf_Note_Iterator(); 252 } 253 254 /// Get an iterator range over notes of a program header. 255 /// 256 /// The program header must be of type \c PT_NOTE. 257 /// 258 /// \param Phdr the program header to iterate over. 259 /// \param Err [out] an error to support fallible iteration, which should 260 /// be checked after iteration ends. 261 iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr, 262 Error &Err) const { 263 return make_range(notes_begin(Phdr, Err), notes_end()); 264 } 265 266 /// Get an iterator range over notes of a section. 267 /// 268 /// The section must be of type \c SHT_NOTE. 269 /// 270 /// \param Shdr the section to iterate over. 271 /// \param Err [out] an error to support fallible iteration, which should 272 /// be checked after iteration ends. 273 iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr, 274 Error &Err) const { 275 return make_range(notes_begin(Shdr, Err), notes_end()); 276 } 277 278 Expected<StringRef> getSectionStringTable( 279 Elf_Shdr_Range Sections, 280 WarningHandler WarnHandler = &defaultWarningHandler) const; 281 Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, 282 ArrayRef<Elf_Word> ShndxTable) const; 283 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, 284 const Elf_Shdr *SymTab, 285 ArrayRef<Elf_Word> ShndxTable) const; 286 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, 287 Elf_Sym_Range Symtab, 288 ArrayRef<Elf_Word> ShndxTable) const; 289 Expected<const Elf_Shdr *> getSection(uint32_t Index) const; 290 291 Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, 292 uint32_t Index) const; 293 294 Expected<StringRef> 295 getSectionName(const Elf_Shdr *Section, 296 WarningHandler WarnHandler = &defaultWarningHandler) const; 297 Expected<StringRef> getSectionName(const Elf_Shdr *Section, 298 StringRef DotShstrtab) const; 299 template <typename T> 300 Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const; 301 Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const; 302}; 303 304using ELF32LEFile = ELFFile<ELF32LE>; 305using ELF64LEFile = ELFFile<ELF64LE>; 306using ELF32BEFile = ELFFile<ELF32BE>; 307using ELF64BEFile = ELFFile<ELF64BE>; 308 309template <class ELFT> 310inline Expected<const typename ELFT::Shdr *> 311getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { 312 if (Index >= Sections.size()) 313 return createError("invalid section index: " + Twine(Index)); 314 return &Sections[Index]; 315} 316 317template <class ELFT> 318inline Expected<uint32_t> 319getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym, 320 const typename ELFT::Sym *FirstSym, 321 ArrayRef<typename ELFT::Word> ShndxTable) { 322 assert(Sym->st_shndx == ELF::SHN_XINDEX); 323 unsigned Index = Sym - FirstSym; 324 if (Index >= ShndxTable.size()) 325 return createError( 326 "extended symbol index (" + Twine(Index) + 327 ") is past the end of the SHT_SYMTAB_SHNDX section of size " + 328 Twine(ShndxTable.size())); 329 330 // The size of the table was checked in getSHNDXTable. 331 return ShndxTable[Index]; 332} 333 334template <class ELFT> 335Expected<uint32_t> 336ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, 337 ArrayRef<Elf_Word> ShndxTable) const { 338 uint32_t Index = Sym->st_shndx; 339 if (Index == ELF::SHN_XINDEX) { 340 auto ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>( 341 Sym, Syms.begin(), ShndxTable); 342 if (!ErrorOrIndex) 343 return ErrorOrIndex.takeError(); 344 return *ErrorOrIndex; 345 } 346 if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) 347 return 0; 348 return Index; 349} 350 351template <class ELFT> 352Expected<const typename ELFT::Shdr *> 353ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, 354 ArrayRef<Elf_Word> ShndxTable) const { 355 auto SymsOrErr = symbols(SymTab); 356 if (!SymsOrErr) 357 return SymsOrErr.takeError(); 358 return getSection(Sym, *SymsOrErr, ShndxTable); 359} 360 361template <class ELFT> 362Expected<const typename ELFT::Shdr *> 363ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols, 364 ArrayRef<Elf_Word> ShndxTable) const { 365 auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable); 366 if (!IndexOrErr) 367 return IndexOrErr.takeError(); 368 uint32_t Index = *IndexOrErr; 369 if (Index == 0) 370 return nullptr; 371 return getSection(Index); 372} 373 374template <class ELFT> 375Expected<const typename ELFT::Sym *> 376ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { 377 auto SymsOrErr = symbols(Sec); 378 if (!SymsOrErr) 379 return SymsOrErr.takeError(); 380 381 Elf_Sym_Range Symbols = *SymsOrErr; 382 if (Index >= Symbols.size()) 383 return createError("unable to get symbol from section " + 384 getSecIndexForError(this, Sec) + 385 ": invalid symbol index (" + Twine(Index) + ")"); 386 return &Symbols[Index]; 387} 388 389template <class ELFT> 390template <typename T> 391Expected<ArrayRef<T>> 392ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { 393 if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1) 394 return createError("section " + getSecIndexForError(this, Sec) + 395 " has an invalid sh_entsize: " + Twine(Sec->sh_entsize)); 396 397 uintX_t Offset = Sec->sh_offset; 398 uintX_t Size = Sec->sh_size; 399 400 if (Size % sizeof(T)) 401 return createError("section " + getSecIndexForError(this, Sec) + 402 " has an invalid sh_size (" + Twine(Size) + 403 ") which is not a multiple of its sh_entsize (" + 404 Twine(Sec->sh_entsize) + ")"); 405 if (std::numeric_limits<uintX_t>::max() - Offset < Size) 406 return createError("section " + getSecIndexForError(this, Sec) + 407 " has a sh_offset (0x" + Twine::utohexstr(Offset) + 408 ") + sh_size (0x" + Twine::utohexstr(Size) + 409 ") that cannot be represented"); 410 if (Offset + Size > Buf.size()) 411 return createError("section " + getSecIndexForError(this, Sec) + 412 " has a sh_offset (0x" + Twine::utohexstr(Offset) + 413 ") + sh_size (0x" + Twine::utohexstr(Size) + 414 ") that is greater than the file size (0x" + 415 Twine::utohexstr(Buf.size()) + ")"); 416 417 if (Offset % alignof(T)) 418 // TODO: this error is untested. 419 return createError("unaligned data"); 420 421 const T *Start = reinterpret_cast<const T *>(base() + Offset); 422 return makeArrayRef(Start, Size / sizeof(T)); 423} 424 425template <class ELFT> 426Expected<ArrayRef<uint8_t>> 427ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { 428 return getSectionContentsAsArray<uint8_t>(Sec); 429} 430 431template <class ELFT> 432StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { 433 return getELFRelocationTypeName(getHeader()->e_machine, Type); 434} 435 436template <class ELFT> 437void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, 438 SmallVectorImpl<char> &Result) const { 439 if (!isMipsELF64()) { 440 StringRef Name = getRelocationTypeName(Type); 441 Result.append(Name.begin(), Name.end()); 442 } else { 443 // The Mips N64 ABI allows up to three operations to be specified per 444 // relocation record. Unfortunately there's no easy way to test for the 445 // presence of N64 ELFs as they have no special flag that identifies them 446 // as being N64. We can safely assume at the moment that all Mips 447 // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough 448 // information to disambiguate between old vs new ABIs. 449 uint8_t Type1 = (Type >> 0) & 0xFF; 450 uint8_t Type2 = (Type >> 8) & 0xFF; 451 uint8_t Type3 = (Type >> 16) & 0xFF; 452 453 // Concat all three relocation type names. 454 StringRef Name = getRelocationTypeName(Type1); 455 Result.append(Name.begin(), Name.end()); 456 457 Name = getRelocationTypeName(Type2); 458 Result.append(1, '/'); 459 Result.append(Name.begin(), Name.end()); 460 461 Name = getRelocationTypeName(Type3); 462 Result.append(1, '/'); 463 Result.append(Name.begin(), Name.end()); 464 } 465} 466 467template <class ELFT> 468uint32_t ELFFile<ELFT>::getRelativeRelocationType() const { 469 return getELFRelativeRelocationType(getHeader()->e_machine); 470} 471 472template <class ELFT> 473Expected<const typename ELFT::Sym *> 474ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, 475 const Elf_Shdr *SymTab) const { 476 uint32_t Index = Rel->getSymbol(isMips64EL()); 477 if (Index == 0) 478 return nullptr; 479 return getEntry<Elf_Sym>(SymTab, Index); 480} 481 482template <class ELFT> 483Expected<StringRef> 484ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections, 485 WarningHandler WarnHandler) const { 486 uint32_t Index = getHeader()->e_shstrndx; 487 if (Index == ELF::SHN_XINDEX) 488 Index = Sections[0].sh_link; 489 490 if (!Index) // no section string table. 491 return ""; 492 if (Index >= Sections.size()) 493 return createError("section header string table index " + Twine(Index) + 494 " does not exist"); 495 return getStringTable(&Sections[Index], WarnHandler); 496} 497 498template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} 499 500template <class ELFT> 501Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { 502 if (sizeof(Elf_Ehdr) > Object.size()) 503 return createError("invalid buffer: the size (" + Twine(Object.size()) + 504 ") is smaller than an ELF header (" + 505 Twine(sizeof(Elf_Ehdr)) + ")"); 506 return ELFFile(Object); 507} 508 509template <class ELFT> 510Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { 511 const uintX_t SectionTableOffset = getHeader()->e_shoff; 512 if (SectionTableOffset == 0) 513 return ArrayRef<Elf_Shdr>(); 514 515 if (getHeader()->e_shentsize != sizeof(Elf_Shdr)) 516 return createError("invalid e_shentsize in ELF header: " + 517 Twine(getHeader()->e_shentsize)); 518 519 const uint64_t FileSize = Buf.size(); 520 if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize || 521 SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset) 522 return createError( 523 "section header table goes past the end of the file: e_shoff = 0x" + 524 Twine::utohexstr(SectionTableOffset)); 525 526 // Invalid address alignment of section headers 527 if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) 528 // TODO: this error is untested. 529 return createError("invalid alignment of section headers"); 530 531 const Elf_Shdr *First = 532 reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); 533 534 uintX_t NumSections = getHeader()->e_shnum; 535 if (NumSections == 0) 536 NumSections = First->sh_size; 537 538 if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) 539 return createError("invalid number of sections specified in the NULL " 540 "section's sh_size field (" + 541 Twine(NumSections) + ")"); 542 543 const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); 544 if (SectionTableOffset + SectionTableSize < SectionTableOffset) 545 return createError( 546 "invalid section header table offset (e_shoff = 0x" + 547 Twine::utohexstr(SectionTableOffset) + 548 ") or invalid number of sections specified in the first section " 549 "header's sh_size field (0x" + 550 Twine::utohexstr(NumSections) + ")"); 551 552 // Section table goes past end of file! 553 if (SectionTableOffset + SectionTableSize > FileSize) 554 return createError("section table goes past the end of file"); 555 return makeArrayRef(First, NumSections); 556} 557 558template <class ELFT> 559template <typename T> 560Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, 561 uint32_t Entry) const { 562 auto SecOrErr = getSection(Section); 563 if (!SecOrErr) 564 return SecOrErr.takeError(); 565 return getEntry<T>(*SecOrErr, Entry); 566} 567 568template <class ELFT> 569template <typename T> 570Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, 571 uint32_t Entry) const { 572 if (sizeof(T) != Section->sh_entsize) 573 return createError("section " + getSecIndexForError(this, Section) + 574 " has invalid sh_entsize: expected " + Twine(sizeof(T)) + 575 ", but got " + Twine(Section->sh_entsize)); 576 size_t Pos = Section->sh_offset + Entry * sizeof(T); 577 if (Pos + sizeof(T) > Buf.size()) 578 return createError("unable to access section " + 579 getSecIndexForError(this, Section) + " data at 0x" + 580 Twine::utohexstr(Pos) + 581 ": offset goes past the end of file"); 582 return reinterpret_cast<const T *>(base() + Pos); 583} 584 585template <class ELFT> 586Expected<const typename ELFT::Shdr *> 587ELFFile<ELFT>::getSection(uint32_t Index) const { 588 auto TableOrErr = sections(); 589 if (!TableOrErr) 590 return TableOrErr.takeError(); 591 return object::getSection<ELFT>(*TableOrErr, Index); 592} 593 594template <class ELFT> 595Expected<StringRef> 596ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section, 597 WarningHandler WarnHandler) const { 598 if (Section->sh_type != ELF::SHT_STRTAB) 599 if (Error E = WarnHandler("invalid sh_type for string table section " + 600 getSecIndexForError(this, Section) + 601 ": expected SHT_STRTAB, but got " + 602 object::getELFSectionTypeName( 603 getHeader()->e_machine, Section->sh_type))) 604 return std::move(E); 605 606 auto V = getSectionContentsAsArray<char>(Section); 607 if (!V) 608 return V.takeError(); 609 ArrayRef<char> Data = *V; 610 if (Data.empty()) 611 return createError("SHT_STRTAB string table section " + 612 getSecIndexForError(this, Section) + " is empty"); 613 if (Data.back() != '\0') 614 return createError("SHT_STRTAB string table section " + 615 getSecIndexForError(this, Section) + 616 " is non-null terminated"); 617 return StringRef(Data.begin(), Data.size()); 618} 619 620template <class ELFT> 621Expected<ArrayRef<typename ELFT::Word>> 622ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { 623 auto SectionsOrErr = sections(); 624 if (!SectionsOrErr) 625 return SectionsOrErr.takeError(); 626 return getSHNDXTable(Section, *SectionsOrErr); 627} 628 629template <class ELFT> 630Expected<ArrayRef<typename ELFT::Word>> 631ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, 632 Elf_Shdr_Range Sections) const { 633 assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); 634 auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section); 635 if (!VOrErr) 636 return VOrErr.takeError(); 637 ArrayRef<Elf_Word> V = *VOrErr; 638 auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); 639 if (!SymTableOrErr) 640 return SymTableOrErr.takeError(); 641 const Elf_Shdr &SymTable = **SymTableOrErr; 642 if (SymTable.sh_type != ELF::SHT_SYMTAB && 643 SymTable.sh_type != ELF::SHT_DYNSYM) 644 return createError("SHT_SYMTAB_SHNDX section is linked with " + 645 object::getELFSectionTypeName(getHeader()->e_machine, 646 SymTable.sh_type) + 647 " section (expected SHT_SYMTAB/SHT_DYNSYM)"); 648 649 uint64_t Syms = SymTable.sh_size / sizeof(Elf_Sym); 650 if (V.size() != Syms) 651 return createError("SHT_SYMTAB_SHNDX has " + Twine(V.size()) + 652 " entries, but the symbol table associated has " + 653 Twine(Syms)); 654 655 return V; 656} 657 658template <class ELFT> 659Expected<StringRef> 660ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { 661 auto SectionsOrErr = sections(); 662 if (!SectionsOrErr) 663 return SectionsOrErr.takeError(); 664 return getStringTableForSymtab(Sec, *SectionsOrErr); 665} 666 667template <class ELFT> 668Expected<StringRef> 669ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, 670 Elf_Shdr_Range Sections) const { 671 672 if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) 673 // TODO: this error is untested. 674 return createError( 675 "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); 676 auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link); 677 if (!SectionOrErr) 678 return SectionOrErr.takeError(); 679 return getStringTable(*SectionOrErr); 680} 681 682template <class ELFT> 683Expected<StringRef> 684ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section, 685 WarningHandler WarnHandler) const { 686 auto SectionsOrErr = sections(); 687 if (!SectionsOrErr) 688 return SectionsOrErr.takeError(); 689 auto Table = getSectionStringTable(*SectionsOrErr, WarnHandler); 690 if (!Table) 691 return Table.takeError(); 692 return getSectionName(Section, *Table); 693} 694 695template <class ELFT> 696Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section, 697 StringRef DotShstrtab) const { 698 uint32_t Offset = Section->sh_name; 699 if (Offset == 0) 700 return StringRef(); 701 if (Offset >= DotShstrtab.size()) 702 return createError("a section " + getSecIndexForError(this, Section) + 703 " has an invalid sh_name (0x" + 704 Twine::utohexstr(Offset) + 705 ") offset which goes past the end of the " 706 "section name string table"); 707 return StringRef(DotShstrtab.data() + Offset); 708} 709 710/// This function returns the hash value for a symbol in the .dynsym section 711/// Name of the API remains consistent as specified in the libelf 712/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash 713inline unsigned hashSysV(StringRef SymbolName) { 714 unsigned h = 0, g; 715 for (char C : SymbolName) { 716 h = (h << 4) + C; 717 g = h & 0xf0000000L; 718 if (g != 0) 719 h ^= g >> 24; 720 h &= ~g; 721 } 722 return h; 723} 724 725} // end namespace object 726} // end namespace llvm 727 728#endif // LLVM_OBJECT_ELF_H 729