1 | //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file declares the ELFFile template class. |
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/MapVector.h" |
18 | #include "llvm/ADT/SmallString.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/BinaryFormat/ELF.h" |
22 | #include "llvm/Object/ELFTypes.h" |
23 | #include "llvm/Object/Error.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 | |
34 | struct VerdAux { |
35 | unsigned Offset; |
36 | std::string Name; |
37 | }; |
38 | |
39 | struct VerDef { |
40 | unsigned Offset; |
41 | unsigned Version; |
42 | unsigned Flags; |
43 | unsigned Ndx; |
44 | unsigned Cnt; |
45 | unsigned Hash; |
46 | std::string Name; |
47 | std::vector<VerdAux> AuxV; |
48 | }; |
49 | |
50 | struct VernAux { |
51 | unsigned Hash; |
52 | unsigned Flags; |
53 | unsigned Other; |
54 | unsigned Offset; |
55 | std::string Name; |
56 | }; |
57 | |
58 | struct VerNeed { |
59 | unsigned Version; |
60 | unsigned Cnt; |
61 | unsigned Offset; |
62 | std::string File; |
63 | std::vector<VernAux> AuxV; |
64 | }; |
65 | |
66 | struct VersionEntry { |
67 | std::string Name; |
68 | bool IsVerDef; |
69 | }; |
70 | |
71 | StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); |
72 | uint32_t getELFRelativeRelocationType(uint32_t Machine); |
73 | StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); |
74 | |
75 | // Subclasses of ELFFile may need this for template instantiation |
76 | inline std::pair<unsigned char, unsigned char> |
77 | getElfArchType(StringRef Object) { |
78 | if (Object.size() < ELF::EI_NIDENT) |
79 | return std::make_pair(x: (uint8_t)ELF::ELFCLASSNONE, |
80 | y: (uint8_t)ELF::ELFDATANONE); |
81 | return std::make_pair(x: (uint8_t)Object[ELF::EI_CLASS], |
82 | y: (uint8_t)Object[ELF::EI_DATA]); |
83 | } |
84 | |
85 | enum PPCInstrMasks : uint64_t { |
86 | PADDI_R12_NO_DISP = 0x0610000039800000, |
87 | ADDIS_R12_TO_R2_NO_DISP = 0x3D820000, |
88 | ADDI_R12_TO_R2_NO_DISP = 0x39820000, |
89 | ADDI_R12_TO_R12_NO_DISP = 0x398C0000, |
90 | PLD_R12_NO_DISP = 0x04100000E5800000, |
91 | MTCTR_R12 = 0x7D8903A6, |
92 | BCTR = 0x4E800420, |
93 | }; |
94 | |
95 | template <class ELFT> class ELFFile; |
96 | |
97 | template <class T> struct DataRegion { |
98 | // This constructor is used when we know the start and the size of a data |
99 | // region. We assume that Arr does not go past the end of the file. |
100 | DataRegion(ArrayRef<T> Arr) : First(Arr.data()), Size(Arr.size()) {} |
101 | |
102 | // Sometimes we only know the start of a data region. We still don't want to |
103 | // read past the end of the file, so we provide the end of a buffer. |
104 | DataRegion(const T *Data, const uint8_t *BufferEnd) |
105 | : First(Data), BufEnd(BufferEnd) {} |
106 | |
107 | Expected<T> operator[](uint64_t N) { |
108 | assert(Size || BufEnd); |
109 | if (Size) { |
110 | if (N >= *Size) |
111 | return createError( |
112 | Err: "the index is greater than or equal to the number of entries (" + |
113 | Twine(*Size) + ")" ); |
114 | } else { |
115 | const uint8_t *EntryStart = (const uint8_t *)First + N * sizeof(T); |
116 | if (EntryStart + sizeof(T) > BufEnd) |
117 | return createError(Err: "can't read past the end of the file" ); |
118 | } |
119 | return *(First + N); |
120 | } |
121 | |
122 | const T *First; |
123 | std::optional<uint64_t> Size; |
124 | const uint8_t *BufEnd = nullptr; |
125 | }; |
126 | |
127 | template <class ELFT> |
128 | std::string getSecIndexForError(const ELFFile<ELFT> &Obj, |
129 | const typename ELFT::Shdr &Sec) { |
130 | auto TableOrErr = Obj.sections(); |
131 | if (TableOrErr) |
132 | return "[index " + std::to_string(&Sec - &TableOrErr->front()) + "]" ; |
133 | // To make this helper be more convenient for error reporting purposes we |
134 | // drop the error. But really it should never be triggered. Before this point, |
135 | // our code should have called 'sections()' and reported a proper error on |
136 | // failure. |
137 | llvm::consumeError(Err: TableOrErr.takeError()); |
138 | return "[unknown index]" ; |
139 | } |
140 | |
141 | template <class ELFT> |
142 | static std::string describe(const ELFFile<ELFT> &Obj, |
143 | const typename ELFT::Shdr &Sec) { |
144 | unsigned SecNdx = &Sec - &cantFail(Obj.sections()).front(); |
145 | return (object::getELFSectionTypeName(Machine: Obj.getHeader().e_machine, |
146 | Type: Sec.sh_type) + |
147 | " section with index " + Twine(SecNdx)) |
148 | .str(); |
149 | } |
150 | |
151 | template <class ELFT> |
152 | std::string getPhdrIndexForError(const ELFFile<ELFT> &Obj, |
153 | const typename ELFT::Phdr &Phdr) { |
154 | auto = Obj.program_headers(); |
155 | if (Headers) |
156 | return ("[index " + Twine(&Phdr - &Headers->front()) + "]" ).str(); |
157 | // See comment in the getSecIndexForError() above. |
158 | llvm::consumeError(Err: Headers.takeError()); |
159 | return "[unknown index]" ; |
160 | } |
161 | |
162 | static inline Error defaultWarningHandler(const Twine &Msg) { |
163 | return createError(Err: Msg); |
164 | } |
165 | |
166 | template <class ELFT> |
167 | bool checkSectionOffsets(const typename ELFT::Phdr &Phdr, |
168 | const typename ELFT::Shdr &Sec) { |
169 | // SHT_NOBITS sections don't need to have an offset inside the segment. |
170 | if (Sec.sh_type == ELF::SHT_NOBITS) |
171 | return true; |
172 | |
173 | if (Sec.sh_offset < Phdr.p_offset) |
174 | return false; |
175 | |
176 | // Only non-empty sections can be at the end of a segment. |
177 | if (Sec.sh_size == 0) |
178 | return (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz); |
179 | return Sec.sh_offset + Sec.sh_size <= Phdr.p_offset + Phdr.p_filesz; |
180 | } |
181 | |
182 | // Check that an allocatable section belongs to a virtual address |
183 | // space of a segment. |
184 | template <class ELFT> |
185 | bool checkSectionVMA(const typename ELFT::Phdr &Phdr, |
186 | const typename ELFT::Shdr &Sec) { |
187 | if (!(Sec.sh_flags & ELF::SHF_ALLOC)) |
188 | return true; |
189 | |
190 | if (Sec.sh_addr < Phdr.p_vaddr) |
191 | return false; |
192 | |
193 | bool IsTbss = |
194 | (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); |
195 | // .tbss is special, it only has memory in PT_TLS and has NOBITS properties. |
196 | bool IsTbssInNonTLS = IsTbss && Phdr.p_type != ELF::PT_TLS; |
197 | // Only non-empty sections can be at the end of a segment. |
198 | if (Sec.sh_size == 0 || IsTbssInNonTLS) |
199 | return Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz; |
200 | return Sec.sh_addr + Sec.sh_size <= Phdr.p_vaddr + Phdr.p_memsz; |
201 | } |
202 | |
203 | template <class ELFT> |
204 | bool isSectionInSegment(const typename ELFT::Phdr &Phdr, |
205 | const typename ELFT::Shdr &Sec) { |
206 | return checkSectionOffsets<ELFT>(Phdr, Sec) && |
207 | checkSectionVMA<ELFT>(Phdr, Sec); |
208 | } |
209 | |
210 | template <class ELFT> |
211 | class ELFFile { |
212 | public: |
213 | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
214 | |
215 | // This is a callback that can be passed to a number of functions. |
216 | // It can be used to ignore non-critical errors (warnings), which is |
217 | // useful for dumpers, like llvm-readobj. |
218 | // It accepts a warning message string and returns a success |
219 | // when the warning should be ignored or an error otherwise. |
220 | using WarningHandler = llvm::function_ref<Error(const Twine &Msg)>; |
221 | |
222 | const uint8_t *base() const { return Buf.bytes_begin(); } |
223 | const uint8_t *end() const { return base() + getBufSize(); } |
224 | |
225 | size_t getBufSize() const { return Buf.size(); } |
226 | |
227 | private: |
228 | StringRef Buf; |
229 | std::vector<Elf_Shdr> FakeSections; |
230 | SmallString<0> FakeSectionStrings; |
231 | |
232 | ELFFile(StringRef Object); |
233 | |
234 | public: |
235 | const Elf_Ehdr &() const { |
236 | return *reinterpret_cast<const Elf_Ehdr *>(base()); |
237 | } |
238 | |
239 | template <typename T> |
240 | Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; |
241 | template <typename T> |
242 | Expected<const T *> getEntry(const Elf_Shdr &Section, uint32_t Entry) const; |
243 | |
244 | Expected<std::vector<VerDef>> |
245 | getVersionDefinitions(const Elf_Shdr &Sec) const; |
246 | Expected<std::vector<VerNeed>> getVersionDependencies( |
247 | const Elf_Shdr &Sec, |
248 | WarningHandler WarnHandler = &defaultWarningHandler) const; |
249 | Expected<StringRef> getSymbolVersionByIndex( |
250 | uint32_t SymbolVersionIndex, bool &IsDefault, |
251 | SmallVector<std::optional<VersionEntry>, 0> &VersionMap, |
252 | std::optional<bool> IsSymHidden) const; |
253 | |
254 | Expected<StringRef> |
255 | getStringTable(const Elf_Shdr &Section, |
256 | WarningHandler WarnHandler = &defaultWarningHandler) const; |
257 | Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; |
258 | Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, |
259 | Elf_Shdr_Range Sections) const; |
260 | Expected<StringRef> getLinkAsStrtab(const typename ELFT::Shdr &Sec) const; |
261 | |
262 | Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; |
263 | Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, |
264 | Elf_Shdr_Range Sections) const; |
265 | |
266 | Expected<uint64_t> getDynSymtabSize() const; |
267 | |
268 | StringRef getRelocationTypeName(uint32_t Type) const; |
269 | void getRelocationTypeName(uint32_t Type, |
270 | SmallVectorImpl<char> &Result) const; |
271 | uint32_t getRelativeRelocationType() const; |
272 | |
273 | std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const; |
274 | std::string getDynamicTagAsString(uint64_t Type) const; |
275 | |
276 | /// Get the symbol for a given relocation. |
277 | Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel &Rel, |
278 | const Elf_Shdr *SymTab) const; |
279 | |
280 | Expected<SmallVector<std::optional<VersionEntry>, 0>> |
281 | loadVersionMap(const Elf_Shdr *VerNeedSec, const Elf_Shdr *VerDefSec) const; |
282 | |
283 | static Expected<ELFFile> create(StringRef Object); |
284 | |
285 | bool isLE() const { |
286 | return getHeader().getDataEncoding() == ELF::ELFDATA2LSB; |
287 | } |
288 | |
289 | bool isMipsELF64() const { |
290 | return getHeader().e_machine == ELF::EM_MIPS && |
291 | getHeader().getFileClass() == ELF::ELFCLASS64; |
292 | } |
293 | |
294 | bool isMips64EL() const { return isMipsELF64() && isLE(); } |
295 | |
296 | Expected<Elf_Shdr_Range> sections() const; |
297 | |
298 | Expected<Elf_Dyn_Range> dynamicEntries() const; |
299 | |
300 | Expected<const uint8_t *> |
301 | toMappedAddr(uint64_t VAddr, |
302 | WarningHandler WarnHandler = &defaultWarningHandler) const; |
303 | |
304 | Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { |
305 | if (!Sec) |
306 | return ArrayRef<Elf_Sym>(nullptr, nullptr); |
307 | return getSectionContentsAsArray<Elf_Sym>(*Sec); |
308 | } |
309 | |
310 | Expected<Elf_Rela_Range> relas(const Elf_Shdr &Sec) const { |
311 | return getSectionContentsAsArray<Elf_Rela>(Sec); |
312 | } |
313 | |
314 | Expected<Elf_Rel_Range> rels(const Elf_Shdr &Sec) const { |
315 | return getSectionContentsAsArray<Elf_Rel>(Sec); |
316 | } |
317 | |
318 | Expected<Elf_Relr_Range> relrs(const Elf_Shdr &Sec) const { |
319 | return getSectionContentsAsArray<Elf_Relr>(Sec); |
320 | } |
321 | |
322 | std::vector<Elf_Rel> decode_relrs(Elf_Relr_Range relrs) const; |
323 | |
324 | Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr &Sec) const; |
325 | |
326 | /// Iterate over program header table. |
327 | Expected<Elf_Phdr_Range> () const { |
328 | if (getHeader().e_phnum && getHeader().e_phentsize != sizeof(Elf_Phdr)) |
329 | return createError(Err: "invalid e_phentsize: " + |
330 | Twine(getHeader().e_phentsize)); |
331 | |
332 | uint64_t = |
333 | (uint64_t)getHeader().e_phnum * getHeader().e_phentsize; |
334 | uint64_t PhOff = getHeader().e_phoff; |
335 | if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize()) |
336 | return createError("program headers are longer than binary of size " + |
337 | Twine(getBufSize()) + ": e_phoff = 0x" + |
338 | Twine::utohexstr(Val: getHeader().e_phoff) + |
339 | ", e_phnum = " + Twine(getHeader().e_phnum) + |
340 | ", e_phentsize = " + Twine(getHeader().e_phentsize)); |
341 | |
342 | auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff); |
343 | return ArrayRef(Begin, Begin + getHeader().e_phnum); |
344 | } |
345 | |
346 | /// Get an iterator over notes in a program header. |
347 | /// |
348 | /// The program header must be of type \c PT_NOTE. |
349 | /// |
350 | /// \param Phdr the program header to iterate over. |
351 | /// \param Err [out] an error to support fallible iteration, which should |
352 | /// be checked after iteration ends. |
353 | Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { |
354 | assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE" ); |
355 | ErrorAsOutParameter ErrAsOutParam(&Err); |
356 | if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { |
357 | Err = |
358 | createError("invalid offset (0x" + Twine::utohexstr(Val: Phdr.p_offset) + |
359 | ") or size (0x" + Twine::utohexstr(Val: Phdr.p_filesz) + ")" ); |
360 | return Elf_Note_Iterator(Err); |
361 | } |
362 | // Allow 4, 8, and (for Linux core dumps) 0. |
363 | // TODO: Disallow 1 after all tests are fixed. |
364 | if (Phdr.p_align != 0 && Phdr.p_align != 1 && Phdr.p_align != 4 && |
365 | Phdr.p_align != 8) { |
366 | Err = |
367 | createError(Err: "alignment (" + Twine(Phdr.p_align) + ") is not 4 or 8" ); |
368 | return Elf_Note_Iterator(Err); |
369 | } |
370 | return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, |
371 | std::max<size_t>(Phdr.p_align, 4), Err); |
372 | } |
373 | |
374 | /// Get an iterator over notes in a section. |
375 | /// |
376 | /// The section must be of type \c SHT_NOTE. |
377 | /// |
378 | /// \param Shdr the section to iterate over. |
379 | /// \param Err [out] an error to support fallible iteration, which should |
380 | /// be checked after iteration ends. |
381 | Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { |
382 | assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE" ); |
383 | ErrorAsOutParameter ErrAsOutParam(&Err); |
384 | if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { |
385 | Err = |
386 | createError("invalid offset (0x" + Twine::utohexstr(Val: Shdr.sh_offset) + |
387 | ") or size (0x" + Twine::utohexstr(Val: Shdr.sh_size) + ")" ); |
388 | return Elf_Note_Iterator(Err); |
389 | } |
390 | // TODO: Allow just 4 and 8 after all tests are fixed. |
391 | if (Shdr.sh_addralign != 0 && Shdr.sh_addralign != 1 && |
392 | Shdr.sh_addralign != 4 && Shdr.sh_addralign != 8) { |
393 | Err = createError(Err: "alignment (" + Twine(Shdr.sh_addralign) + |
394 | ") is not 4 or 8" ); |
395 | return Elf_Note_Iterator(Err); |
396 | } |
397 | return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, |
398 | std::max<size_t>(Shdr.sh_addralign, 4), Err); |
399 | } |
400 | |
401 | /// Get the end iterator for notes. |
402 | Elf_Note_Iterator notes_end() const { |
403 | return Elf_Note_Iterator(); |
404 | } |
405 | |
406 | /// Get an iterator range over notes of a program header. |
407 | /// |
408 | /// The program header must be of type \c PT_NOTE. |
409 | /// |
410 | /// \param Phdr the program header to iterate over. |
411 | /// \param Err [out] an error to support fallible iteration, which should |
412 | /// be checked after iteration ends. |
413 | iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr, |
414 | Error &Err) const { |
415 | return make_range(notes_begin(Phdr, Err), notes_end()); |
416 | } |
417 | |
418 | /// Get an iterator range over notes of a section. |
419 | /// |
420 | /// The section must be of type \c SHT_NOTE. |
421 | /// |
422 | /// \param Shdr the section to iterate over. |
423 | /// \param Err [out] an error to support fallible iteration, which should |
424 | /// be checked after iteration ends. |
425 | iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr, |
426 | Error &Err) const { |
427 | return make_range(notes_begin(Shdr, Err), notes_end()); |
428 | } |
429 | |
430 | Expected<StringRef> getSectionStringTable( |
431 | Elf_Shdr_Range Sections, |
432 | WarningHandler WarnHandler = &defaultWarningHandler) const; |
433 | Expected<uint32_t> getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms, |
434 | DataRegion<Elf_Word> ShndxTable) const; |
435 | Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym, |
436 | const Elf_Shdr *SymTab, |
437 | DataRegion<Elf_Word> ShndxTable) const; |
438 | Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym, |
439 | Elf_Sym_Range Symtab, |
440 | DataRegion<Elf_Word> ShndxTable) const; |
441 | Expected<const Elf_Shdr *> getSection(uint32_t Index) const; |
442 | |
443 | Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, |
444 | uint32_t Index) const; |
445 | |
446 | Expected<StringRef> |
447 | getSectionName(const Elf_Shdr &Section, |
448 | WarningHandler WarnHandler = &defaultWarningHandler) const; |
449 | Expected<StringRef> getSectionName(const Elf_Shdr &Section, |
450 | StringRef DotShstrtab) const; |
451 | template <typename T> |
452 | Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr &Sec) const; |
453 | Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr &Sec) const; |
454 | Expected<ArrayRef<uint8_t>> getSegmentContents(const Elf_Phdr &Phdr) const; |
455 | |
456 | /// Returns a vector of BBAddrMap structs corresponding to each function |
457 | /// within the text section that the SHT_LLVM_BB_ADDR_MAP section \p Sec |
458 | /// is associated with. If the current ELFFile is relocatable, a corresponding |
459 | /// \p RelaSec must be passed in as an argument. |
460 | /// Optional out variable to collect all PGO Analyses. New elements are only |
461 | /// added if no error occurs. If not provided, the PGO Analyses are decoded |
462 | /// then ignored. |
463 | Expected<std::vector<BBAddrMap>> |
464 | decodeBBAddrMap(const Elf_Shdr &Sec, const Elf_Shdr *RelaSec = nullptr, |
465 | std::vector<PGOAnalysisMap> *PGOAnalyses = nullptr) const; |
466 | |
467 | /// Returns a map from every section matching \p IsMatch to its relocation |
468 | /// section, or \p nullptr if it has no relocation section. This function |
469 | /// returns an error if any of the \p IsMatch calls fail or if it fails to |
470 | /// retrieve the content section of any relocation section. |
471 | Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> |
472 | getSectionAndRelocations( |
473 | std::function<Expected<bool>(const Elf_Shdr &)> IsMatch) const; |
474 | |
475 | void createFakeSections(); |
476 | }; |
477 | |
478 | using ELF32LEFile = ELFFile<ELF32LE>; |
479 | using ELF64LEFile = ELFFile<ELF64LE>; |
480 | using ELF32BEFile = ELFFile<ELF32BE>; |
481 | using ELF64BEFile = ELFFile<ELF64BE>; |
482 | |
483 | template <class ELFT> |
484 | inline Expected<const typename ELFT::Shdr *> |
485 | getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { |
486 | if (Index >= Sections.size()) |
487 | return createError(Err: "invalid section index: " + Twine(Index)); |
488 | return &Sections[Index]; |
489 | } |
490 | |
491 | template <class ELFT> |
492 | inline Expected<uint32_t> |
493 | getExtendedSymbolTableIndex(const typename ELFT::Sym &Sym, unsigned SymIndex, |
494 | DataRegion<typename ELFT::Word> ShndxTable) { |
495 | assert(Sym.st_shndx == ELF::SHN_XINDEX); |
496 | if (!ShndxTable.First) |
497 | return createError( |
498 | Err: "found an extended symbol index (" + Twine(SymIndex) + |
499 | "), but unable to locate the extended symbol index table" ); |
500 | |
501 | Expected<typename ELFT::Word> TableOrErr = ShndxTable[SymIndex]; |
502 | if (!TableOrErr) |
503 | return createError("unable to read an extended symbol table at index " + |
504 | Twine(SymIndex) + ": " + |
505 | toString(TableOrErr.takeError())); |
506 | return *TableOrErr; |
507 | } |
508 | |
509 | template <class ELFT> |
510 | Expected<uint32_t> |
511 | ELFFile<ELFT>::getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms, |
512 | DataRegion<Elf_Word> ShndxTable) const { |
513 | uint32_t Index = Sym.st_shndx; |
514 | if (Index == ELF::SHN_XINDEX) { |
515 | Expected<uint32_t> ErrorOrIndex = |
516 | getExtendedSymbolTableIndex<ELFT>(Sym, &Sym - Syms.begin(), ShndxTable); |
517 | if (!ErrorOrIndex) |
518 | return ErrorOrIndex.takeError(); |
519 | return *ErrorOrIndex; |
520 | } |
521 | if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) |
522 | return 0; |
523 | return Index; |
524 | } |
525 | |
526 | template <class ELFT> |
527 | Expected<const typename ELFT::Shdr *> |
528 | ELFFile<ELFT>::getSection(const Elf_Sym &Sym, const Elf_Shdr *SymTab, |
529 | DataRegion<Elf_Word> ShndxTable) const { |
530 | auto SymsOrErr = symbols(Sec: SymTab); |
531 | if (!SymsOrErr) |
532 | return SymsOrErr.takeError(); |
533 | return getSection(Sym, *SymsOrErr, ShndxTable); |
534 | } |
535 | |
536 | template <class ELFT> |
537 | Expected<const typename ELFT::Shdr *> |
538 | ELFFile<ELFT>::getSection(const Elf_Sym &Sym, Elf_Sym_Range Symbols, |
539 | DataRegion<Elf_Word> ShndxTable) const { |
540 | auto IndexOrErr = getSectionIndex(Sym, Syms: Symbols, ShndxTable); |
541 | if (!IndexOrErr) |
542 | return IndexOrErr.takeError(); |
543 | uint32_t Index = *IndexOrErr; |
544 | if (Index == 0) |
545 | return nullptr; |
546 | return getSection(Index); |
547 | } |
548 | |
549 | template <class ELFT> |
550 | Expected<const typename ELFT::Sym *> |
551 | ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { |
552 | auto SymsOrErr = symbols(Sec); |
553 | if (!SymsOrErr) |
554 | return SymsOrErr.takeError(); |
555 | |
556 | Elf_Sym_Range Symbols = *SymsOrErr; |
557 | if (Index >= Symbols.size()) |
558 | return createError("unable to get symbol from section " + |
559 | getSecIndexForError(*this, *Sec) + |
560 | ": invalid symbol index (" + Twine(Index) + ")" ); |
561 | return &Symbols[Index]; |
562 | } |
563 | |
564 | template <class ELFT> |
565 | template <typename T> |
566 | Expected<ArrayRef<T>> |
567 | ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr &Sec) const { |
568 | if (Sec.sh_entsize != sizeof(T) && sizeof(T) != 1) |
569 | return createError("section " + getSecIndexForError(*this, Sec) + |
570 | " has invalid sh_entsize: expected " + Twine(sizeof(T)) + |
571 | ", but got " + Twine(Sec.sh_entsize)); |
572 | |
573 | uintX_t Offset = Sec.sh_offset; |
574 | uintX_t Size = Sec.sh_size; |
575 | |
576 | if (Size % sizeof(T)) |
577 | return createError("section " + getSecIndexForError(*this, Sec) + |
578 | " has an invalid sh_size (" + Twine(Size) + |
579 | ") which is not a multiple of its sh_entsize (" + |
580 | Twine(Sec.sh_entsize) + ")" ); |
581 | if (std::numeric_limits<uintX_t>::max() - Offset < Size) |
582 | return createError("section " + getSecIndexForError(*this, Sec) + |
583 | " has a sh_offset (0x" + Twine::utohexstr(Val: Offset) + |
584 | ") + sh_size (0x" + Twine::utohexstr(Val: Size) + |
585 | ") that cannot be represented" ); |
586 | if (Offset + Size > Buf.size()) |
587 | return createError("section " + getSecIndexForError(*this, Sec) + |
588 | " has a sh_offset (0x" + Twine::utohexstr(Val: Offset) + |
589 | ") + sh_size (0x" + Twine::utohexstr(Val: Size) + |
590 | ") that is greater than the file size (0x" + |
591 | Twine::utohexstr(Val: Buf.size()) + ")" ); |
592 | |
593 | if (Offset % alignof(T)) |
594 | // TODO: this error is untested. |
595 | return createError(Err: "unaligned data" ); |
596 | |
597 | const T *Start = reinterpret_cast<const T *>(base() + Offset); |
598 | return ArrayRef(Start, Size / sizeof(T)); |
599 | } |
600 | |
601 | template <class ELFT> |
602 | Expected<ArrayRef<uint8_t>> |
603 | ELFFile<ELFT>::getSegmentContents(const Elf_Phdr &Phdr) const { |
604 | uintX_t Offset = Phdr.p_offset; |
605 | uintX_t Size = Phdr.p_filesz; |
606 | |
607 | if (std::numeric_limits<uintX_t>::max() - Offset < Size) |
608 | return createError("program header " + getPhdrIndexForError(*this, Phdr) + |
609 | " has a p_offset (0x" + Twine::utohexstr(Val: Offset) + |
610 | ") + p_filesz (0x" + Twine::utohexstr(Val: Size) + |
611 | ") that cannot be represented" ); |
612 | if (Offset + Size > Buf.size()) |
613 | return createError("program header " + getPhdrIndexForError(*this, Phdr) + |
614 | " has a p_offset (0x" + Twine::utohexstr(Val: Offset) + |
615 | ") + p_filesz (0x" + Twine::utohexstr(Val: Size) + |
616 | ") that is greater than the file size (0x" + |
617 | Twine::utohexstr(Val: Buf.size()) + ")" ); |
618 | return ArrayRef(base() + Offset, Size); |
619 | } |
620 | |
621 | template <class ELFT> |
622 | Expected<ArrayRef<uint8_t>> |
623 | ELFFile<ELFT>::getSectionContents(const Elf_Shdr &Sec) const { |
624 | return getSectionContentsAsArray<uint8_t>(Sec); |
625 | } |
626 | |
627 | template <class ELFT> |
628 | StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { |
629 | return getELFRelocationTypeName(getHeader().e_machine, Type); |
630 | } |
631 | |
632 | template <class ELFT> |
633 | void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, |
634 | SmallVectorImpl<char> &Result) const { |
635 | if (!isMipsELF64()) { |
636 | StringRef Name = getRelocationTypeName(Type); |
637 | Result.append(in_start: Name.begin(), in_end: Name.end()); |
638 | } else { |
639 | // The Mips N64 ABI allows up to three operations to be specified per |
640 | // relocation record. Unfortunately there's no easy way to test for the |
641 | // presence of N64 ELFs as they have no special flag that identifies them |
642 | // as being N64. We can safely assume at the moment that all Mips |
643 | // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough |
644 | // information to disambiguate between old vs new ABIs. |
645 | uint8_t Type1 = (Type >> 0) & 0xFF; |
646 | uint8_t Type2 = (Type >> 8) & 0xFF; |
647 | uint8_t Type3 = (Type >> 16) & 0xFF; |
648 | |
649 | // Concat all three relocation type names. |
650 | StringRef Name = getRelocationTypeName(Type1); |
651 | Result.append(in_start: Name.begin(), in_end: Name.end()); |
652 | |
653 | Name = getRelocationTypeName(Type2); |
654 | Result.append(NumInputs: 1, Elt: '/'); |
655 | Result.append(in_start: Name.begin(), in_end: Name.end()); |
656 | |
657 | Name = getRelocationTypeName(Type3); |
658 | Result.append(NumInputs: 1, Elt: '/'); |
659 | Result.append(in_start: Name.begin(), in_end: Name.end()); |
660 | } |
661 | } |
662 | |
663 | template <class ELFT> |
664 | uint32_t ELFFile<ELFT>::getRelativeRelocationType() const { |
665 | return getELFRelativeRelocationType(getHeader().e_machine); |
666 | } |
667 | |
668 | template <class ELFT> |
669 | Expected<SmallVector<std::optional<VersionEntry>, 0>> |
670 | ELFFile<ELFT>::loadVersionMap(const Elf_Shdr *VerNeedSec, |
671 | const Elf_Shdr *VerDefSec) const { |
672 | SmallVector<std::optional<VersionEntry>, 0> VersionMap; |
673 | |
674 | // The first two version indexes are reserved. |
675 | // Index 0 is VER_NDX_LOCAL, index 1 is VER_NDX_GLOBAL. |
676 | VersionMap.push_back(Elt: VersionEntry()); |
677 | VersionMap.push_back(Elt: VersionEntry()); |
678 | |
679 | auto InsertEntry = [&](unsigned N, StringRef Version, bool IsVerdef) { |
680 | if (N >= VersionMap.size()) |
681 | VersionMap.resize(N: N + 1); |
682 | VersionMap[N] = {.Name: std::string(Version), .IsVerDef: IsVerdef}; |
683 | }; |
684 | |
685 | if (VerDefSec) { |
686 | Expected<std::vector<VerDef>> Defs = getVersionDefinitions(Sec: *VerDefSec); |
687 | if (!Defs) |
688 | return Defs.takeError(); |
689 | for (const VerDef &Def : *Defs) |
690 | InsertEntry(Def.Ndx & ELF::VERSYM_VERSION, Def.Name, true); |
691 | } |
692 | |
693 | if (VerNeedSec) { |
694 | Expected<std::vector<VerNeed>> Deps = getVersionDependencies(Sec: *VerNeedSec); |
695 | if (!Deps) |
696 | return Deps.takeError(); |
697 | for (const VerNeed &Dep : *Deps) |
698 | for (const VernAux &Aux : Dep.AuxV) |
699 | InsertEntry(Aux.Other & ELF::VERSYM_VERSION, Aux.Name, false); |
700 | } |
701 | |
702 | return VersionMap; |
703 | } |
704 | |
705 | template <class ELFT> |
706 | Expected<const typename ELFT::Sym *> |
707 | ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel &Rel, |
708 | const Elf_Shdr *SymTab) const { |
709 | uint32_t Index = Rel.getSymbol(isMips64EL()); |
710 | if (Index == 0) |
711 | return nullptr; |
712 | return getEntry<Elf_Sym>(*SymTab, Index); |
713 | } |
714 | |
715 | template <class ELFT> |
716 | Expected<StringRef> |
717 | ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections, |
718 | WarningHandler WarnHandler) const { |
719 | uint32_t Index = getHeader().e_shstrndx; |
720 | if (Index == ELF::SHN_XINDEX) { |
721 | // If the section name string table section index is greater than |
722 | // or equal to SHN_LORESERVE, then the actual index of the section name |
723 | // string table section is contained in the sh_link field of the section |
724 | // header at index 0. |
725 | if (Sections.empty()) |
726 | return createError( |
727 | Err: "e_shstrndx == SHN_XINDEX, but the section header table is empty" ); |
728 | |
729 | Index = Sections[0].sh_link; |
730 | } |
731 | |
732 | // There is no section name string table. Return FakeSectionStrings which |
733 | // is non-empty if we have created fake sections. |
734 | if (!Index) |
735 | return FakeSectionStrings; |
736 | |
737 | if (Index >= Sections.size()) |
738 | return createError(Err: "section header string table index " + Twine(Index) + |
739 | " does not exist" ); |
740 | return getStringTable(Section: Sections[Index], WarnHandler); |
741 | } |
742 | |
743 | /// This function finds the number of dynamic symbols using a GNU hash table. |
744 | /// |
745 | /// @param Table The GNU hash table for .dynsym. |
746 | template <class ELFT> |
747 | static Expected<uint64_t> |
748 | getDynSymtabSizeFromGnuHash(const typename ELFT::GnuHash &Table, |
749 | const void *BufEnd) { |
750 | using Elf_Word = typename ELFT::Word; |
751 | if (Table.nbuckets == 0) |
752 | return Table.symndx + 1; |
753 | uint64_t LastSymIdx = 0; |
754 | // Find the index of the first symbol in the last chain. |
755 | for (Elf_Word Val : Table.buckets()) |
756 | LastSymIdx = std::max(a: LastSymIdx, b: (uint64_t)Val); |
757 | const Elf_Word *It = |
758 | reinterpret_cast<const Elf_Word *>(Table.values(LastSymIdx).end()); |
759 | // Locate the end of the chain to find the last symbol index. |
760 | while (It < BufEnd && (*It & 1) == 0) { |
761 | ++LastSymIdx; |
762 | ++It; |
763 | } |
764 | if (It >= BufEnd) { |
765 | return createStringError( |
766 | EC: object_error::parse_failed, |
767 | Msg: "no terminator found for GNU hash section before buffer end" ); |
768 | } |
769 | return LastSymIdx + 1; |
770 | } |
771 | |
772 | /// This function determines the number of dynamic symbols. It reads section |
773 | /// headers first. If section headers are not available, the number of |
774 | /// symbols will be inferred by parsing dynamic hash tables. |
775 | template <class ELFT> |
776 | Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const { |
777 | // Read .dynsym section header first if available. |
778 | Expected<Elf_Shdr_Range> SectionsOrError = sections(); |
779 | if (!SectionsOrError) |
780 | return SectionsOrError.takeError(); |
781 | for (const Elf_Shdr &Sec : *SectionsOrError) { |
782 | if (Sec.sh_type == ELF::SHT_DYNSYM) { |
783 | if (Sec.sh_size % Sec.sh_entsize != 0) { |
784 | return createStringError(EC: object_error::parse_failed, |
785 | S: "SHT_DYNSYM section has sh_size (" + |
786 | Twine(Sec.sh_size) + ") % sh_entsize (" + |
787 | Twine(Sec.sh_entsize) + ") that is not 0" ); |
788 | } |
789 | return Sec.sh_size / Sec.sh_entsize; |
790 | } |
791 | } |
792 | |
793 | if (!SectionsOrError->empty()) { |
794 | // Section headers are available but .dynsym header is not found. |
795 | // Return 0 as .dynsym does not exist. |
796 | return 0; |
797 | } |
798 | |
799 | // Section headers do not exist. Falling back to infer |
800 | // upper bound of .dynsym from .gnu.hash and .hash. |
801 | Expected<Elf_Dyn_Range> DynTable = dynamicEntries(); |
802 | if (!DynTable) |
803 | return DynTable.takeError(); |
804 | std::optional<uint64_t> ElfHash; |
805 | std::optional<uint64_t> ElfGnuHash; |
806 | for (const Elf_Dyn &Entry : *DynTable) { |
807 | switch (Entry.d_tag) { |
808 | case ELF::DT_HASH: |
809 | ElfHash = Entry.d_un.d_ptr; |
810 | break; |
811 | case ELF::DT_GNU_HASH: |
812 | ElfGnuHash = Entry.d_un.d_ptr; |
813 | break; |
814 | } |
815 | } |
816 | if (ElfGnuHash) { |
817 | Expected<const uint8_t *> TablePtr = toMappedAddr(VAddr: *ElfGnuHash); |
818 | if (!TablePtr) |
819 | return TablePtr.takeError(); |
820 | const Elf_GnuHash *Table = |
821 | reinterpret_cast<const Elf_GnuHash *>(TablePtr.get()); |
822 | return getDynSymtabSizeFromGnuHash<ELFT>(*Table, this->Buf.bytes_end()); |
823 | } |
824 | |
825 | // Search SYSV hash table to try to find the upper bound of dynsym. |
826 | if (ElfHash) { |
827 | Expected<const uint8_t *> TablePtr = toMappedAddr(VAddr: *ElfHash); |
828 | if (!TablePtr) |
829 | return TablePtr.takeError(); |
830 | const Elf_Hash *Table = reinterpret_cast<const Elf_Hash *>(TablePtr.get()); |
831 | return Table->nchain; |
832 | } |
833 | return 0; |
834 | } |
835 | |
836 | template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} |
837 | |
838 | template <class ELFT> |
839 | Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { |
840 | if (sizeof(Elf_Ehdr) > Object.size()) |
841 | return createError(Err: "invalid buffer: the size (" + Twine(Object.size()) + |
842 | ") is smaller than an ELF header (" + |
843 | Twine(sizeof(Elf_Ehdr)) + ")" ); |
844 | return ELFFile(Object); |
845 | } |
846 | |
847 | /// Used by llvm-objdump -d (which needs sections for disassembly) to |
848 | /// disassemble objects without a section header table (e.g. ET_CORE objects |
849 | /// analyzed by linux perf or ET_EXEC with llvm-strip --strip-sections). |
850 | template <class ELFT> void ELFFile<ELFT>::createFakeSections() { |
851 | if (!FakeSections.empty()) |
852 | return; |
853 | auto PhdrsOrErr = program_headers(); |
854 | if (!PhdrsOrErr) |
855 | return; |
856 | |
857 | FakeSectionStrings += '\0'; |
858 | for (auto [Idx, Phdr] : llvm::enumerate(*PhdrsOrErr)) { |
859 | if (Phdr.p_type != ELF::PT_LOAD || !(Phdr.p_flags & ELF::PF_X)) |
860 | continue; |
861 | Elf_Shdr FakeShdr = {}; |
862 | FakeShdr.sh_type = ELF::SHT_PROGBITS; |
863 | FakeShdr.sh_flags = ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; |
864 | FakeShdr.sh_addr = Phdr.p_vaddr; |
865 | FakeShdr.sh_size = Phdr.p_memsz; |
866 | FakeShdr.sh_offset = Phdr.p_offset; |
867 | // Create a section name based on the p_type and index. |
868 | FakeShdr.sh_name = FakeSectionStrings.size(); |
869 | FakeSectionStrings += ("PT_LOAD#" + Twine(Idx)).str(); |
870 | FakeSectionStrings += '\0'; |
871 | FakeSections.push_back(FakeShdr); |
872 | } |
873 | } |
874 | |
875 | template <class ELFT> |
876 | Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { |
877 | const uintX_t SectionTableOffset = getHeader().e_shoff; |
878 | if (SectionTableOffset == 0) { |
879 | if (!FakeSections.empty()) |
880 | return ArrayRef(FakeSections.data(), FakeSections.size()); |
881 | return ArrayRef<Elf_Shdr>(); |
882 | } |
883 | |
884 | if (getHeader().e_shentsize != sizeof(Elf_Shdr)) |
885 | return createError(Err: "invalid e_shentsize in ELF header: " + |
886 | Twine(getHeader().e_shentsize)); |
887 | |
888 | const uint64_t FileSize = Buf.size(); |
889 | if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize || |
890 | SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset) |
891 | return createError( |
892 | "section header table goes past the end of the file: e_shoff = 0x" + |
893 | Twine::utohexstr(Val: SectionTableOffset)); |
894 | |
895 | // Invalid address alignment of section headers |
896 | if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) |
897 | // TODO: this error is untested. |
898 | return createError(Err: "invalid alignment of section headers" ); |
899 | |
900 | const Elf_Shdr *First = |
901 | reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); |
902 | |
903 | uintX_t NumSections = getHeader().e_shnum; |
904 | if (NumSections == 0) |
905 | NumSections = First->sh_size; |
906 | |
907 | if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) |
908 | return createError(Err: "invalid number of sections specified in the NULL " |
909 | "section's sh_size field (" + |
910 | Twine(NumSections) + ")" ); |
911 | |
912 | const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); |
913 | if (SectionTableOffset + SectionTableSize < SectionTableOffset) |
914 | return createError( |
915 | "invalid section header table offset (e_shoff = 0x" + |
916 | Twine::utohexstr(Val: SectionTableOffset) + |
917 | ") or invalid number of sections specified in the first section " |
918 | "header's sh_size field (0x" + |
919 | Twine::utohexstr(Val: NumSections) + ")" ); |
920 | |
921 | // Section table goes past end of file! |
922 | if (SectionTableOffset + SectionTableSize > FileSize) |
923 | return createError(Err: "section table goes past the end of file" ); |
924 | return ArrayRef(First, NumSections); |
925 | } |
926 | |
927 | template <class ELFT> |
928 | template <typename T> |
929 | Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, |
930 | uint32_t Entry) const { |
931 | auto SecOrErr = getSection(Section); |
932 | if (!SecOrErr) |
933 | return SecOrErr.takeError(); |
934 | return getEntry<T>(**SecOrErr, Entry); |
935 | } |
936 | |
937 | template <class ELFT> |
938 | template <typename T> |
939 | Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr &Section, |
940 | uint32_t Entry) const { |
941 | Expected<ArrayRef<T>> EntriesOrErr = getSectionContentsAsArray<T>(Section); |
942 | if (!EntriesOrErr) |
943 | return EntriesOrErr.takeError(); |
944 | |
945 | ArrayRef<T> Arr = *EntriesOrErr; |
946 | if (Entry >= Arr.size()) |
947 | return createError( |
948 | "can't read an entry at 0x" + |
949 | Twine::utohexstr(Val: Entry * static_cast<uint64_t>(sizeof(T))) + |
950 | ": it goes past the end of the section (0x" + |
951 | Twine::utohexstr(Val: Section.sh_size) + ")" ); |
952 | return &Arr[Entry]; |
953 | } |
954 | |
955 | template <typename ELFT> |
956 | Expected<StringRef> ELFFile<ELFT>::getSymbolVersionByIndex( |
957 | uint32_t SymbolVersionIndex, bool &IsDefault, |
958 | SmallVector<std::optional<VersionEntry>, 0> &VersionMap, |
959 | std::optional<bool> IsSymHidden) const { |
960 | size_t VersionIndex = SymbolVersionIndex & llvm::ELF::VERSYM_VERSION; |
961 | |
962 | // Special markers for unversioned symbols. |
963 | if (VersionIndex == llvm::ELF::VER_NDX_LOCAL || |
964 | VersionIndex == llvm::ELF::VER_NDX_GLOBAL) { |
965 | IsDefault = false; |
966 | return "" ; |
967 | } |
968 | |
969 | // Lookup this symbol in the version table. |
970 | if (VersionIndex >= VersionMap.size() || !VersionMap[VersionIndex]) |
971 | return createError(Err: "SHT_GNU_versym section refers to a version index " + |
972 | Twine(VersionIndex) + " which is missing" ); |
973 | |
974 | const VersionEntry &Entry = *VersionMap[VersionIndex]; |
975 | // A default version (@@) is only available for defined symbols. |
976 | if (!Entry.IsVerDef || IsSymHidden.value_or(u: false)) |
977 | IsDefault = false; |
978 | else |
979 | IsDefault = !(SymbolVersionIndex & llvm::ELF::VERSYM_HIDDEN); |
980 | return Entry.Name.c_str(); |
981 | } |
982 | |
983 | template <class ELFT> |
984 | Expected<std::vector<VerDef>> |
985 | ELFFile<ELFT>::getVersionDefinitions(const Elf_Shdr &Sec) const { |
986 | Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Sec); |
987 | if (!StrTabOrErr) |
988 | return StrTabOrErr.takeError(); |
989 | |
990 | Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); |
991 | if (!ContentsOrErr) |
992 | return createError("cannot read content of " + describe(*this, Sec) + ": " + |
993 | toString(E: ContentsOrErr.takeError())); |
994 | |
995 | const uint8_t *Start = ContentsOrErr->data(); |
996 | const uint8_t *End = Start + ContentsOrErr->size(); |
997 | |
998 | auto = [&](const uint8_t *&VerdauxBuf, |
999 | unsigned VerDefNdx) -> Expected<VerdAux> { |
1000 | if (VerdauxBuf + sizeof(Elf_Verdaux) > End) |
1001 | return createError("invalid " + describe(*this, Sec) + |
1002 | ": version definition " + Twine(VerDefNdx) + |
1003 | " refers to an auxiliary entry that goes past the end " |
1004 | "of the section" ); |
1005 | |
1006 | auto *Verdaux = reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf); |
1007 | VerdauxBuf += Verdaux->vda_next; |
1008 | |
1009 | VerdAux Aux; |
1010 | Aux.Offset = VerdauxBuf - Start; |
1011 | if (Verdaux->vda_name <= StrTabOrErr->size()) |
1012 | Aux.Name = std::string(StrTabOrErr->drop_front(N: Verdaux->vda_name)); |
1013 | else |
1014 | Aux.Name = ("<invalid vda_name: " + Twine(Verdaux->vda_name) + ">" ).str(); |
1015 | return Aux; |
1016 | }; |
1017 | |
1018 | std::vector<VerDef> Ret; |
1019 | const uint8_t *VerdefBuf = Start; |
1020 | for (unsigned I = 1; I <= /*VerDefsNum=*/Sec.sh_info; ++I) { |
1021 | if (VerdefBuf + sizeof(Elf_Verdef) > End) |
1022 | return createError("invalid " + describe(*this, Sec) + |
1023 | ": version definition " + Twine(I) + |
1024 | " goes past the end of the section" ); |
1025 | |
1026 | if (reinterpret_cast<uintptr_t>(VerdefBuf) % sizeof(uint32_t) != 0) |
1027 | return createError( |
1028 | "invalid " + describe(*this, Sec) + |
1029 | ": found a misaligned version definition entry at offset 0x" + |
1030 | Twine::utohexstr(Val: VerdefBuf - Start)); |
1031 | |
1032 | unsigned Version = *reinterpret_cast<const Elf_Half *>(VerdefBuf); |
1033 | if (Version != 1) |
1034 | return createError("unable to dump " + describe(*this, Sec) + |
1035 | ": version " + Twine(Version) + |
1036 | " is not yet supported" ); |
1037 | |
1038 | const Elf_Verdef *D = reinterpret_cast<const Elf_Verdef *>(VerdefBuf); |
1039 | VerDef &VD = *Ret.emplace(position: Ret.end()); |
1040 | VD.Offset = VerdefBuf - Start; |
1041 | VD.Version = D->vd_version; |
1042 | VD.Flags = D->vd_flags; |
1043 | VD.Ndx = D->vd_ndx; |
1044 | VD.Cnt = D->vd_cnt; |
1045 | VD.Hash = D->vd_hash; |
1046 | |
1047 | const uint8_t *VerdauxBuf = VerdefBuf + D->vd_aux; |
1048 | for (unsigned J = 0; J < D->vd_cnt; ++J) { |
1049 | if (reinterpret_cast<uintptr_t>(VerdauxBuf) % sizeof(uint32_t) != 0) |
1050 | return createError("invalid " + describe(*this, Sec) + |
1051 | ": found a misaligned auxiliary entry at offset 0x" + |
1052 | Twine::utohexstr(Val: VerdauxBuf - Start)); |
1053 | |
1054 | Expected<VerdAux> AuxOrErr = ExtractNextAux(VerdauxBuf, I); |
1055 | if (!AuxOrErr) |
1056 | return AuxOrErr.takeError(); |
1057 | |
1058 | if (J == 0) |
1059 | VD.Name = AuxOrErr->Name; |
1060 | else |
1061 | VD.AuxV.push_back(x: *AuxOrErr); |
1062 | } |
1063 | |
1064 | VerdefBuf += D->vd_next; |
1065 | } |
1066 | |
1067 | return Ret; |
1068 | } |
1069 | |
1070 | template <class ELFT> |
1071 | Expected<std::vector<VerNeed>> |
1072 | ELFFile<ELFT>::getVersionDependencies(const Elf_Shdr &Sec, |
1073 | WarningHandler WarnHandler) const { |
1074 | StringRef StrTab; |
1075 | Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Sec); |
1076 | if (!StrTabOrErr) { |
1077 | if (Error E = WarnHandler(toString(E: StrTabOrErr.takeError()))) |
1078 | return std::move(E); |
1079 | } else { |
1080 | StrTab = *StrTabOrErr; |
1081 | } |
1082 | |
1083 | Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); |
1084 | if (!ContentsOrErr) |
1085 | return createError("cannot read content of " + describe(*this, Sec) + ": " + |
1086 | toString(E: ContentsOrErr.takeError())); |
1087 | |
1088 | const uint8_t *Start = ContentsOrErr->data(); |
1089 | const uint8_t *End = Start + ContentsOrErr->size(); |
1090 | const uint8_t *VerneedBuf = Start; |
1091 | |
1092 | std::vector<VerNeed> Ret; |
1093 | for (unsigned I = 1; I <= /*VerneedNum=*/Sec.sh_info; ++I) { |
1094 | if (VerneedBuf + sizeof(Elf_Verdef) > End) |
1095 | return createError("invalid " + describe(*this, Sec) + |
1096 | ": version dependency " + Twine(I) + |
1097 | " goes past the end of the section" ); |
1098 | |
1099 | if (reinterpret_cast<uintptr_t>(VerneedBuf) % sizeof(uint32_t) != 0) |
1100 | return createError( |
1101 | "invalid " + describe(*this, Sec) + |
1102 | ": found a misaligned version dependency entry at offset 0x" + |
1103 | Twine::utohexstr(Val: VerneedBuf - Start)); |
1104 | |
1105 | unsigned Version = *reinterpret_cast<const Elf_Half *>(VerneedBuf); |
1106 | if (Version != 1) |
1107 | return createError("unable to dump " + describe(*this, Sec) + |
1108 | ": version " + Twine(Version) + |
1109 | " is not yet supported" ); |
1110 | |
1111 | const Elf_Verneed *Verneed = |
1112 | reinterpret_cast<const Elf_Verneed *>(VerneedBuf); |
1113 | |
1114 | VerNeed &VN = *Ret.emplace(position: Ret.end()); |
1115 | VN.Version = Verneed->vn_version; |
1116 | VN.Cnt = Verneed->vn_cnt; |
1117 | VN.Offset = VerneedBuf - Start; |
1118 | |
1119 | if (Verneed->vn_file < StrTab.size()) |
1120 | VN.File = std::string(StrTab.data() + Verneed->vn_file); |
1121 | else |
1122 | VN.File = ("<corrupt vn_file: " + Twine(Verneed->vn_file) + ">" ).str(); |
1123 | |
1124 | const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux; |
1125 | for (unsigned J = 0; J < Verneed->vn_cnt; ++J) { |
1126 | if (reinterpret_cast<uintptr_t>(VernauxBuf) % sizeof(uint32_t) != 0) |
1127 | return createError("invalid " + describe(*this, Sec) + |
1128 | ": found a misaligned auxiliary entry at offset 0x" + |
1129 | Twine::utohexstr(Val: VernauxBuf - Start)); |
1130 | |
1131 | if (VernauxBuf + sizeof(Elf_Vernaux) > End) |
1132 | return createError( |
1133 | "invalid " + describe(*this, Sec) + ": version dependency " + |
1134 | Twine(I) + |
1135 | " refers to an auxiliary entry that goes past the end " |
1136 | "of the section" ); |
1137 | |
1138 | const Elf_Vernaux *Vernaux = |
1139 | reinterpret_cast<const Elf_Vernaux *>(VernauxBuf); |
1140 | |
1141 | VernAux &Aux = *VN.AuxV.emplace(position: VN.AuxV.end()); |
1142 | Aux.Hash = Vernaux->vna_hash; |
1143 | Aux.Flags = Vernaux->vna_flags; |
1144 | Aux.Other = Vernaux->vna_other; |
1145 | Aux.Offset = VernauxBuf - Start; |
1146 | if (StrTab.size() <= Vernaux->vna_name) |
1147 | Aux.Name = "<corrupt>" ; |
1148 | else |
1149 | Aux.Name = std::string(StrTab.drop_front(N: Vernaux->vna_name)); |
1150 | |
1151 | VernauxBuf += Vernaux->vna_next; |
1152 | } |
1153 | VerneedBuf += Verneed->vn_next; |
1154 | } |
1155 | return Ret; |
1156 | } |
1157 | |
1158 | template <class ELFT> |
1159 | Expected<const typename ELFT::Shdr *> |
1160 | ELFFile<ELFT>::getSection(uint32_t Index) const { |
1161 | auto TableOrErr = sections(); |
1162 | if (!TableOrErr) |
1163 | return TableOrErr.takeError(); |
1164 | return object::getSection<ELFT>(*TableOrErr, Index); |
1165 | } |
1166 | |
1167 | template <class ELFT> |
1168 | Expected<StringRef> |
1169 | ELFFile<ELFT>::getStringTable(const Elf_Shdr &Section, |
1170 | WarningHandler WarnHandler) const { |
1171 | if (Section.sh_type != ELF::SHT_STRTAB) |
1172 | if (Error E = WarnHandler("invalid sh_type for string table section " + |
1173 | getSecIndexForError(*this, Section) + |
1174 | ": expected SHT_STRTAB, but got " + |
1175 | object::getELFSectionTypeName( |
1176 | Machine: getHeader().e_machine, Type: Section.sh_type))) |
1177 | return std::move(E); |
1178 | |
1179 | auto V = getSectionContentsAsArray<char>(Section); |
1180 | if (!V) |
1181 | return V.takeError(); |
1182 | ArrayRef<char> Data = *V; |
1183 | if (Data.empty()) |
1184 | return createError("SHT_STRTAB string table section " + |
1185 | getSecIndexForError(*this, Section) + " is empty" ); |
1186 | if (Data.back() != '\0') |
1187 | return createError("SHT_STRTAB string table section " + |
1188 | getSecIndexForError(*this, Section) + |
1189 | " is non-null terminated" ); |
1190 | return StringRef(Data.begin(), Data.size()); |
1191 | } |
1192 | |
1193 | template <class ELFT> |
1194 | Expected<ArrayRef<typename ELFT::Word>> |
1195 | ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { |
1196 | auto SectionsOrErr = sections(); |
1197 | if (!SectionsOrErr) |
1198 | return SectionsOrErr.takeError(); |
1199 | return getSHNDXTable(Section, *SectionsOrErr); |
1200 | } |
1201 | |
1202 | template <class ELFT> |
1203 | Expected<ArrayRef<typename ELFT::Word>> |
1204 | ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, |
1205 | Elf_Shdr_Range Sections) const { |
1206 | assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); |
1207 | auto VOrErr = getSectionContentsAsArray<Elf_Word>(Section); |
1208 | if (!VOrErr) |
1209 | return VOrErr.takeError(); |
1210 | ArrayRef<Elf_Word> V = *VOrErr; |
1211 | auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); |
1212 | if (!SymTableOrErr) |
1213 | return SymTableOrErr.takeError(); |
1214 | const Elf_Shdr &SymTable = **SymTableOrErr; |
1215 | if (SymTable.sh_type != ELF::SHT_SYMTAB && |
1216 | SymTable.sh_type != ELF::SHT_DYNSYM) |
1217 | return createError( |
1218 | "SHT_SYMTAB_SHNDX section is linked with " + |
1219 | object::getELFSectionTypeName(Machine: getHeader().e_machine, Type: SymTable.sh_type) + |
1220 | " section (expected SHT_SYMTAB/SHT_DYNSYM)" ); |
1221 | |
1222 | uint64_t Syms = SymTable.sh_size / sizeof(Elf_Sym); |
1223 | if (V.size() != Syms) |
1224 | return createError(Err: "SHT_SYMTAB_SHNDX has " + Twine(V.size()) + |
1225 | " entries, but the symbol table associated has " + |
1226 | Twine(Syms)); |
1227 | |
1228 | return V; |
1229 | } |
1230 | |
1231 | template <class ELFT> |
1232 | Expected<StringRef> |
1233 | ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { |
1234 | auto SectionsOrErr = sections(); |
1235 | if (!SectionsOrErr) |
1236 | return SectionsOrErr.takeError(); |
1237 | return getStringTableForSymtab(Sec, *SectionsOrErr); |
1238 | } |
1239 | |
1240 | template <class ELFT> |
1241 | Expected<StringRef> |
1242 | ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, |
1243 | Elf_Shdr_Range Sections) const { |
1244 | |
1245 | if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) |
1246 | return createError( |
1247 | Err: "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM" ); |
1248 | Expected<const Elf_Shdr *> SectionOrErr = |
1249 | object::getSection<ELFT>(Sections, Sec.sh_link); |
1250 | if (!SectionOrErr) |
1251 | return SectionOrErr.takeError(); |
1252 | return getStringTable(Section: **SectionOrErr); |
1253 | } |
1254 | |
1255 | template <class ELFT> |
1256 | Expected<StringRef> |
1257 | ELFFile<ELFT>::getLinkAsStrtab(const typename ELFT::Shdr &Sec) const { |
1258 | Expected<const typename ELFT::Shdr *> StrTabSecOrErr = |
1259 | getSection(Sec.sh_link); |
1260 | if (!StrTabSecOrErr) |
1261 | return createError("invalid section linked to " + describe(*this, Sec) + |
1262 | ": " + toString(StrTabSecOrErr.takeError())); |
1263 | |
1264 | Expected<StringRef> StrTabOrErr = getStringTable(Section: **StrTabSecOrErr); |
1265 | if (!StrTabOrErr) |
1266 | return createError("invalid string table linked to " + |
1267 | describe(*this, Sec) + ": " + |
1268 | toString(E: StrTabOrErr.takeError())); |
1269 | return *StrTabOrErr; |
1270 | } |
1271 | |
1272 | template <class ELFT> |
1273 | Expected<StringRef> |
1274 | ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section, |
1275 | WarningHandler WarnHandler) const { |
1276 | auto SectionsOrErr = sections(); |
1277 | if (!SectionsOrErr) |
1278 | return SectionsOrErr.takeError(); |
1279 | auto Table = getSectionStringTable(Sections: *SectionsOrErr, WarnHandler); |
1280 | if (!Table) |
1281 | return Table.takeError(); |
1282 | return getSectionName(Section, *Table); |
1283 | } |
1284 | |
1285 | template <class ELFT> |
1286 | Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section, |
1287 | StringRef DotShstrtab) const { |
1288 | uint32_t Offset = Section.sh_name; |
1289 | if (Offset == 0) |
1290 | return StringRef(); |
1291 | if (Offset >= DotShstrtab.size()) |
1292 | return createError("a section " + getSecIndexForError(*this, Section) + |
1293 | " has an invalid sh_name (0x" + |
1294 | Twine::utohexstr(Val: Offset) + |
1295 | ") offset which goes past the end of the " |
1296 | "section name string table" ); |
1297 | return StringRef(DotShstrtab.data() + Offset); |
1298 | } |
1299 | |
1300 | /// This function returns the hash value for a symbol in the .dynsym section |
1301 | /// Name of the API remains consistent as specified in the libelf |
1302 | /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash |
1303 | inline uint32_t hashSysV(StringRef SymbolName) { |
1304 | uint32_t H = 0; |
1305 | for (uint8_t C : SymbolName) { |
1306 | H = (H << 4) + C; |
1307 | H ^= (H >> 24) & 0xf0; |
1308 | } |
1309 | return H & 0x0fffffff; |
1310 | } |
1311 | |
1312 | /// This function returns the hash value for a symbol in the .dynsym section |
1313 | /// for the GNU hash table. The implementation is defined in the GNU hash ABI. |
1314 | /// REF : https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=bfd/elf.c#l222 |
1315 | inline uint32_t hashGnu(StringRef Name) { |
1316 | uint32_t H = 5381; |
1317 | for (uint8_t C : Name) |
1318 | H = (H << 5) + H + C; |
1319 | return H; |
1320 | } |
1321 | |
1322 | } // end namespace object |
1323 | } // end namespace llvm |
1324 | |
1325 | #endif // LLVM_OBJECT_ELF_H |
1326 | |