LLVM  7.0.0svn
ELF.h
Go to the documentation of this file.
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 
31 namespace llvm {
32 namespace object {
33 
36 
37 // Subclasses of ELFFile may need this for template instantiation
38 inline std::pair<unsigned char, unsigned char>
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 
47 static inline Error createError(StringRef Err) {
48  return make_error<StringError>(Err, object_error::parse_failed);
49 }
50 
51 template <class ELFT>
52 class ELFFile {
53 public:
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 
83 private:
84  StringRef Buf;
85 
86  ELFFile(StringRef Object);
87 
88 public:
89  const Elf_Ehdr *getHeader() const {
90  return reinterpret_cast<const Elf_Ehdr *>(base());
91  }
92 
93  template <typename T>
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;
101  Elf_Shdr_Range Sections) const;
102 
103  Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const;
105  Elf_Shdr_Range Sections) const;
106 
109  SmallVectorImpl<char> &Result) const;
110 
111  /// \brief Get the symbol for a given relocation.
113  const Elf_Shdr *SymTab) const;
114 
115  static Expected<ELFFile> create(StringRef Object);
116 
117  bool isMipsELF64() const {
118  return getHeader()->e_machine == ELF::EM_MIPS &&
119  getHeader()->getFileClass() == ELF::ELFCLASS64;
120  }
121 
122  bool isMips64EL() const {
123  return isMipsELF64() &&
124  getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
125  }
126 
128 
130  if (!Sec)
131  return makeArrayRef<Elf_Sym>(nullptr, nullptr);
132  return getSectionContentsAsArray<Elf_Sym>(Sec);
133  }
134 
136  return getSectionContentsAsArray<Elf_Rela>(Sec);
137  }
138 
140  return getSectionContentsAsArray<Elf_Rel>(Sec);
141  }
142 
144 
145  /// \brief Iterate over program header table.
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 
160  ArrayRef<Elf_Word> ShndxTable) const;
162  const Elf_Shdr *SymTab,
163  ArrayRef<Elf_Word> ShndxTable) const;
165  Elf_Sym_Range Symtab,
166  ArrayRef<Elf_Word> ShndxTable) const;
168 
170  uint32_t Index) const;
171 
172  Expected<StringRef> getSectionName(const Elf_Shdr *Section) const;
174  StringRef DotShstrtab) const;
175  template <typename T>
178 };
179 
184 
185 template <class ELFT>
187 getSection(typename ELFT::ShdrRange Sections, uint32_t Index) {
188  if (Index >= Sections.size())
189  return createError("invalid section index");
190  return &Sections[Index];
191 }
192 
193 template <class ELFT>
194 inline Expected<uint32_t>
195 getExtendedSymbolTableIndex(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 
207 template <class ELFT>
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 
224 template <class ELFT>
226 ELFFile<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 
234 template <class ELFT>
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 
247 template <class ELFT>
249 getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) {
250  if (Index >= Symbols.size())
251  return createError("invalid symbol index");
252  return &Symbols[Index];
253 }
254 
255 template <class ELFT>
257 ELFFile<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 
264 template <class ELFT>
265 template <typename T>
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  if (Offset % alignof(T))
281  return createError("unaligned data");
282 
283  const T *Start = reinterpret_cast<const T *>(base() + Offset);
284  return makeArrayRef(Start, Size / sizeof(T));
285 }
286 
287 template <class ELFT>
290  return getSectionContentsAsArray<uint8_t>(Sec);
291 }
292 
293 template <class ELFT>
295  return getELFRelocationTypeName(getHeader()->e_machine, Type);
296 }
297 
298 template <class ELFT>
300  SmallVectorImpl<char> &Result) const {
301  if (!isMipsELF64()) {
303  Result.append(Name.begin(), Name.end());
304  } else {
305  // The Mips N64 ABI allows up to three operations to be specified per
306  // relocation record. Unfortunately there's no easy way to test for the
307  // presence of N64 ELFs as they have no special flag that identifies them
308  // as being N64. We can safely assume at the moment that all Mips
309  // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough
310  // information to disambiguate between old vs new ABIs.
311  uint8_t Type1 = (Type >> 0) & 0xFF;
312  uint8_t Type2 = (Type >> 8) & 0xFF;
313  uint8_t Type3 = (Type >> 16) & 0xFF;
314 
315  // Concat all three relocation type names.
317  Result.append(Name.begin(), Name.end());
318 
319  Name = getRelocationTypeName(Type2);
320  Result.append(1, '/');
321  Result.append(Name.begin(), Name.end());
322 
323  Name = getRelocationTypeName(Type3);
324  Result.append(1, '/');
325  Result.append(Name.begin(), Name.end());
326  }
327 }
328 
329 template <class ELFT>
332  const Elf_Shdr *SymTab) const {
333  uint32_t Index = Rel->getSymbol(isMips64EL());
334  if (Index == 0)
335  return nullptr;
336  return getEntry<Elf_Sym>(SymTab, Index);
337 }
338 
339 template <class ELFT>
342  uint32_t Index = getHeader()->e_shstrndx;
343  if (Index == ELF::SHN_XINDEX)
344  Index = Sections[0].sh_link;
345 
346  if (!Index) // no section string table.
347  return "";
348  if (Index >= Sections.size())
349  return createError("invalid section index");
350  return getStringTable(&Sections[Index]);
351 }
352 
353 template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
354 
355 template <class ELFT>
357  if (sizeof(Elf_Ehdr) > Object.size())
358  return createError("Invalid buffer");
359  return ELFFile(Object);
360 }
361 
362 template <class ELFT>
364  const uintX_t SectionTableOffset = getHeader()->e_shoff;
365  if (SectionTableOffset == 0)
366  return ArrayRef<Elf_Shdr>();
367 
368  if (getHeader()->e_shentsize != sizeof(Elf_Shdr))
369  return createError(
370  "invalid section header entry size (e_shentsize) in ELF header");
371 
372  const uint64_t FileSize = Buf.size();
373 
374  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
375  return createError("section header table goes past the end of the file");
376 
377  // Invalid address alignment of section headers
378  if (SectionTableOffset & (alignof(Elf_Shdr) - 1))
379  return createError("invalid alignment of section headers");
380 
381  const Elf_Shdr *First =
382  reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
383 
384  uintX_t NumSections = getHeader()->e_shnum;
385  if (NumSections == 0)
386  NumSections = First->sh_size;
387 
388  if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
389  return createError("section table goes past the end of file");
390 
391  const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
392 
393  // Section table goes past end of file!
394  if (SectionTableOffset + SectionTableSize > FileSize)
395  return createError("section table goes past the end of file");
396 
397  return makeArrayRef(First, NumSections);
398 }
399 
400 template <class ELFT>
401 template <typename T>
403  uint32_t Entry) const {
404  auto SecOrErr = getSection(Section);
405  if (!SecOrErr)
406  return SecOrErr.takeError();
407  return getEntry<T>(*SecOrErr, Entry);
408 }
409 
410 template <class ELFT>
411 template <typename T>
413  uint32_t Entry) const {
414  if (sizeof(T) != Section->sh_entsize)
415  return createError("invalid sh_entsize");
416  size_t Pos = Section->sh_offset + Entry * sizeof(T);
417  if (Pos + sizeof(T) > Buf.size())
418  return createError("invalid section offset");
419  return reinterpret_cast<const T *>(base() + Pos);
420 }
421 
422 template <class ELFT>
425  auto TableOrErr = sections();
426  if (!TableOrErr)
427  return TableOrErr.takeError();
428  return object::getSection<ELFT>(*TableOrErr, Index);
429 }
430 
431 template <class ELFT>
434  if (Section->sh_type != ELF::SHT_STRTAB)
435  return createError("invalid sh_type for string table, expected SHT_STRTAB");
436  auto V = getSectionContentsAsArray<char>(Section);
437  if (!V)
438  return V.takeError();
439  ArrayRef<char> Data = *V;
440  if (Data.empty())
441  return createError("empty string table");
442  if (Data.back() != '\0')
443  return createError("string table non-null terminated");
444  return StringRef(Data.begin(), Data.size());
445 }
446 
447 template <class ELFT>
450  auto SectionsOrErr = sections();
451  if (!SectionsOrErr)
452  return SectionsOrErr.takeError();
453  return getSHNDXTable(Section, *SectionsOrErr);
454 }
455 
456 template <class ELFT>
459  Elf_Shdr_Range Sections) const {
460  assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);
461  auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section);
462  if (!VOrErr)
463  return VOrErr.takeError();
464  ArrayRef<Elf_Word> V = *VOrErr;
465  auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link);
466  if (!SymTableOrErr)
467  return SymTableOrErr.takeError();
468  const Elf_Shdr &SymTable = **SymTableOrErr;
469  if (SymTable.sh_type != ELF::SHT_SYMTAB &&
470  SymTable.sh_type != ELF::SHT_DYNSYM)
471  return createError("invalid sh_type");
472  if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
473  return createError("invalid section contents size");
474  return V;
475 }
476 
477 template <class ELFT>
480  auto SectionsOrErr = sections();
481  if (!SectionsOrErr)
482  return SectionsOrErr.takeError();
483  return getStringTableForSymtab(Sec, *SectionsOrErr);
484 }
485 
486 template <class ELFT>
489  Elf_Shdr_Range Sections) const {
490 
491  if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)
492  return createError(
493  "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");
494  auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link);
495  if (!SectionOrErr)
496  return SectionOrErr.takeError();
497  return getStringTable(*SectionOrErr);
498 }
499 
500 template <class ELFT>
503  auto SectionsOrErr = sections();
504  if (!SectionsOrErr)
505  return SectionsOrErr.takeError();
506  auto Table = getSectionStringTable(*SectionsOrErr);
507  if (!Table)
508  return Table.takeError();
509  return getSectionName(Section, *Table);
510 }
511 
512 template <class ELFT>
514  StringRef DotShstrtab) const {
515  uint32_t Offset = Section->sh_name;
516  if (Offset == 0)
517  return StringRef();
518  if (Offset >= DotShstrtab.size())
519  return createError("invalid string offset");
520  return StringRef(DotShstrtab.data() + Offset);
521 }
522 
523 /// This function returns the hash value for a symbol in the .dynsym section
524 /// Name of the API remains consistent as specified in the libelf
525 /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
526 inline unsigned hashSysV(StringRef SymbolName) {
527  unsigned h = 0, g;
528  for (char C : SymbolName) {
529  h = (h << 4) + C;
530  g = h & 0xf0000000L;
531  if (g != 0)
532  h ^= g >> 24;
533  h &= ~g;
534  }
535  return h;
536 }
537 
538 } // end namespace object
539 } // end namespace llvm
540 
541 #endif // LLVM_OBJECT_ELF_H
typename ELFT::Dyn Elf_Dyn
Definition: ELF.h:59
uint64_t CallInst * C
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
const T & back() const
back - Get the last element.
Definition: ArrayRef.h:158
typename ELFT::Rel Elf_Rel
Definition: ELF.h:61
Expected< const T * > getEntry(uint32_t Section, uint32_t Entry) const
Definition: ELF.h:402
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
static Expected< ELFFile > create(StringRef Object)
Definition: ELF.h:356
iterator begin() const
Definition: ArrayRef.h:137
typename ELFT::Vernaux Elf_Vernaux
Definition: ELF.h:66
StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
StringRef getRelocationTypeName(uint32_t Type) const
Definition: ELF.h:294
Expected< StringRef > getSectionStringTable(Elf_Shdr_Range Sections) const
Definition: ELF.h:341
ELFYAML::ELF_REL Type3
Definition: ELFYAML.cpp:900
Expected< StringRef > getStringTable(const Elf_Shdr *Section) const
Definition: ELF.h:433
static Error createError(StringRef Err)
Definition: ELF.h:47
unsigned hashSysV(StringRef SymbolName)
This function returns the hash value for a symbol in the .dynsym section Name of the API remains cons...
Definition: ELF.h:526
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
typename ELFT::Sym Elf_Sym
Definition: ELF.h:58
Expected< Elf_Phdr_Range > program_headers() const
Iterate over program header table.
Definition: ELF.h:146
const uint8_t * base() const
Definition: ELF.h:77
Expected< const Elf_Shdr * > getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef< Elf_Word > ShndxTable) const
Definition: ELF.h:226
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isMips64EL() const
Definition: ELF.h:122
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
Expected< Elf_Shdr_Range > sections() const
Definition: ELF.h:363
typename ELFT::PhdrRange Elf_Phdr_Range
Definition: ELF.h:75
typename ELFT::Phdr Elf_Phdr
Definition: ELF.h:60
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
Expected< ArrayRef< uint8_t > > getSectionContents(const Elf_Shdr *Sec) const
Definition: ELF.h:289
#define T
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
Definition: ELF.h:39
typename ELFT::GnuHash Elf_GnuHash
Definition: ELF.h:69
COFF::MachineTypes Machine
Definition: COFFYAML.cpp:363
typename ELFT::SymRange Elf_Sym_Range
Definition: ELF.h:72
Expected< ArrayRef< T > > getSectionContentsAsArray(const Elf_Shdr *Sec) const
Definition: ELF.h:267
Expected< Elf_Rel_Range > rels(const Elf_Shdr *Sec) const
Definition: ELF.h:139
Expected< ArrayRef< Elf_Word > > getSHNDXTable(const Elf_Shdr &Section) const
Definition: ELF.h:449
bool isMipsELF64() const
Definition: ELF.h:117
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
Expected< StringRef > getStringTableForSymtab(const Elf_Shdr &Section) const
Definition: ELF.h:479
Expected< Elf_Rela_Range > relas(const Elf_Shdr *Sec) const
Definition: ELF.h:135
typename ELFT::uint uintX_t
Definition: ELF.h:55
Expected< uint32_t > getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, ArrayRef< Elf_Word > ShndxTable) const
Definition: ELF.h:209
typename ELFT::Verdaux Elf_Verdaux
Definition: ELF.h:64
typename ELFT::Ehdr Elf_Ehdr
Definition: ELF.h:56
typename ELFT::Rela Elf_Rela
Definition: ELF.h:62
typename ELFT::Verneed Elf_Verneed
Definition: ELF.h:65
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
Definition: ELF.cpp:23
Expected< uint32_t > getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym, const typename ELFT::Sym *FirstSym, ArrayRef< typename ELFT::Word > ShndxTable)
Definition: ELF.h:195
size_t getBufSize() const
Definition: ELF.h:81
Expected< const Elf_Sym * > getRelocationSymbol(const Elf_Rel *Rel, const Elf_Shdr *SymTab) const
Get the symbol for a given relocation.
Definition: ELF.h:331
iterator begin() const
Definition: StringRef.h:106
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:396
typename ELFT::DynRange Elf_Dyn_Range
Definition: ELF.h:70
ELFYAML::ELF_REL Type2
Definition: ELFYAML.cpp:899
Expected< std::vector< Elf_Rela > > android_relas(const Elf_Shdr *Sec) const
Definition: ELF.cpp:220
Expected< const Elf_Sym * > getSymbol(const Elf_Shdr *Sec, uint32_t Index) const
Definition: ELF.h:257
Expected< Elf_Sym_Range > symbols(const Elf_Shdr *Sec) const
Definition: ELF.h:129
typename ELFT::Verdef Elf_Verdef
Definition: ELF.h:63
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
typename ELFT::RelRange Elf_Rel_Range
Definition: ELF.h:73
aarch64 promote const
typename ELFT::Versym Elf_Versym
Definition: ELF.h:67
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
typename ELFT::RelaRange Elf_Rela_Range
Definition: ELF.h:74
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Definition: ELFTypes.h:94
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
typename ELFT::ShdrRange Elf_Shdr_Range
Definition: ELF.h:71
const Elf_Ehdr * getHeader() const
Definition: ELF.h:89
iterator end() const
Definition: StringRef.h:108
typename ELFT::Shdr Elf_Shdr
Definition: ELF.h:57
Expected< StringRef > getSectionName(const Elf_Shdr *Section) const
Definition: ELF.h:502
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:144
typename ELFT::Hash Elf_Hash
Definition: ELF.h:68