/src/keystone/llvm/include/llvm/Object/ELF.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file declares the ELFFile template class. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_OBJECT_ELF_H |
15 | | #define LLVM_OBJECT_ELF_H |
16 | | |
17 | | #include "llvm/ADT/SmallVector.h" |
18 | | #include "llvm/Object/ELFTypes.h" |
19 | | #include "llvm/Support/MemoryBuffer.h" |
20 | | |
21 | | namespace llvm_ks { |
22 | | namespace object { |
23 | | |
24 | | StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); |
25 | | |
26 | | // Subclasses of ELFFile may need this for template instantiation |
27 | | inline std::pair<unsigned char, unsigned char> |
28 | 0 | getElfArchType(StringRef Object) { |
29 | 0 | if (Object.size() < ELF::EI_NIDENT) |
30 | 0 | return std::make_pair((uint8_t)ELF::ELFCLASSNONE, |
31 | 0 | (uint8_t)ELF::ELFDATANONE); |
32 | 0 | return std::make_pair((uint8_t)Object[ELF::EI_CLASS], |
33 | 0 | (uint8_t)Object[ELF::EI_DATA]); |
34 | 0 | } |
35 | | |
36 | | template <class ELFT> |
37 | | class ELFFile { |
38 | | public: |
39 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
40 | | typedef typename std::conditional<ELFT::Is64Bits, |
41 | | uint64_t, uint32_t>::type uintX_t; |
42 | | |
43 | | typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; |
44 | | typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; |
45 | | typedef Elf_Sym_Impl<ELFT> Elf_Sym; |
46 | | typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; |
47 | | typedef Elf_Phdr_Impl<ELFT> Elf_Phdr; |
48 | | typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; |
49 | | typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; |
50 | | typedef Elf_Verdef_Impl<ELFT> Elf_Verdef; |
51 | | typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; |
52 | | typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; |
53 | | typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; |
54 | | typedef Elf_Versym_Impl<ELFT> Elf_Versym; |
55 | | typedef Elf_Hash_Impl<ELFT> Elf_Hash; |
56 | | typedef Elf_GnuHash_Impl<ELFT> Elf_GnuHash; |
57 | | typedef iterator_range<const Elf_Dyn *> Elf_Dyn_Range; |
58 | | typedef iterator_range<const Elf_Shdr *> Elf_Shdr_Range; |
59 | | typedef iterator_range<const Elf_Sym *> Elf_Sym_Range; |
60 | | |
61 | | const uint8_t *base() const { |
62 | | return reinterpret_cast<const uint8_t *>(Buf.data()); |
63 | | } |
64 | | |
65 | | private: |
66 | | |
67 | | StringRef Buf; |
68 | | |
69 | | const Elf_Ehdr *Header; |
70 | | const Elf_Shdr *SectionHeaderTable = nullptr; |
71 | | StringRef DotShstrtab; // Section header string table. |
72 | | |
73 | | public: |
74 | | template<typename T> |
75 | | const T *getEntry(uint32_t Section, uint32_t Entry) const; |
76 | | template <typename T> |
77 | | const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; |
78 | | |
79 | | ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const; |
80 | | ErrorOr<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; |
81 | | |
82 | | ErrorOr<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; |
83 | | |
84 | | void VerifyStrTab(const Elf_Shdr *sh) const; |
85 | | |
86 | | StringRef getRelocationTypeName(uint32_t Type) const; |
87 | | void getRelocationTypeName(uint32_t Type, |
88 | | SmallVectorImpl<char> &Result) const; |
89 | | |
90 | | /// \brief Get the symbol for a given relocation. |
91 | | const Elf_Sym *getRelocationSymbol(const Elf_Rel *Rel, |
92 | | const Elf_Shdr *SymTab) const; |
93 | | |
94 | | ELFFile(StringRef Object, std::error_code &EC); |
95 | | |
96 | | bool isMipsELF64() const { |
97 | | return Header->e_machine == ELF::EM_MIPS && |
98 | | Header->getFileClass() == ELF::ELFCLASS64; |
99 | | } |
100 | | |
101 | | bool isMips64EL() const { |
102 | | return Header->e_machine == ELF::EM_MIPS && |
103 | | Header->getFileClass() == ELF::ELFCLASS64 && |
104 | | Header->getDataEncoding() == ELF::ELFDATA2LSB; |
105 | | } |
106 | | |
107 | | ErrorOr<const Elf_Dyn *> dynamic_table_begin(const Elf_Phdr *Phdr) const; |
108 | | ErrorOr<const Elf_Dyn *> dynamic_table_end(const Elf_Phdr *Phdr) const; |
109 | | ErrorOr<Elf_Dyn_Range> dynamic_table(const Elf_Phdr *Phdr) const { |
110 | | ErrorOr<const Elf_Dyn *> Begin = dynamic_table_begin(Phdr); |
111 | | if (std::error_code EC = Begin.getError()) |
112 | | return EC; |
113 | | ErrorOr<const Elf_Dyn *> End = dynamic_table_end(Phdr); |
114 | | if (std::error_code EC = End.getError()) |
115 | | return EC; |
116 | | return make_range(*Begin, *End); |
117 | | } |
118 | | |
119 | | const Elf_Shdr *section_begin() const; |
120 | | const Elf_Shdr *section_end() const; |
121 | | Elf_Shdr_Range sections() const { |
122 | | return make_range(section_begin(), section_end()); |
123 | | } |
124 | | |
125 | | const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const { |
126 | | if (!Sec) |
127 | | return nullptr; |
128 | | if (Sec->sh_entsize != sizeof(Elf_Sym)) |
129 | | report_fatal_error("Invalid symbol size"); |
130 | | return reinterpret_cast<const Elf_Sym *>(base() + Sec->sh_offset); |
131 | | } |
132 | | const Elf_Sym *symbol_end(const Elf_Shdr *Sec) const { |
133 | | if (!Sec) |
134 | | return nullptr; |
135 | | uint64_t Size = Sec->sh_size; |
136 | | if (Size % sizeof(Elf_Sym)) |
137 | | report_fatal_error("Invalid symbol table size"); |
138 | | return symbol_begin(Sec) + Size / sizeof(Elf_Sym); |
139 | | } |
140 | | Elf_Sym_Range symbols(const Elf_Shdr *Sec) const { |
141 | | return make_range(symbol_begin(Sec), symbol_end(Sec)); |
142 | | } |
143 | | |
144 | | typedef iterator_range<const Elf_Rela *> Elf_Rela_Range; |
145 | | |
146 | | const Elf_Rela *rela_begin(const Elf_Shdr *sec) const { |
147 | | if (sec->sh_entsize != sizeof(Elf_Rela)) |
148 | | report_fatal_error("Invalid relocation entry size"); |
149 | | return reinterpret_cast<const Elf_Rela *>(base() + sec->sh_offset); |
150 | | } |
151 | | |
152 | | const Elf_Rela *rela_end(const Elf_Shdr *sec) const { |
153 | | uint64_t Size = sec->sh_size; |
154 | | if (Size % sizeof(Elf_Rela)) |
155 | | report_fatal_error("Invalid relocation table size"); |
156 | | return rela_begin(sec) + Size / sizeof(Elf_Rela); |
157 | | } |
158 | | |
159 | | Elf_Rela_Range relas(const Elf_Shdr *Sec) const { |
160 | | return make_range(rela_begin(Sec), rela_end(Sec)); |
161 | | } |
162 | | |
163 | | const Elf_Rel *rel_begin(const Elf_Shdr *sec) const { |
164 | | if (sec->sh_entsize != sizeof(Elf_Rel)) |
165 | | report_fatal_error("Invalid relocation entry size"); |
166 | | return reinterpret_cast<const Elf_Rel *>(base() + sec->sh_offset); |
167 | | } |
168 | | |
169 | | const Elf_Rel *rel_end(const Elf_Shdr *sec) const { |
170 | | uint64_t Size = sec->sh_size; |
171 | | if (Size % sizeof(Elf_Rel)) |
172 | | report_fatal_error("Invalid relocation table size"); |
173 | | return rel_begin(sec) + Size / sizeof(Elf_Rel); |
174 | | } |
175 | | |
176 | | typedef iterator_range<const Elf_Rel *> Elf_Rel_Range; |
177 | | Elf_Rel_Range rels(const Elf_Shdr *Sec) const { |
178 | | return make_range(rel_begin(Sec), rel_end(Sec)); |
179 | | } |
180 | | |
181 | | /// \brief Iterate over program header table. |
182 | | const Elf_Phdr *program_header_begin() const { |
183 | | if (Header->e_phnum && Header->e_phentsize != sizeof(Elf_Phdr)) |
184 | | report_fatal_error("Invalid program header size"); |
185 | | return reinterpret_cast<const Elf_Phdr *>(base() + Header->e_phoff); |
186 | | } |
187 | | |
188 | | const Elf_Phdr *program_header_end() const { |
189 | | return program_header_begin() + Header->e_phnum; |
190 | | } |
191 | | |
192 | | typedef iterator_range<const Elf_Phdr *> Elf_Phdr_Range; |
193 | | |
194 | | const Elf_Phdr_Range program_headers() const { |
195 | | return make_range(program_header_begin(), program_header_end()); |
196 | | } |
197 | | |
198 | | uint64_t getNumSections() const; |
199 | | uintX_t getStringTableIndex() const; |
200 | | uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, |
201 | | const Elf_Shdr *SymTab, |
202 | | ArrayRef<Elf_Word> ShndxTable) const; |
203 | | const Elf_Ehdr *getHeader() const { return Header; } |
204 | | ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym, |
205 | | const Elf_Shdr *SymTab, |
206 | | ArrayRef<Elf_Word> ShndxTable) const; |
207 | | ErrorOr<const Elf_Shdr *> getSection(uint32_t Index) const; |
208 | | |
209 | | const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { |
210 | | return &*(symbol_begin(Sec) + Index); |
211 | | } |
212 | | |
213 | | ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const; |
214 | | template <typename T> |
215 | | ErrorOr<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const; |
216 | | ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const; |
217 | | }; |
218 | | |
219 | | typedef ELFFile<ELFType<support::little, false>> ELF32LEFile; |
220 | | typedef ELFFile<ELFType<support::little, true>> ELF64LEFile; |
221 | | typedef ELFFile<ELFType<support::big, false>> ELF32BEFile; |
222 | | typedef ELFFile<ELFType<support::big, true>> ELF64BEFile; |
223 | | |
224 | | template <class ELFT> |
225 | | uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( |
226 | | const Elf_Sym *Sym, const Elf_Shdr *SymTab, |
227 | | ArrayRef<Elf_Word> ShndxTable) const { |
228 | | assert(Sym->st_shndx == ELF::SHN_XINDEX); |
229 | | unsigned Index = Sym - symbol_begin(SymTab); |
230 | | |
231 | | // The size of the table was checked in getSHNDXTable. |
232 | | return ShndxTable[Index]; |
233 | | } |
234 | | |
235 | | template <class ELFT> |
236 | | ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *> |
237 | | ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, |
238 | | ArrayRef<Elf_Word> ShndxTable) const { |
239 | | uint32_t Index = Sym->st_shndx; |
240 | | if (Index == ELF::SHN_XINDEX) |
241 | | return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable)); |
242 | | |
243 | | if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) |
244 | | return nullptr; |
245 | | return getSection(Sym->st_shndx); |
246 | | } |
247 | | |
248 | | template <class ELFT> |
249 | | template <typename T> |
250 | | ErrorOr<ArrayRef<T>> |
251 | | ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { |
252 | | uintX_t Offset = Sec->sh_offset; |
253 | | uintX_t Size = Sec->sh_size; |
254 | | |
255 | | if (Size % sizeof(T)) |
256 | | return object_error::parse_failed; |
257 | | if (Offset + Size > Buf.size()) |
258 | | return object_error::parse_failed; |
259 | | |
260 | | const T *Start = reinterpret_cast<const T *>(base() + Offset); |
261 | | return makeArrayRef(Start, Size / sizeof(T)); |
262 | | } |
263 | | |
264 | | template <class ELFT> |
265 | | ErrorOr<ArrayRef<uint8_t>> |
266 | | ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { |
267 | | return getSectionContentsAsArray<uint8_t>(Sec); |
268 | | } |
269 | | |
270 | | template <class ELFT> |
271 | | StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { |
272 | | return getELFRelocationTypeName(Header->e_machine, Type); |
273 | | } |
274 | | |
275 | | template <class ELFT> |
276 | | void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, |
277 | | SmallVectorImpl<char> &Result) const { |
278 | | if (!isMipsELF64()) { |
279 | | StringRef Name = getRelocationTypeName(Type); |
280 | | Result.append(Name.begin(), Name.end()); |
281 | | } else { |
282 | | // The Mips N64 ABI allows up to three operations to be specified per |
283 | | // relocation record. Unfortunately there's no easy way to test for the |
284 | | // presence of N64 ELFs as they have no special flag that identifies them |
285 | | // as being N64. We can safely assume at the moment that all Mips |
286 | | // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough |
287 | | // information to disambiguate between old vs new ABIs. |
288 | | uint8_t Type1 = (Type >> 0) & 0xFF; |
289 | | uint8_t Type2 = (Type >> 8) & 0xFF; |
290 | | uint8_t Type3 = (Type >> 16) & 0xFF; |
291 | | |
292 | | // Concat all three relocation type names. |
293 | | StringRef Name = getRelocationTypeName(Type1); |
294 | | Result.append(Name.begin(), Name.end()); |
295 | | |
296 | | Name = getRelocationTypeName(Type2); |
297 | | Result.append(1, '/'); |
298 | | Result.append(Name.begin(), Name.end()); |
299 | | |
300 | | Name = getRelocationTypeName(Type3); |
301 | | Result.append(1, '/'); |
302 | | Result.append(Name.begin(), Name.end()); |
303 | | } |
304 | | } |
305 | | |
306 | | template <class ELFT> |
307 | | const typename ELFFile<ELFT>::Elf_Sym * |
308 | | ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, |
309 | | const Elf_Shdr *SymTab) const { |
310 | | uint32_t Index = Rel->getSymbol(isMips64EL()); |
311 | | if (Index == 0) |
312 | | return nullptr; |
313 | | return getEntry<Elf_Sym>(SymTab, Index); |
314 | | } |
315 | | |
316 | | template <class ELFT> |
317 | | uint64_t ELFFile<ELFT>::getNumSections() const { |
318 | | assert(Header && "Header not initialized!"); |
319 | | if (Header->e_shnum == ELF::SHN_UNDEF && Header->e_shoff > 0) { |
320 | | assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); |
321 | | return SectionHeaderTable->sh_size; |
322 | | } |
323 | | return Header->e_shnum; |
324 | | } |
325 | | |
326 | | template <class ELFT> |
327 | | typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const { |
328 | | if (Header->e_shnum == ELF::SHN_UNDEF) { |
329 | | if (Header->e_shstrndx == ELF::SHN_HIRESERVE) |
330 | | return SectionHeaderTable->sh_link; |
331 | | if (Header->e_shstrndx >= getNumSections()) |
332 | | return 0; |
333 | | } |
334 | | return Header->e_shstrndx; |
335 | | } |
336 | | |
337 | | template <class ELFT> |
338 | | ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) |
339 | | : Buf(Object) { |
340 | | const uint64_t FileSize = Buf.size(); |
341 | | |
342 | | if (sizeof(Elf_Ehdr) > FileSize) { |
343 | | // File too short! |
344 | | EC = object_error::parse_failed; |
345 | | return; |
346 | | } |
347 | | |
348 | | Header = reinterpret_cast<const Elf_Ehdr *>(base()); |
349 | | |
350 | | if (Header->e_shoff == 0) |
351 | | return; |
352 | | |
353 | | const uint64_t SectionTableOffset = Header->e_shoff; |
354 | | |
355 | | if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) { |
356 | | // Section header table goes past end of file! |
357 | | EC = object_error::parse_failed; |
358 | | return; |
359 | | } |
360 | | |
361 | | // The getNumSections() call below depends on SectionHeaderTable being set. |
362 | | SectionHeaderTable = |
363 | | reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); |
364 | | const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; |
365 | | |
366 | | if (SectionTableOffset + SectionTableSize > FileSize) { |
367 | | // Section table goes past end of file! |
368 | | EC = object_error::parse_failed; |
369 | | return; |
370 | | } |
371 | | |
372 | | // Get string table sections. |
373 | | uintX_t StringTableIndex = getStringTableIndex(); |
374 | | if (StringTableIndex) { |
375 | | ErrorOr<const Elf_Shdr *> StrTabSecOrErr = getSection(StringTableIndex); |
376 | | if ((EC = StrTabSecOrErr.getError())) |
377 | | return; |
378 | | |
379 | | ErrorOr<StringRef> StringTableOrErr = getStringTable(*StrTabSecOrErr); |
380 | | if ((EC = StringTableOrErr.getError())) |
381 | | return; |
382 | | DotShstrtab = *StringTableOrErr; |
383 | | } |
384 | | |
385 | | EC = std::error_code(); |
386 | | } |
387 | | |
388 | | template <class ELFT> |
389 | | static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { |
390 | | return VAddr < Phdr->p_vaddr; |
391 | | } |
392 | | |
393 | | template <class ELFT> |
394 | | const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_begin() const { |
395 | | if (Header->e_shentsize != sizeof(Elf_Shdr)) |
396 | | report_fatal_error( |
397 | | "Invalid section header entry size (e_shentsize) in ELF header"); |
398 | | return reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); |
399 | | } |
400 | | |
401 | | template <class ELFT> |
402 | | const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_end() const { |
403 | | return section_begin() + getNumSections(); |
404 | | } |
405 | | |
406 | | template <class ELFT> |
407 | | ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *> |
408 | | ELFFile<ELFT>::dynamic_table_begin(const Elf_Phdr *Phdr) const { |
409 | | if (!Phdr) |
410 | | return nullptr; |
411 | | assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header"); |
412 | | uintX_t Offset = Phdr->p_offset; |
413 | | if (Offset > Buf.size()) |
414 | | return object_error::parse_failed; |
415 | | return reinterpret_cast<const Elf_Dyn *>(base() + Offset); |
416 | | } |
417 | | |
418 | | template <class ELFT> |
419 | | ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *> |
420 | | ELFFile<ELFT>::dynamic_table_end(const Elf_Phdr *Phdr) const { |
421 | | if (!Phdr) |
422 | | return nullptr; |
423 | | assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header"); |
424 | | uintX_t Size = Phdr->p_filesz; |
425 | | if (Size % sizeof(Elf_Dyn)) |
426 | | return object_error::elf_invalid_dynamic_table_size; |
427 | | // FIKME: Check for overflow? |
428 | | uintX_t End = Phdr->p_offset + Size; |
429 | | if (End > Buf.size()) |
430 | | return object_error::parse_failed; |
431 | | return reinterpret_cast<const Elf_Dyn *>(base() + End); |
432 | | } |
433 | | |
434 | | template <class ELFT> |
435 | | template <typename T> |
436 | | const T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { |
437 | | ErrorOr<const Elf_Shdr *> Sec = getSection(Section); |
438 | | if (std::error_code EC = Sec.getError()) |
439 | | report_fatal_error(EC.message()); |
440 | | return getEntry<T>(*Sec, Entry); |
441 | | } |
442 | | |
443 | | template <class ELFT> |
444 | | template <typename T> |
445 | | const T *ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, |
446 | | uint32_t Entry) const { |
447 | | return reinterpret_cast<const T *>(base() + Section->sh_offset + |
448 | | (Entry * Section->sh_entsize)); |
449 | | } |
450 | | |
451 | | template <class ELFT> |
452 | | ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *> |
453 | | ELFFile<ELFT>::getSection(uint32_t Index) const { |
454 | | assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); |
455 | | if (Index >= getNumSections()) |
456 | | return object_error::invalid_section_index; |
457 | | |
458 | | return reinterpret_cast<const Elf_Shdr *>( |
459 | | reinterpret_cast<const char *>(SectionHeaderTable) + |
460 | | (Index * Header->e_shentsize)); |
461 | | } |
462 | | |
463 | | template <class ELFT> |
464 | | ErrorOr<StringRef> |
465 | | ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { |
466 | | if (Section->sh_type != ELF::SHT_STRTAB) |
467 | | return object_error::parse_failed; |
468 | | uint64_t Offset = Section->sh_offset; |
469 | | uint64_t Size = Section->sh_size; |
470 | | if (Offset + Size > Buf.size()) |
471 | | return object_error::parse_failed; |
472 | | StringRef Data((const char *)base() + Section->sh_offset, Size); |
473 | | if (Data[Size - 1] != '\0') |
474 | | return object_error::string_table_non_null_end; |
475 | | return Data; |
476 | | } |
477 | | |
478 | | template <class ELFT> |
479 | | ErrorOr<ArrayRef<typename ELFFile<ELFT>::Elf_Word>> |
480 | | ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { |
481 | | assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); |
482 | | const Elf_Word *ShndxTableBegin = |
483 | | reinterpret_cast<const Elf_Word *>(base() + Section.sh_offset); |
484 | | uintX_t Size = Section.sh_size; |
485 | | if (Size % sizeof(uint32_t)) |
486 | | return object_error::parse_failed; |
487 | | uintX_t NumSymbols = Size / sizeof(uint32_t); |
488 | | const Elf_Word *ShndxTableEnd = ShndxTableBegin + NumSymbols; |
489 | | if (reinterpret_cast<const char *>(ShndxTableEnd) > Buf.end()) |
490 | | return object_error::parse_failed; |
491 | | ErrorOr<const Elf_Shdr *> SymTableOrErr = getSection(Section.sh_link); |
492 | | if (std::error_code EC = SymTableOrErr.getError()) |
493 | | return EC; |
494 | | const Elf_Shdr &SymTable = **SymTableOrErr; |
495 | | if (SymTable.sh_type != ELF::SHT_SYMTAB && |
496 | | SymTable.sh_type != ELF::SHT_DYNSYM) |
497 | | return object_error::parse_failed; |
498 | | if (NumSymbols != (SymTable.sh_size / sizeof(Elf_Sym))) |
499 | | return object_error::parse_failed; |
500 | | return makeArrayRef(ShndxTableBegin, ShndxTableEnd); |
501 | | } |
502 | | |
503 | | template <class ELFT> |
504 | | ErrorOr<StringRef> |
505 | | ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { |
506 | | if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) |
507 | | return object_error::parse_failed; |
508 | | ErrorOr<const Elf_Shdr *> SectionOrErr = getSection(Sec.sh_link); |
509 | | if (std::error_code EC = SectionOrErr.getError()) |
510 | | return EC; |
511 | | return getStringTable(*SectionOrErr); |
512 | | } |
513 | | |
514 | | template <class ELFT> |
515 | | ErrorOr<StringRef> |
516 | | ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { |
517 | | uint32_t Offset = Section->sh_name; |
518 | | if (Offset == 0) |
519 | | return StringRef(); |
520 | | if (Offset >= DotShstrtab.size()) |
521 | | return object_error::parse_failed; |
522 | | return StringRef(DotShstrtab.data() + Offset); |
523 | | } |
524 | | |
525 | | /// This function returns the hash value for a symbol in the .dynsym section |
526 | | /// Name of the API remains consistent as specified in the libelf |
527 | | /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash |
528 | 0 | static inline unsigned elf_hash(StringRef &symbolName) { |
529 | 0 | unsigned h = 0, g; |
530 | 0 | for (unsigned i = 0, j = symbolName.size(); i < j; i++) { |
531 | 0 | h = (h << 4) + symbolName[i]; |
532 | 0 | g = h & 0xf0000000L; |
533 | 0 | if (g != 0) |
534 | 0 | h ^= g >> 24; |
535 | 0 | h &= ~g; |
536 | 0 | } |
537 | 0 | return h; |
538 | 0 | } Unexecuted instantiation: AArch64MCExpr.cpp:llvm_ks::object::elf_hash(llvm_ks::StringRef&) Unexecuted instantiation: SparcMCExpr.cpp:llvm_ks::object::elf_hash(llvm_ks::StringRef&) |
539 | | } // end namespace object |
540 | | } // end namespace llvm_ks |
541 | | |
542 | | #endif |