1 //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
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
;
54 std::string
getSecIndexForError(const ELFFile
<ELFT
> *Obj
,
55 const typename
ELFT::Shdr
*Sec
) {
56 auto TableOrErr
= Obj
->sections();
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
63 llvm::consumeError(TableOrErr
.takeError());
64 return "[unknown index]";
67 static inline Error
defaultWarningHandler(const Twine
&Msg
) {
68 return createError(Msg
);
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(); }
116 ELFFile(StringRef Object
);
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;
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
);
154 return getHeader()->getDataEncoding() == ELF::ELFDATA2LSB
;
157 bool isMipsELF64() const {
158 return getHeader()->e_machine
== ELF::EM_MIPS
&&
159 getHeader()->getFileClass() == ELF::ELFCLASS64
;
162 bool isMips64EL() const { return isMipsELF64() && isLE(); }
164 Expected
<Elf_Shdr_Range
> sections() const;
166 Expected
<Elf_Dyn_Range
> dynamicEntries() const;
168 Expected
<const uint8_t *> toMappedAddr(uint64_t VAddr
) const;
170 Expected
<Elf_Sym_Range
> symbols(const Elf_Shdr
*Sec
) const {
172 return makeArrayRef
<Elf_Sym
>(nullptr, nullptr);
173 return getSectionContentsAsArray
<Elf_Sym
>(Sec
);
176 Expected
<Elf_Rela_Range
> relas(const Elf_Shdr
*Sec
) const {
177 return getSectionContentsAsArray
<Elf_Rela
>(Sec
);
180 Expected
<Elf_Rel_Range
> rels(const Elf_Shdr
*Sec
) const {
181 return getSectionContentsAsArray
<Elf_Rel
>(Sec
);
184 Expected
<Elf_Relr_Range
> relrs(const Elf_Shdr
*Sec
) const {
185 return getSectionContentsAsArray
<Elf_Relr
>(Sec
);
188 Expected
<std::vector
<Elf_Rela
>> decode_relrs(Elf_Relr_Range relrs
) const;
190 Expected
<std::vector
<Elf_Rela
>> android_relas(const Elf_Shdr
*Sec
) const;
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
) >
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
));
206 reinterpret_cast<const Elf_Phdr
*>(base() + getHeader()->e_phoff
);
207 return makeArrayRef(Begin
, Begin
+ getHeader()->e_phnum
);
210 /// Get an iterator over notes in a program header.
212 /// The program header must be of type \c PT_NOTE.
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
);
226 return Elf_Note_Iterator(base() + Phdr
.p_offset
, Phdr
.p_filesz
, Err
);
229 /// Get an iterator over notes in a section.
231 /// The section must be of type \c SHT_NOTE.
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
);
246 return Elf_Note_Iterator(base() + Shdr
.sh_offset
, Shdr
.sh_size
, Err
);
249 /// Get the end iterator for notes.
250 Elf_Note_Iterator
notes_end() const {
251 return Elf_Note_Iterator();
254 /// Get an iterator range over notes of a program header.
256 /// The program header must be of type \c PT_NOTE.
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
,
263 return make_range(notes_begin(Phdr
, Err
), notes_end());
266 /// Get an iterator range over notes of a section.
268 /// The section must be of type \c SHT_NOTE.
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
,
275 return make_range(notes_begin(Shdr
, Err
), notes_end());
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;
291 Expected
<const Elf_Sym
*> getSymbol(const Elf_Shdr
*Sec
,
292 uint32_t Index
) const;
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;
304 using ELF32LEFile
= ELFFile
<ELF32LE
>;
305 using ELF64LEFile
= ELFFile
<ELF64LE
>;
306 using ELF32BEFile
= ELFFile
<ELF32BE
>;
307 using ELF64BEFile
= ELFFile
<ELF64BE
>;
309 template <class ELFT
>
310 inline Expected
<const typename
ELFT::Shdr
*>
311 getSection(typename
ELFT::ShdrRange Sections
, uint32_t Index
) {
312 if (Index
>= Sections
.size())
313 return createError("invalid section index: " + Twine(Index
));
314 return &Sections
[Index
];
317 template <class ELFT
>
318 inline Expected
<uint32_t>
319 getExtendedSymbolTableIndex(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())
326 "extended symbol index (" + Twine(Index
) +
327 ") is past the end of the SHT_SYMTAB_SHNDX section of size " +
328 Twine(ShndxTable
.size()));
330 // The size of the table was checked in getSHNDXTable.
331 return ShndxTable
[Index
];
334 template <class ELFT
>
336 ELFFile
<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
);
343 return ErrorOrIndex
.takeError();
344 return *ErrorOrIndex
;
346 if (Index
== ELF::SHN_UNDEF
|| Index
>= ELF::SHN_LORESERVE
)
351 template <class ELFT
>
352 Expected
<const typename
ELFT::Shdr
*>
353 ELFFile
<ELFT
>::getSection(const Elf_Sym
*Sym
, const Elf_Shdr
*SymTab
,
354 ArrayRef
<Elf_Word
> ShndxTable
) const {
355 auto SymsOrErr
= symbols(SymTab
);
357 return SymsOrErr
.takeError();
358 return getSection(Sym
, *SymsOrErr
, ShndxTable
);
361 template <class ELFT
>
362 Expected
<const typename
ELFT::Shdr
*>
363 ELFFile
<ELFT
>::getSection(const Elf_Sym
*Sym
, Elf_Sym_Range Symbols
,
364 ArrayRef
<Elf_Word
> ShndxTable
) const {
365 auto IndexOrErr
= getSectionIndex(Sym
, Symbols
, ShndxTable
);
367 return IndexOrErr
.takeError();
368 uint32_t Index
= *IndexOrErr
;
371 return getSection(Index
);
374 template <class ELFT
>
375 Expected
<const typename
ELFT::Sym
*>
376 ELFFile
<ELFT
>::getSymbol(const Elf_Shdr
*Sec
, uint32_t Index
) const {
377 auto SymsOrErr
= symbols(Sec
);
379 return SymsOrErr
.takeError();
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
];
389 template <class ELFT
>
390 template <typename T
>
391 Expected
<ArrayRef
<T
>>
392 ELFFile
<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
));
397 uintX_t Offset
= Sec
->sh_offset
;
398 uintX_t Size
= Sec
->sh_size
;
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 Offset
+ Size
> Buf
.size())
407 return createError("section " + getSecIndexForError(this, Sec
) +
408 " has a sh_offset (0x" + Twine::utohexstr(Offset
) +
409 ") + sh_size (0x" + Twine(Size
) +
410 ") that cannot be represented");
412 if (Offset
% alignof(T
))
413 // TODO: this error is untested.
414 return createError("unaligned data");
416 const T
*Start
= reinterpret_cast<const T
*>(base() + Offset
);
417 return makeArrayRef(Start
, Size
/ sizeof(T
));
420 template <class ELFT
>
421 Expected
<ArrayRef
<uint8_t>>
422 ELFFile
<ELFT
>::getSectionContents(const Elf_Shdr
*Sec
) const {
423 return getSectionContentsAsArray
<uint8_t>(Sec
);
426 template <class ELFT
>
427 StringRef ELFFile
<ELFT
>::getRelocationTypeName(uint32_t Type
) const {
428 return getELFRelocationTypeName(getHeader()->e_machine
, Type
);
431 template <class ELFT
>
432 void ELFFile
<ELFT
>::getRelocationTypeName(uint32_t Type
,
433 SmallVectorImpl
<char> &Result
) const {
434 if (!isMipsELF64()) {
435 StringRef Name
= getRelocationTypeName(Type
);
436 Result
.append(Name
.begin(), Name
.end());
438 // The Mips N64 ABI allows up to three operations to be specified per
439 // relocation record. Unfortunately there's no easy way to test for the
440 // presence of N64 ELFs as they have no special flag that identifies them
441 // as being N64. We can safely assume at the moment that all Mips
442 // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough
443 // information to disambiguate between old vs new ABIs.
444 uint8_t Type1
= (Type
>> 0) & 0xFF;
445 uint8_t Type2
= (Type
>> 8) & 0xFF;
446 uint8_t Type3
= (Type
>> 16) & 0xFF;
448 // Concat all three relocation type names.
449 StringRef Name
= getRelocationTypeName(Type1
);
450 Result
.append(Name
.begin(), Name
.end());
452 Name
= getRelocationTypeName(Type2
);
453 Result
.append(1, '/');
454 Result
.append(Name
.begin(), Name
.end());
456 Name
= getRelocationTypeName(Type3
);
457 Result
.append(1, '/');
458 Result
.append(Name
.begin(), Name
.end());
462 template <class ELFT
>
463 uint32_t ELFFile
<ELFT
>::getRelativeRelocationType() const {
464 return getELFRelativeRelocationType(getHeader()->e_machine
);
467 template <class ELFT
>
468 Expected
<const typename
ELFT::Sym
*>
469 ELFFile
<ELFT
>::getRelocationSymbol(const Elf_Rel
*Rel
,
470 const Elf_Shdr
*SymTab
) const {
471 uint32_t Index
= Rel
->getSymbol(isMips64EL());
474 return getEntry
<Elf_Sym
>(SymTab
, Index
);
477 template <class ELFT
>
479 ELFFile
<ELFT
>::getSectionStringTable(Elf_Shdr_Range Sections
,
480 WarningHandler WarnHandler
) const {
481 uint32_t Index
= getHeader()->e_shstrndx
;
482 if (Index
== ELF::SHN_XINDEX
)
483 Index
= Sections
[0].sh_link
;
485 if (!Index
) // no section string table.
487 if (Index
>= Sections
.size())
488 return createError("section header string table index " + Twine(Index
) +
490 return getStringTable(&Sections
[Index
], WarnHandler
);
493 template <class ELFT
> ELFFile
<ELFT
>::ELFFile(StringRef Object
) : Buf(Object
) {}
495 template <class ELFT
>
496 Expected
<ELFFile
<ELFT
>> ELFFile
<ELFT
>::create(StringRef Object
) {
497 if (sizeof(Elf_Ehdr
) > Object
.size())
498 return createError("invalid buffer: the size (" + Twine(Object
.size()) +
499 ") is smaller than an ELF header (" +
500 Twine(sizeof(Elf_Ehdr
)) + ")");
501 return ELFFile(Object
);
504 template <class ELFT
>
505 Expected
<typename
ELFT::ShdrRange
> ELFFile
<ELFT
>::sections() const {
506 const uintX_t SectionTableOffset
= getHeader()->e_shoff
;
507 if (SectionTableOffset
== 0)
508 return ArrayRef
<Elf_Shdr
>();
510 if (getHeader()->e_shentsize
!= sizeof(Elf_Shdr
))
511 return createError("invalid e_shentsize in ELF header: " +
512 Twine(getHeader()->e_shentsize
));
514 const uint64_t FileSize
= Buf
.size();
515 if (SectionTableOffset
+ sizeof(Elf_Shdr
) > FileSize
||
516 SectionTableOffset
+ (uintX_t
)sizeof(Elf_Shdr
) < SectionTableOffset
)
518 "section header table goes past the end of the file: e_shoff = 0x" +
519 Twine::utohexstr(SectionTableOffset
));
521 // Invalid address alignment of section headers
522 if (SectionTableOffset
& (alignof(Elf_Shdr
) - 1))
523 // TODO: this error is untested.
524 return createError("invalid alignment of section headers");
526 const Elf_Shdr
*First
=
527 reinterpret_cast<const Elf_Shdr
*>(base() + SectionTableOffset
);
529 uintX_t NumSections
= getHeader()->e_shnum
;
530 if (NumSections
== 0)
531 NumSections
= First
->sh_size
;
533 if (NumSections
> UINT64_MAX
/ sizeof(Elf_Shdr
))
534 return createError("invalid number of sections specified in the NULL "
535 "section's sh_size field (" +
536 Twine(NumSections
) + ")");
538 const uint64_t SectionTableSize
= NumSections
* sizeof(Elf_Shdr
);
539 if (SectionTableOffset
+ SectionTableSize
< SectionTableOffset
)
541 "invalid section header table offset (e_shoff = 0x" +
542 Twine::utohexstr(SectionTableOffset
) +
543 ") or invalid number of sections specified in the first section "
544 "header's sh_size field (0x" +
545 Twine::utohexstr(NumSections
) + ")");
547 // Section table goes past end of file!
548 if (SectionTableOffset
+ SectionTableSize
> FileSize
)
549 return createError("section table goes past the end of file");
550 return makeArrayRef(First
, NumSections
);
553 template <class ELFT
>
554 template <typename T
>
555 Expected
<const T
*> ELFFile
<ELFT
>::getEntry(uint32_t Section
,
556 uint32_t Entry
) const {
557 auto SecOrErr
= getSection(Section
);
559 return SecOrErr
.takeError();
560 return getEntry
<T
>(*SecOrErr
, Entry
);
563 template <class ELFT
>
564 template <typename T
>
565 Expected
<const T
*> ELFFile
<ELFT
>::getEntry(const Elf_Shdr
*Section
,
566 uint32_t Entry
) const {
567 if (sizeof(T
) != Section
->sh_entsize
)
568 return createError("section " + getSecIndexForError(this, Section
) +
569 " has invalid sh_entsize: expected " + Twine(sizeof(T
)) +
570 ", but got " + Twine(Section
->sh_entsize
));
571 size_t Pos
= Section
->sh_offset
+ Entry
* sizeof(T
);
572 if (Pos
+ sizeof(T
) > Buf
.size())
573 return createError("unable to access section " +
574 getSecIndexForError(this, Section
) + " data at 0x" +
575 Twine::utohexstr(Pos
) +
576 ": offset goes past the end of file");
577 return reinterpret_cast<const T
*>(base() + Pos
);
580 template <class ELFT
>
581 Expected
<const typename
ELFT::Shdr
*>
582 ELFFile
<ELFT
>::getSection(uint32_t Index
) const {
583 auto TableOrErr
= sections();
585 return TableOrErr
.takeError();
586 return object::getSection
<ELFT
>(*TableOrErr
, Index
);
589 template <class ELFT
>
591 ELFFile
<ELFT
>::getStringTable(const Elf_Shdr
*Section
,
592 WarningHandler WarnHandler
) const {
593 if (Section
->sh_type
!= ELF::SHT_STRTAB
)
594 if (Error E
= WarnHandler("invalid sh_type for string table section " +
595 getSecIndexForError(this, Section
) +
596 ": expected SHT_STRTAB, but got " +
597 object::getELFSectionTypeName(
598 getHeader()->e_machine
, Section
->sh_type
)))
601 auto V
= getSectionContentsAsArray
<char>(Section
);
603 return V
.takeError();
604 ArrayRef
<char> Data
= *V
;
606 return createError("SHT_STRTAB string table section " +
607 getSecIndexForError(this, Section
) + " is empty");
608 if (Data
.back() != '\0')
609 return createError("SHT_STRTAB string table section " +
610 getSecIndexForError(this, Section
) +
611 " is non-null terminated");
612 return StringRef(Data
.begin(), Data
.size());
615 template <class ELFT
>
616 Expected
<ArrayRef
<typename
ELFT::Word
>>
617 ELFFile
<ELFT
>::getSHNDXTable(const Elf_Shdr
&Section
) const {
618 auto SectionsOrErr
= sections();
620 return SectionsOrErr
.takeError();
621 return getSHNDXTable(Section
, *SectionsOrErr
);
624 template <class ELFT
>
625 Expected
<ArrayRef
<typename
ELFT::Word
>>
626 ELFFile
<ELFT
>::getSHNDXTable(const Elf_Shdr
&Section
,
627 Elf_Shdr_Range Sections
) const {
628 assert(Section
.sh_type
== ELF::SHT_SYMTAB_SHNDX
);
629 auto VOrErr
= getSectionContentsAsArray
<Elf_Word
>(&Section
);
631 return VOrErr
.takeError();
632 ArrayRef
<Elf_Word
> V
= *VOrErr
;
633 auto SymTableOrErr
= object::getSection
<ELFT
>(Sections
, Section
.sh_link
);
635 return SymTableOrErr
.takeError();
636 const Elf_Shdr
&SymTable
= **SymTableOrErr
;
637 if (SymTable
.sh_type
!= ELF::SHT_SYMTAB
&&
638 SymTable
.sh_type
!= ELF::SHT_DYNSYM
)
639 return createError("SHT_SYMTAB_SHNDX section is linked with " +
640 object::getELFSectionTypeName(getHeader()->e_machine
,
642 " section (expected SHT_SYMTAB/SHT_DYNSYM)");
644 if (V
.size() != (SymTable
.sh_size
/ sizeof(Elf_Sym
)))
645 return createError("SHT_SYMTAB_SHNDX section has sh_size (" +
646 Twine(SymTable
.sh_size
) +
647 ") which is not equal to the number of symbols (" +
648 Twine(V
.size()) + ")");
652 template <class ELFT
>
654 ELFFile
<ELFT
>::getStringTableForSymtab(const Elf_Shdr
&Sec
) const {
655 auto SectionsOrErr
= sections();
657 return SectionsOrErr
.takeError();
658 return getStringTableForSymtab(Sec
, *SectionsOrErr
);
661 template <class ELFT
>
663 ELFFile
<ELFT
>::getStringTableForSymtab(const Elf_Shdr
&Sec
,
664 Elf_Shdr_Range Sections
) const {
666 if (Sec
.sh_type
!= ELF::SHT_SYMTAB
&& Sec
.sh_type
!= ELF::SHT_DYNSYM
)
667 // TODO: this error is untested.
669 "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");
670 auto SectionOrErr
= object::getSection
<ELFT
>(Sections
, Sec
.sh_link
);
672 return SectionOrErr
.takeError();
673 return getStringTable(*SectionOrErr
);
676 template <class ELFT
>
678 ELFFile
<ELFT
>::getSectionName(const Elf_Shdr
*Section
,
679 WarningHandler WarnHandler
) const {
680 auto SectionsOrErr
= sections();
682 return SectionsOrErr
.takeError();
683 auto Table
= getSectionStringTable(*SectionsOrErr
, WarnHandler
);
685 return Table
.takeError();
686 return getSectionName(Section
, *Table
);
689 template <class ELFT
>
690 Expected
<StringRef
> ELFFile
<ELFT
>::getSectionName(const Elf_Shdr
*Section
,
691 StringRef DotShstrtab
) const {
692 uint32_t Offset
= Section
->sh_name
;
695 if (Offset
>= DotShstrtab
.size())
696 return createError("a section " + getSecIndexForError(this, Section
) +
697 " has an invalid sh_name (0x" +
698 Twine::utohexstr(Offset
) +
699 ") offset which goes past the end of the "
700 "section name string table");
701 return StringRef(DotShstrtab
.data() + Offset
);
704 /// This function returns the hash value for a symbol in the .dynsym section
705 /// Name of the API remains consistent as specified in the libelf
706 /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
707 inline unsigned hashSysV(StringRef SymbolName
) {
709 for (char C
: SymbolName
) {
719 } // end namespace object
720 } // end namespace llvm
722 #endif // LLVM_OBJECT_ELF_H