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