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
);
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 {
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
) >
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
));
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
,
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
,
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;
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())
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
>
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
);
342 return ErrorOrIndex
.takeError();
343 return *ErrorOrIndex
;
345 if (Index
== ELF::SHN_UNDEF
|| Index
>= ELF::SHN_LORESERVE
)
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
);
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
);
366 return IndexOrErr
.takeError();
367 uint32_t Index
= *IndexOrErr
;
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
);
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());
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());
473 return getEntry
<Elf_Sym
>(SymTab
, Index
);
476 template <class ELFT
>
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.
486 if (Index
>= Sections
.size())
487 return createError("section header string table index " + Twine(Index
) +
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
)
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
)
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
);
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();
584 return TableOrErr
.takeError();
585 return object::getSection
<ELFT
>(*TableOrErr
, Index
);
588 template <class ELFT
>
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
)))
600 auto V
= getSectionContentsAsArray
<char>(Section
);
602 return V
.takeError();
603 ArrayRef
<char> Data
= *V
;
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();
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
);
630 return VOrErr
.takeError();
631 ArrayRef
<Elf_Word
> V
= *VOrErr
;
632 auto SymTableOrErr
= object::getSection
<ELFT
>(Sections
, Section
.sh_link
);
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
,
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()) + ")");
651 template <class ELFT
>
653 ELFFile
<ELFT
>::getStringTableForSymtab(const Elf_Shdr
&Sec
) const {
654 auto SectionsOrErr
= sections();
656 return SectionsOrErr
.takeError();
657 return getStringTableForSymtab(Sec
, *SectionsOrErr
);
660 template <class ELFT
>
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.
668 "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");
669 auto SectionOrErr
= object::getSection
<ELFT
>(Sections
, Sec
.sh_link
);
671 return SectionOrErr
.takeError();
672 return getStringTable(*SectionOrErr
);
675 template <class ELFT
>
677 ELFFile
<ELFT
>::getSectionName(const Elf_Shdr
*Section
,
678 WarningHandler WarnHandler
) const {
679 auto SectionsOrErr
= sections();
681 return SectionsOrErr
.takeError();
682 auto Table
= getSectionStringTable(*SectionsOrErr
, WarnHandler
);
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
;
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
) {
708 for (char C
: SymbolName
) {
718 } // end namespace object
719 } // end namespace llvm
721 #endif // LLVM_OBJECT_ELF_H