[COFF] Add a bounds checking helper for iterating a coff_resource_dir_table
[llvm-core.git] / include / llvm / Object / ELF.h
blob5b7ad184fc890e32b3194fcca69c10d8a81a551a
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.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_OBJECT_ELF_H
14 #define LLVM_OBJECT_ELF_H
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>
30 namespace llvm {
31 namespace object {
33 StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type);
34 uint32_t getELFRelativeRelocationType(uint32_t Machine);
35 StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type);
37 // Subclasses of ELFFile may need this for template instantiation
38 inline std::pair<unsigned char, unsigned char>
39 getElfArchType(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]);
47 static inline Error createError(const Twine &Err) {
48 return make_error<StringError>(Err, object_error::parse_failed);
51 template <class ELFT> class ELFFile;
53 template <class ELFT>
54 std::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]";
67 static inline Error defaultWarningHandler(const Twine &Msg) {
68 return createError(Msg);
71 template <class ELFT>
72 class ELFFile {
73 public:
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;
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)>;
109 const uint8_t *base() const { return Buf.bytes_begin(); }
111 size_t getBufSize() const { return Buf.size(); }
113 private:
114 StringRef Buf;
116 ELFFile(StringRef Object);
118 public:
119 const Elf_Ehdr *getHeader() const {
120 return reinterpret_cast<const Elf_Ehdr *>(base());
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;
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;
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;
139 StringRef getRelocationTypeName(uint32_t Type) const;
140 void getRelocationTypeName(uint32_t Type,
141 SmallVectorImpl<char> &Result) const;
142 uint32_t getRelativeRelocationType() const;
144 std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const;
145 std::string getDynamicTagAsString(uint64_t Type) const;
147 /// Get the symbol for a given relocation.
148 Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
149 const Elf_Shdr *SymTab) const;
151 static Expected<ELFFile> create(StringRef Object);
153 bool isMipsELF64() const {
154 return getHeader()->e_machine == ELF::EM_MIPS &&
155 getHeader()->getFileClass() == ELF::ELFCLASS64;
158 bool isMips64EL() const {
159 return isMipsELF64() &&
160 getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
163 Expected<Elf_Shdr_Range> sections() const;
165 Expected<Elf_Dyn_Range> dynamicEntries() const;
167 Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const;
169 Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const {
170 if (!Sec)
171 return makeArrayRef<Elf_Sym>(nullptr, nullptr);
172 return getSectionContentsAsArray<Elf_Sym>(Sec);
175 Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const {
176 return getSectionContentsAsArray<Elf_Rela>(Sec);
179 Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const {
180 return getSectionContentsAsArray<Elf_Rel>(Sec);
183 Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const {
184 return getSectionContentsAsArray<Elf_Relr>(Sec);
187 Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const;
189 Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const;
191 /// Iterate over program header table.
192 Expected<Elf_Phdr_Range> program_headers() const {
193 if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
194 return createError("invalid e_phentsize: " +
195 Twine(getHeader()->e_phentsize));
196 if (getHeader()->e_phoff +
197 (getHeader()->e_phnum * getHeader()->e_phentsize) >
198 getBufSize())
199 return createError("program headers are longer than binary of size " +
200 Twine(getBufSize()) + ": e_phoff = 0x" +
201 Twine::utohexstr(getHeader()->e_phoff) +
202 ", e_phnum = " + Twine(getHeader()->e_phnum) +
203 ", e_phentsize = " + Twine(getHeader()->e_phentsize));
204 auto *Begin =
205 reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff);
206 return makeArrayRef(Begin, Begin + getHeader()->e_phnum);
209 /// Get an iterator over notes in a program header.
211 /// The program header must be of type \c PT_NOTE.
213 /// \param Phdr the program header to iterate over.
214 /// \param Err [out] an error to support fallible iteration, which should
215 /// be checked after iteration ends.
216 Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const {
217 assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE");
218 ErrorAsOutParameter ErrAsOutParam(&Err);
219 if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) {
220 Err = createError("PT_NOTE header has invalid offset (0x" +
221 Twine::utohexstr(Phdr.p_offset) + ") or size (0x" +
222 Twine::utohexstr(Phdr.p_filesz) + ")");
223 return Elf_Note_Iterator(Err);
225 return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err);
228 /// Get an iterator over notes in a section.
230 /// The section must be of type \c SHT_NOTE.
232 /// \param Shdr the section to iterate over.
233 /// \param Err [out] an error to support fallible iteration, which should
234 /// be checked after iteration ends.
235 Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const {
236 assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE");
237 ErrorAsOutParameter ErrAsOutParam(&Err);
238 if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) {
239 Err = createError("SHT_NOTE section " + getSecIndexForError(this, &Shdr) +
240 " has invalid offset (0x" +
241 Twine::utohexstr(Shdr.sh_offset) + ") or size (0x" +
242 Twine::utohexstr(Shdr.sh_size) + ")");
243 return Elf_Note_Iterator(Err);
245 return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err);
248 /// Get the end iterator for notes.
249 Elf_Note_Iterator notes_end() const {
250 return Elf_Note_Iterator();
253 /// Get an iterator range over notes of a program header.
255 /// The program header must be of type \c PT_NOTE.
257 /// \param Phdr the program header to iterate over.
258 /// \param Err [out] an error to support fallible iteration, which should
259 /// be checked after iteration ends.
260 iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr,
261 Error &Err) const {
262 return make_range(notes_begin(Phdr, Err), notes_end());
265 /// Get an iterator range over notes of a section.
267 /// The section must be of type \c SHT_NOTE.
269 /// \param Shdr the section to iterate over.
270 /// \param Err [out] an error to support fallible iteration, which should
271 /// be checked after iteration ends.
272 iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr,
273 Error &Err) const {
274 return make_range(notes_begin(Shdr, Err), notes_end());
277 Expected<StringRef> getSectionStringTable(
278 Elf_Shdr_Range Sections,
279 WarningHandler WarnHandler = &defaultWarningHandler) const;
280 Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
281 ArrayRef<Elf_Word> ShndxTable) const;
282 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
283 const Elf_Shdr *SymTab,
284 ArrayRef<Elf_Word> ShndxTable) const;
285 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
286 Elf_Sym_Range Symtab,
287 ArrayRef<Elf_Word> ShndxTable) const;
288 Expected<const Elf_Shdr *> getSection(uint32_t Index) const;
290 Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec,
291 uint32_t Index) const;
293 Expected<StringRef>
294 getSectionName(const Elf_Shdr *Section,
295 WarningHandler WarnHandler = &defaultWarningHandler) const;
296 Expected<StringRef> getSectionName(const Elf_Shdr *Section,
297 StringRef DotShstrtab) const;
298 template <typename T>
299 Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const;
300 Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const;
303 using ELF32LEFile = ELFFile<ELF32LE>;
304 using ELF64LEFile = ELFFile<ELF64LE>;
305 using ELF32BEFile = ELFFile<ELF32BE>;
306 using ELF64BEFile = ELFFile<ELF64BE>;
308 template <class ELFT>
309 inline Expected<const typename ELFT::Shdr *>
310 getSection(typename ELFT::ShdrRange Sections, uint32_t Index) {
311 if (Index >= Sections.size())
312 return createError("invalid section index: " + Twine(Index));
313 return &Sections[Index];
316 template <class ELFT>
317 inline Expected<uint32_t>
318 getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym,
319 const typename ELFT::Sym *FirstSym,
320 ArrayRef<typename ELFT::Word> ShndxTable) {
321 assert(Sym->st_shndx == ELF::SHN_XINDEX);
322 unsigned Index = Sym - FirstSym;
323 if (Index >= ShndxTable.size())
324 return createError(
325 "extended symbol index (" + Twine(Index) +
326 ") is past the end of the SHT_SYMTAB_SHNDX section of size " +
327 Twine(ShndxTable.size()));
329 // The size of the table was checked in getSHNDXTable.
330 return ShndxTable[Index];
333 template <class ELFT>
334 Expected<uint32_t>
335 ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
336 ArrayRef<Elf_Word> ShndxTable) const {
337 uint32_t Index = Sym->st_shndx;
338 if (Index == ELF::SHN_XINDEX) {
339 auto ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>(
340 Sym, Syms.begin(), ShndxTable);
341 if (!ErrorOrIndex)
342 return ErrorOrIndex.takeError();
343 return *ErrorOrIndex;
345 if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
346 return 0;
347 return Index;
350 template <class ELFT>
351 Expected<const typename ELFT::Shdr *>
352 ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
353 ArrayRef<Elf_Word> ShndxTable) const {
354 auto SymsOrErr = symbols(SymTab);
355 if (!SymsOrErr)
356 return SymsOrErr.takeError();
357 return getSection(Sym, *SymsOrErr, ShndxTable);
360 template <class ELFT>
361 Expected<const typename ELFT::Shdr *>
362 ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols,
363 ArrayRef<Elf_Word> ShndxTable) const {
364 auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable);
365 if (!IndexOrErr)
366 return IndexOrErr.takeError();
367 uint32_t Index = *IndexOrErr;
368 if (Index == 0)
369 return nullptr;
370 return getSection(Index);
373 template <class ELFT>
374 Expected<const typename ELFT::Sym *>
375 ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const {
376 auto SymsOrErr = symbols(Sec);
377 if (!SymsOrErr)
378 return SymsOrErr.takeError();
380 Elf_Sym_Range Symbols = *SymsOrErr;
381 if (Index >= Symbols.size())
382 return createError("unable to get symbol from section " +
383 getSecIndexForError(this, Sec) +
384 ": invalid symbol index (" + Twine(Index) + ")");
385 return &Symbols[Index];
388 template <class ELFT>
389 template <typename T>
390 Expected<ArrayRef<T>>
391 ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const {
392 if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1)
393 return createError("section " + getSecIndexForError(this, Sec) +
394 " has an invalid sh_entsize: " + Twine(Sec->sh_entsize));
396 uintX_t Offset = Sec->sh_offset;
397 uintX_t Size = Sec->sh_size;
399 if (Size % sizeof(T))
400 return createError("section " + getSecIndexForError(this, Sec) +
401 " has an invalid sh_size (" + Twine(Size) +
402 ") which is not a multiple of its sh_entsize (" +
403 Twine(Sec->sh_entsize) + ")");
404 if ((std::numeric_limits<uintX_t>::max() - Offset < Size) ||
405 Offset + Size > Buf.size())
406 return createError("section " + getSecIndexForError(this, Sec) +
407 " has a sh_offset (0x" + Twine::utohexstr(Offset) +
408 ") + sh_size (0x" + Twine(Size) +
409 ") that cannot be represented");
411 if (Offset % alignof(T))
412 // TODO: this error is untested.
413 return createError("unaligned data");
415 const T *Start = reinterpret_cast<const T *>(base() + Offset);
416 return makeArrayRef(Start, Size / sizeof(T));
419 template <class ELFT>
420 Expected<ArrayRef<uint8_t>>
421 ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const {
422 return getSectionContentsAsArray<uint8_t>(Sec);
425 template <class ELFT>
426 StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
427 return getELFRelocationTypeName(getHeader()->e_machine, Type);
430 template <class ELFT>
431 void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
432 SmallVectorImpl<char> &Result) const {
433 if (!isMipsELF64()) {
434 StringRef Name = getRelocationTypeName(Type);
435 Result.append(Name.begin(), Name.end());
436 } else {
437 // The Mips N64 ABI allows up to three operations to be specified per
438 // relocation record. Unfortunately there's no easy way to test for the
439 // presence of N64 ELFs as they have no special flag that identifies them
440 // as being N64. We can safely assume at the moment that all Mips
441 // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough
442 // information to disambiguate between old vs new ABIs.
443 uint8_t Type1 = (Type >> 0) & 0xFF;
444 uint8_t Type2 = (Type >> 8) & 0xFF;
445 uint8_t Type3 = (Type >> 16) & 0xFF;
447 // Concat all three relocation type names.
448 StringRef Name = getRelocationTypeName(Type1);
449 Result.append(Name.begin(), Name.end());
451 Name = getRelocationTypeName(Type2);
452 Result.append(1, '/');
453 Result.append(Name.begin(), Name.end());
455 Name = getRelocationTypeName(Type3);
456 Result.append(1, '/');
457 Result.append(Name.begin(), Name.end());
461 template <class ELFT>
462 uint32_t ELFFile<ELFT>::getRelativeRelocationType() const {
463 return getELFRelativeRelocationType(getHeader()->e_machine);
466 template <class ELFT>
467 Expected<const typename ELFT::Sym *>
468 ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
469 const Elf_Shdr *SymTab) const {
470 uint32_t Index = Rel->getSymbol(isMips64EL());
471 if (Index == 0)
472 return nullptr;
473 return getEntry<Elf_Sym>(SymTab, Index);
476 template <class ELFT>
477 Expected<StringRef>
478 ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
479 WarningHandler WarnHandler) const {
480 uint32_t Index = getHeader()->e_shstrndx;
481 if (Index == ELF::SHN_XINDEX)
482 Index = Sections[0].sh_link;
484 if (!Index) // no section string table.
485 return "";
486 if (Index >= Sections.size())
487 return createError("section header string table index " + Twine(Index) +
488 " does not exist");
489 return getStringTable(&Sections[Index], WarnHandler);
492 template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
494 template <class ELFT>
495 Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
496 if (sizeof(Elf_Ehdr) > Object.size())
497 return createError("invalid buffer: the size (" + Twine(Object.size()) +
498 ") is smaller than an ELF header (" +
499 Twine(sizeof(Elf_Ehdr)) + ")");
500 return ELFFile(Object);
503 template <class ELFT>
504 Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
505 const uintX_t SectionTableOffset = getHeader()->e_shoff;
506 if (SectionTableOffset == 0)
507 return ArrayRef<Elf_Shdr>();
509 if (getHeader()->e_shentsize != sizeof(Elf_Shdr))
510 return createError("invalid e_shentsize in ELF header: " +
511 Twine(getHeader()->e_shentsize));
513 const uint64_t FileSize = Buf.size();
514 if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize ||
515 SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset)
516 return createError(
517 "section header table goes past the end of the file: e_shoff = 0x" +
518 Twine::utohexstr(SectionTableOffset));
520 // Invalid address alignment of section headers
521 if (SectionTableOffset & (alignof(Elf_Shdr) - 1))
522 // TODO: this error is untested.
523 return createError("invalid alignment of section headers");
525 const Elf_Shdr *First =
526 reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
528 uintX_t NumSections = getHeader()->e_shnum;
529 if (NumSections == 0)
530 NumSections = First->sh_size;
532 if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
533 return createError("invalid number of sections specified in the NULL "
534 "section's sh_size field (" +
535 Twine(NumSections) + ")");
537 const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
538 if (SectionTableOffset + SectionTableSize < SectionTableOffset)
539 return createError(
540 "invalid section header table offset (e_shoff = 0x" +
541 Twine::utohexstr(SectionTableOffset) +
542 ") or invalid number of sections specified in the first section "
543 "header's sh_size field (0x" +
544 Twine::utohexstr(NumSections) + ")");
546 // Section table goes past end of file!
547 if (SectionTableOffset + SectionTableSize > FileSize)
548 return createError("section table goes past the end of file");
549 return makeArrayRef(First, NumSections);
552 template <class ELFT>
553 template <typename T>
554 Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section,
555 uint32_t Entry) const {
556 auto SecOrErr = getSection(Section);
557 if (!SecOrErr)
558 return SecOrErr.takeError();
559 return getEntry<T>(*SecOrErr, Entry);
562 template <class ELFT>
563 template <typename T>
564 Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section,
565 uint32_t Entry) const {
566 if (sizeof(T) != Section->sh_entsize)
567 return createError("section " + getSecIndexForError(this, Section) +
568 " has invalid sh_entsize: expected " + Twine(sizeof(T)) +
569 ", but got " + Twine(Section->sh_entsize));
570 size_t Pos = Section->sh_offset + Entry * sizeof(T);
571 if (Pos + sizeof(T) > Buf.size())
572 return createError("unable to access section " +
573 getSecIndexForError(this, Section) + " data at 0x" +
574 Twine::utohexstr(Pos) +
575 ": offset goes past the end of file");
576 return reinterpret_cast<const T *>(base() + Pos);
579 template <class ELFT>
580 Expected<const typename ELFT::Shdr *>
581 ELFFile<ELFT>::getSection(uint32_t Index) const {
582 auto TableOrErr = sections();
583 if (!TableOrErr)
584 return TableOrErr.takeError();
585 return object::getSection<ELFT>(*TableOrErr, Index);
588 template <class ELFT>
589 Expected<StringRef>
590 ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section,
591 WarningHandler WarnHandler) const {
592 if (Section->sh_type != ELF::SHT_STRTAB)
593 if (Error E = WarnHandler("invalid sh_type for string table section " +
594 getSecIndexForError(this, Section) +
595 ": expected SHT_STRTAB, but got " +
596 object::getELFSectionTypeName(
597 getHeader()->e_machine, Section->sh_type)))
598 return std::move(E);
600 auto V = getSectionContentsAsArray<char>(Section);
601 if (!V)
602 return V.takeError();
603 ArrayRef<char> Data = *V;
604 if (Data.empty())
605 return createError("SHT_STRTAB string table section " +
606 getSecIndexForError(this, Section) + " is empty");
607 if (Data.back() != '\0')
608 return createError("SHT_STRTAB string table section " +
609 getSecIndexForError(this, Section) +
610 " is non-null terminated");
611 return StringRef(Data.begin(), Data.size());
614 template <class ELFT>
615 Expected<ArrayRef<typename ELFT::Word>>
616 ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const {
617 auto SectionsOrErr = sections();
618 if (!SectionsOrErr)
619 return SectionsOrErr.takeError();
620 return getSHNDXTable(Section, *SectionsOrErr);
623 template <class ELFT>
624 Expected<ArrayRef<typename ELFT::Word>>
625 ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section,
626 Elf_Shdr_Range Sections) const {
627 assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);
628 auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section);
629 if (!VOrErr)
630 return VOrErr.takeError();
631 ArrayRef<Elf_Word> V = *VOrErr;
632 auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link);
633 if (!SymTableOrErr)
634 return SymTableOrErr.takeError();
635 const Elf_Shdr &SymTable = **SymTableOrErr;
636 if (SymTable.sh_type != ELF::SHT_SYMTAB &&
637 SymTable.sh_type != ELF::SHT_DYNSYM)
638 return createError("SHT_SYMTAB_SHNDX section is linked with " +
639 object::getELFSectionTypeName(getHeader()->e_machine,
640 SymTable.sh_type) +
641 " section (expected SHT_SYMTAB/SHT_DYNSYM)");
643 if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
644 return createError("SHT_SYMTAB_SHNDX section has sh_size (" +
645 Twine(SymTable.sh_size) +
646 ") which is not equal to the number of symbols (" +
647 Twine(V.size()) + ")");
648 return V;
651 template <class ELFT>
652 Expected<StringRef>
653 ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const {
654 auto SectionsOrErr = sections();
655 if (!SectionsOrErr)
656 return SectionsOrErr.takeError();
657 return getStringTableForSymtab(Sec, *SectionsOrErr);
660 template <class ELFT>
661 Expected<StringRef>
662 ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec,
663 Elf_Shdr_Range Sections) const {
665 if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)
666 // TODO: this error is untested.
667 return createError(
668 "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");
669 auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link);
670 if (!SectionOrErr)
671 return SectionOrErr.takeError();
672 return getStringTable(*SectionOrErr);
675 template <class ELFT>
676 Expected<StringRef>
677 ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section,
678 WarningHandler WarnHandler) const {
679 auto SectionsOrErr = sections();
680 if (!SectionsOrErr)
681 return SectionsOrErr.takeError();
682 auto Table = getSectionStringTable(*SectionsOrErr, WarnHandler);
683 if (!Table)
684 return Table.takeError();
685 return getSectionName(Section, *Table);
688 template <class ELFT>
689 Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section,
690 StringRef DotShstrtab) const {
691 uint32_t Offset = Section->sh_name;
692 if (Offset == 0)
693 return StringRef();
694 if (Offset >= DotShstrtab.size())
695 return createError("a section " + getSecIndexForError(this, Section) +
696 " has an invalid sh_name (0x" +
697 Twine::utohexstr(Offset) +
698 ") offset which goes past the end of the "
699 "section name string table");
700 return StringRef(DotShstrtab.data() + Offset);
703 /// This function returns the hash value for a symbol in the .dynsym section
704 /// Name of the API remains consistent as specified in the libelf
705 /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
706 inline unsigned hashSysV(StringRef SymbolName) {
707 unsigned h = 0, g;
708 for (char C : SymbolName) {
709 h = (h << 4) + C;
710 g = h & 0xf0000000L;
711 if (g != 0)
712 h ^= g >> 24;
713 h &= ~g;
715 return h;
718 } // end namespace object
719 } // end namespace llvm
721 #endif // LLVM_OBJECT_ELF_H