blob: 1ba32b4875c5be6b74e459021d53bcc49f603063 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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);
Andrew Walbran16937d02019-10-22 13:54:20 +010034uint32_t getELFRelativeRelocationType(uint32_t Machine);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035StringRef 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;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010063 using Elf_Relr = typename ELFT::Relr;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010064 using Elf_Verdef = typename ELFT::Verdef;
65 using Elf_Verdaux = typename ELFT::Verdaux;
66 using Elf_Verneed = typename ELFT::Verneed;
67 using Elf_Vernaux = typename ELFT::Vernaux;
68 using Elf_Versym = typename ELFT::Versym;
69 using Elf_Hash = typename ELFT::Hash;
70 using Elf_GnuHash = typename ELFT::GnuHash;
71 using Elf_Nhdr = typename ELFT::Nhdr;
72 using Elf_Note = typename ELFT::Note;
73 using Elf_Note_Iterator = typename ELFT::NoteIterator;
74 using Elf_Dyn_Range = typename ELFT::DynRange;
75 using Elf_Shdr_Range = typename ELFT::ShdrRange;
76 using Elf_Sym_Range = typename ELFT::SymRange;
77 using Elf_Rel_Range = typename ELFT::RelRange;
78 using Elf_Rela_Range = typename ELFT::RelaRange;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010079 using Elf_Relr_Range = typename ELFT::RelrRange;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010080 using Elf_Phdr_Range = typename ELFT::PhdrRange;
81
82 const uint8_t *base() const {
83 return reinterpret_cast<const uint8_t *>(Buf.data());
84 }
85
86 size_t getBufSize() const { return Buf.size(); }
87
88private:
89 StringRef Buf;
90
91 ELFFile(StringRef Object);
92
93public:
94 const Elf_Ehdr *getHeader() const {
95 return reinterpret_cast<const Elf_Ehdr *>(base());
96 }
97
98 template <typename T>
99 Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const;
100 template <typename T>
101 Expected<const T *> getEntry(const Elf_Shdr *Section, uint32_t Entry) const;
102
103 Expected<StringRef> getStringTable(const Elf_Shdr *Section) const;
104 Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const;
105 Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section,
106 Elf_Shdr_Range Sections) const;
107
108 Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const;
109 Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section,
110 Elf_Shdr_Range Sections) const;
111
112 StringRef getRelocationTypeName(uint32_t Type) const;
113 void getRelocationTypeName(uint32_t Type,
114 SmallVectorImpl<char> &Result) const;
Andrew Walbran16937d02019-10-22 13:54:20 +0100115 uint32_t getRelativeRelocationType() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100117 const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const;
118 const char *getDynamicTagAsString(uint64_t Type) const;
119
120 /// Get the symbol for a given relocation.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100121 Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
122 const Elf_Shdr *SymTab) const;
123
124 static Expected<ELFFile> create(StringRef Object);
125
126 bool isMipsELF64() const {
127 return getHeader()->e_machine == ELF::EM_MIPS &&
128 getHeader()->getFileClass() == ELF::ELFCLASS64;
129 }
130
131 bool isMips64EL() const {
132 return isMipsELF64() &&
133 getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
134 }
135
136 Expected<Elf_Shdr_Range> sections() const;
137
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100138 Expected<Elf_Dyn_Range> dynamicEntries() const;
139
140 Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const;
141
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100142 Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const {
143 if (!Sec)
144 return makeArrayRef<Elf_Sym>(nullptr, nullptr);
145 return getSectionContentsAsArray<Elf_Sym>(Sec);
146 }
147
148 Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const {
149 return getSectionContentsAsArray<Elf_Rela>(Sec);
150 }
151
152 Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const {
153 return getSectionContentsAsArray<Elf_Rel>(Sec);
154 }
155
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100156 Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const {
157 return getSectionContentsAsArray<Elf_Relr>(Sec);
158 }
159
160 Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const;
161
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100162 Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const;
163
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100164 /// Iterate over program header table.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100165 Expected<Elf_Phdr_Range> program_headers() const {
166 if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
167 return createError("invalid e_phentsize");
168 if (getHeader()->e_phoff +
169 (getHeader()->e_phnum * getHeader()->e_phentsize) >
170 getBufSize())
171 return createError("program headers longer than binary");
172 auto *Begin =
173 reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff);
174 return makeArrayRef(Begin, Begin + getHeader()->e_phnum);
175 }
176
177 /// Get an iterator over notes in a program header.
178 ///
179 /// The program header must be of type \c PT_NOTE.
180 ///
181 /// \param Phdr the program header to iterate over.
182 /// \param Err [out] an error to support fallible iteration, which should
183 /// be checked after iteration ends.
184 Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const {
185 if (Phdr.p_type != ELF::PT_NOTE) {
186 Err = createError("attempt to iterate notes of non-note program header");
187 return Elf_Note_Iterator(Err);
188 }
189 if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) {
190 Err = createError("invalid program header offset/size");
191 return Elf_Note_Iterator(Err);
192 }
193 return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err);
194 }
195
196 /// Get an iterator over notes in a section.
197 ///
198 /// The section must be of type \c SHT_NOTE.
199 ///
200 /// \param Shdr the section to iterate over.
201 /// \param Err [out] an error to support fallible iteration, which should
202 /// be checked after iteration ends.
203 Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const {
204 if (Shdr.sh_type != ELF::SHT_NOTE) {
205 Err = createError("attempt to iterate notes of non-note section");
206 return Elf_Note_Iterator(Err);
207 }
208 if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) {
209 Err = createError("invalid section offset/size");
210 return Elf_Note_Iterator(Err);
211 }
212 return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err);
213 }
214
215 /// Get the end iterator for notes.
216 Elf_Note_Iterator notes_end() const {
217 return Elf_Note_Iterator();
218 }
219
220 /// Get an iterator range over notes of a program header.
221 ///
222 /// The program header must be of type \c PT_NOTE.
223 ///
224 /// \param Phdr the program header to iterate over.
225 /// \param Err [out] an error to support fallible iteration, which should
226 /// be checked after iteration ends.
227 iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr,
228 Error &Err) const {
229 return make_range(notes_begin(Phdr, Err), notes_end());
230 }
231
232 /// Get an iterator range over notes of a section.
233 ///
234 /// The section must be of type \c SHT_NOTE.
235 ///
236 /// \param Shdr the section to iterate over.
237 /// \param Err [out] an error to support fallible iteration, which should
238 /// be checked after iteration ends.
239 iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr,
240 Error &Err) const {
241 return make_range(notes_begin(Shdr, Err), notes_end());
242 }
243
244 Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const;
245 Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
246 ArrayRef<Elf_Word> ShndxTable) const;
247 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
248 const Elf_Shdr *SymTab,
249 ArrayRef<Elf_Word> ShndxTable) const;
250 Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
251 Elf_Sym_Range Symtab,
252 ArrayRef<Elf_Word> ShndxTable) const;
253 Expected<const Elf_Shdr *> getSection(uint32_t Index) const;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100254 Expected<const Elf_Shdr *> getSection(const StringRef SectionName) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100255
256 Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec,
257 uint32_t Index) const;
258
259 Expected<StringRef> getSectionName(const Elf_Shdr *Section) const;
260 Expected<StringRef> getSectionName(const Elf_Shdr *Section,
261 StringRef DotShstrtab) const;
262 template <typename T>
263 Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const;
264 Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const;
265};
266
267using ELF32LEFile = ELFFile<ELF32LE>;
268using ELF64LEFile = ELFFile<ELF64LE>;
269using ELF32BEFile = ELFFile<ELF32BE>;
270using ELF64BEFile = ELFFile<ELF64BE>;
271
272template <class ELFT>
273inline Expected<const typename ELFT::Shdr *>
274getSection(typename ELFT::ShdrRange Sections, uint32_t Index) {
275 if (Index >= Sections.size())
276 return createError("invalid section index");
277 return &Sections[Index];
278}
279
280template <class ELFT>
281inline Expected<uint32_t>
282getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym,
283 const typename ELFT::Sym *FirstSym,
284 ArrayRef<typename ELFT::Word> ShndxTable) {
285 assert(Sym->st_shndx == ELF::SHN_XINDEX);
286 unsigned Index = Sym - FirstSym;
287 if (Index >= ShndxTable.size())
288 return createError("index past the end of the symbol table");
289
290 // The size of the table was checked in getSHNDXTable.
291 return ShndxTable[Index];
292}
293
294template <class ELFT>
295Expected<uint32_t>
296ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
297 ArrayRef<Elf_Word> ShndxTable) const {
298 uint32_t Index = Sym->st_shndx;
299 if (Index == ELF::SHN_XINDEX) {
300 auto ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>(
301 Sym, Syms.begin(), ShndxTable);
302 if (!ErrorOrIndex)
303 return ErrorOrIndex.takeError();
304 return *ErrorOrIndex;
305 }
306 if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
307 return 0;
308 return Index;
309}
310
311template <class ELFT>
312Expected<const typename ELFT::Shdr *>
313ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
314 ArrayRef<Elf_Word> ShndxTable) const {
315 auto SymsOrErr = symbols(SymTab);
316 if (!SymsOrErr)
317 return SymsOrErr.takeError();
318 return getSection(Sym, *SymsOrErr, ShndxTable);
319}
320
321template <class ELFT>
322Expected<const typename ELFT::Shdr *>
323ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols,
324 ArrayRef<Elf_Word> ShndxTable) const {
325 auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable);
326 if (!IndexOrErr)
327 return IndexOrErr.takeError();
328 uint32_t Index = *IndexOrErr;
329 if (Index == 0)
330 return nullptr;
331 return getSection(Index);
332}
333
334template <class ELFT>
335inline Expected<const typename ELFT::Sym *>
336getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) {
337 if (Index >= Symbols.size())
338 return createError("invalid symbol index");
339 return &Symbols[Index];
340}
341
342template <class ELFT>
343Expected<const typename ELFT::Sym *>
344ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const {
345 auto SymtabOrErr = symbols(Sec);
346 if (!SymtabOrErr)
347 return SymtabOrErr.takeError();
348 return object::getSymbol<ELFT>(*SymtabOrErr, Index);
349}
350
351template <class ELFT>
352template <typename T>
353Expected<ArrayRef<T>>
354ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const {
355 if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1)
356 return createError("invalid sh_entsize");
357
358 uintX_t Offset = Sec->sh_offset;
359 uintX_t Size = Sec->sh_size;
360
361 if (Size % sizeof(T))
362 return createError("size is not a multiple of sh_entsize");
363 if ((std::numeric_limits<uintX_t>::max() - Offset < Size) ||
364 Offset + Size > Buf.size())
365 return createError("invalid section offset");
366
367 if (Offset % alignof(T))
368 return createError("unaligned data");
369
370 const T *Start = reinterpret_cast<const T *>(base() + Offset);
371 return makeArrayRef(Start, Size / sizeof(T));
372}
373
374template <class ELFT>
375Expected<ArrayRef<uint8_t>>
376ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const {
377 return getSectionContentsAsArray<uint8_t>(Sec);
378}
379
380template <class ELFT>
381StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
382 return getELFRelocationTypeName(getHeader()->e_machine, Type);
383}
384
385template <class ELFT>
386void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
387 SmallVectorImpl<char> &Result) const {
388 if (!isMipsELF64()) {
389 StringRef Name = getRelocationTypeName(Type);
390 Result.append(Name.begin(), Name.end());
391 } else {
392 // The Mips N64 ABI allows up to three operations to be specified per
393 // relocation record. Unfortunately there's no easy way to test for the
394 // presence of N64 ELFs as they have no special flag that identifies them
395 // as being N64. We can safely assume at the moment that all Mips
396 // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough
397 // information to disambiguate between old vs new ABIs.
398 uint8_t Type1 = (Type >> 0) & 0xFF;
399 uint8_t Type2 = (Type >> 8) & 0xFF;
400 uint8_t Type3 = (Type >> 16) & 0xFF;
401
402 // Concat all three relocation type names.
403 StringRef Name = getRelocationTypeName(Type1);
404 Result.append(Name.begin(), Name.end());
405
406 Name = getRelocationTypeName(Type2);
407 Result.append(1, '/');
408 Result.append(Name.begin(), Name.end());
409
410 Name = getRelocationTypeName(Type3);
411 Result.append(1, '/');
412 Result.append(Name.begin(), Name.end());
413 }
414}
415
416template <class ELFT>
Andrew Walbran16937d02019-10-22 13:54:20 +0100417uint32_t ELFFile<ELFT>::getRelativeRelocationType() const {
418 return getELFRelativeRelocationType(getHeader()->e_machine);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100419}
420
421template <class ELFT>
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100422Expected<const typename ELFT::Sym *>
423ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
424 const Elf_Shdr *SymTab) const {
425 uint32_t Index = Rel->getSymbol(isMips64EL());
426 if (Index == 0)
427 return nullptr;
428 return getEntry<Elf_Sym>(SymTab, Index);
429}
430
431template <class ELFT>
432Expected<StringRef>
433ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const {
434 uint32_t Index = getHeader()->e_shstrndx;
435 if (Index == ELF::SHN_XINDEX)
436 Index = Sections[0].sh_link;
437
438 if (!Index) // no section string table.
439 return "";
440 if (Index >= Sections.size())
441 return createError("invalid section index");
442 return getStringTable(&Sections[Index]);
443}
444
445template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
446
447template <class ELFT>
448Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
449 if (sizeof(Elf_Ehdr) > Object.size())
450 return createError("Invalid buffer");
451 return ELFFile(Object);
452}
453
454template <class ELFT>
455Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
456 const uintX_t SectionTableOffset = getHeader()->e_shoff;
457 if (SectionTableOffset == 0)
458 return ArrayRef<Elf_Shdr>();
459
460 if (getHeader()->e_shentsize != sizeof(Elf_Shdr))
461 return createError(
462 "invalid section header entry size (e_shentsize) in ELF header");
463
464 const uint64_t FileSize = Buf.size();
465
466 if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
467 return createError("section header table goes past the end of the file");
468
469 // Invalid address alignment of section headers
470 if (SectionTableOffset & (alignof(Elf_Shdr) - 1))
471 return createError("invalid alignment of section headers");
472
473 const Elf_Shdr *First =
474 reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
475
476 uintX_t NumSections = getHeader()->e_shnum;
477 if (NumSections == 0)
478 NumSections = First->sh_size;
479
480 if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
481 return createError("section table goes past the end of file");
482
483 const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
484
485 // Section table goes past end of file!
486 if (SectionTableOffset + SectionTableSize > FileSize)
487 return createError("section table goes past the end of file");
488
489 return makeArrayRef(First, NumSections);
490}
491
492template <class ELFT>
493template <typename T>
494Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section,
495 uint32_t Entry) const {
496 auto SecOrErr = getSection(Section);
497 if (!SecOrErr)
498 return SecOrErr.takeError();
499 return getEntry<T>(*SecOrErr, Entry);
500}
501
502template <class ELFT>
503template <typename T>
504Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section,
505 uint32_t Entry) const {
506 if (sizeof(T) != Section->sh_entsize)
507 return createError("invalid sh_entsize");
508 size_t Pos = Section->sh_offset + Entry * sizeof(T);
509 if (Pos + sizeof(T) > Buf.size())
510 return createError("invalid section offset");
511 return reinterpret_cast<const T *>(base() + Pos);
512}
513
514template <class ELFT>
515Expected<const typename ELFT::Shdr *>
516ELFFile<ELFT>::getSection(uint32_t Index) const {
517 auto TableOrErr = sections();
518 if (!TableOrErr)
519 return TableOrErr.takeError();
520 return object::getSection<ELFT>(*TableOrErr, Index);
521}
522
523template <class ELFT>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100524Expected<const typename ELFT::Shdr *>
525ELFFile<ELFT>::getSection(const StringRef SectionName) const {
526 auto TableOrErr = sections();
527 if (!TableOrErr)
528 return TableOrErr.takeError();
529 for (auto &Sec : *TableOrErr) {
530 auto SecNameOrErr = getSectionName(&Sec);
531 if (!SecNameOrErr)
532 return SecNameOrErr.takeError();
533 if (*SecNameOrErr == SectionName)
534 return &Sec;
535 }
536 return createError("invalid section name");
537}
538
539template <class ELFT>
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100540Expected<StringRef>
541ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
542 if (Section->sh_type != ELF::SHT_STRTAB)
543 return createError("invalid sh_type for string table, expected SHT_STRTAB");
544 auto V = getSectionContentsAsArray<char>(Section);
545 if (!V)
546 return V.takeError();
547 ArrayRef<char> Data = *V;
548 if (Data.empty())
549 return createError("empty string table");
550 if (Data.back() != '\0')
551 return createError("string table non-null terminated");
552 return StringRef(Data.begin(), Data.size());
553}
554
555template <class ELFT>
556Expected<ArrayRef<typename ELFT::Word>>
557ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const {
558 auto SectionsOrErr = sections();
559 if (!SectionsOrErr)
560 return SectionsOrErr.takeError();
561 return getSHNDXTable(Section, *SectionsOrErr);
562}
563
564template <class ELFT>
565Expected<ArrayRef<typename ELFT::Word>>
566ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section,
567 Elf_Shdr_Range Sections) const {
568 assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);
569 auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section);
570 if (!VOrErr)
571 return VOrErr.takeError();
572 ArrayRef<Elf_Word> V = *VOrErr;
573 auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link);
574 if (!SymTableOrErr)
575 return SymTableOrErr.takeError();
576 const Elf_Shdr &SymTable = **SymTableOrErr;
577 if (SymTable.sh_type != ELF::SHT_SYMTAB &&
578 SymTable.sh_type != ELF::SHT_DYNSYM)
579 return createError("invalid sh_type");
580 if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
581 return createError("invalid section contents size");
582 return V;
583}
584
585template <class ELFT>
586Expected<StringRef>
587ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const {
588 auto SectionsOrErr = sections();
589 if (!SectionsOrErr)
590 return SectionsOrErr.takeError();
591 return getStringTableForSymtab(Sec, *SectionsOrErr);
592}
593
594template <class ELFT>
595Expected<StringRef>
596ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec,
597 Elf_Shdr_Range Sections) const {
598
599 if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)
600 return createError(
601 "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");
602 auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link);
603 if (!SectionOrErr)
604 return SectionOrErr.takeError();
605 return getStringTable(*SectionOrErr);
606}
607
608template <class ELFT>
609Expected<StringRef>
610ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const {
611 auto SectionsOrErr = sections();
612 if (!SectionsOrErr)
613 return SectionsOrErr.takeError();
614 auto Table = getSectionStringTable(*SectionsOrErr);
615 if (!Table)
616 return Table.takeError();
617 return getSectionName(Section, *Table);
618}
619
620template <class ELFT>
621Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section,
622 StringRef DotShstrtab) const {
623 uint32_t Offset = Section->sh_name;
624 if (Offset == 0)
625 return StringRef();
626 if (Offset >= DotShstrtab.size())
627 return createError("invalid string offset");
628 return StringRef(DotShstrtab.data() + Offset);
629}
630
631/// This function returns the hash value for a symbol in the .dynsym section
632/// Name of the API remains consistent as specified in the libelf
633/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
634inline unsigned hashSysV(StringRef SymbolName) {
635 unsigned h = 0, g;
636 for (char C : SymbolName) {
637 h = (h << 4) + C;
638 g = h & 0xf0000000L;
639 if (g != 0)
640 h ^= g >> 24;
641 h &= ~g;
642 }
643 return h;
644}
645
646} // end namespace object
647} // end namespace llvm
648
649#endif // LLVM_OBJECT_ELF_H