|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "mozilla/NullPtr.h" |
|
6 |
|
7 #include <stdexcept> |
|
8 #include <list> |
|
9 #include <vector> |
|
10 #include <cstring> |
|
11 #include <iostream> |
|
12 #include <fstream> |
|
13 #include <algorithm> |
|
14 #include <elf.h> |
|
15 #include <asm/byteorder.h> |
|
16 |
|
17 // Technically, __*_to_cpu and __cpu_to* function are equivalent, |
|
18 // so swap can use either of both. |
|
19 #define def_swap(endian, type, bits) \ |
|
20 static inline type ## bits ## _t swap(type ## bits ## _t i) { \ |
|
21 return __ ## endian ## bits ## _to_cpu(i); \ |
|
22 } |
|
23 |
|
24 class little_endian { |
|
25 public: |
|
26 def_swap(le, uint, 16); |
|
27 def_swap(le, uint, 32); |
|
28 def_swap(le, uint, 64); |
|
29 def_swap(le, int, 16); |
|
30 def_swap(le, int, 32); |
|
31 def_swap(le, int, 64); |
|
32 }; |
|
33 |
|
34 class big_endian { |
|
35 public: |
|
36 def_swap(be, uint, 16); |
|
37 def_swap(be, uint, 32); |
|
38 def_swap(be, uint, 64); |
|
39 def_swap(be, int, 16); |
|
40 def_swap(be, int, 32); |
|
41 def_swap(be, int, 64); |
|
42 }; |
|
43 |
|
44 // forward declaration |
|
45 class ElfSection; |
|
46 class ElfSegment; |
|
47 // TODO: Rename Elf_* types |
|
48 class Elf_Ehdr; |
|
49 class Elf_Phdr; |
|
50 class Elf; |
|
51 class ElfDynamic_Section; |
|
52 class ElfStrtab_Section; |
|
53 |
|
54 class Elf_Ehdr_Traits { |
|
55 public: |
|
56 typedef Elf32_Ehdr Type32; |
|
57 typedef Elf64_Ehdr Type64; |
|
58 |
|
59 template <class endian, typename R, typename T> |
|
60 static void swap(T &t, R &r); |
|
61 }; |
|
62 |
|
63 class Elf_Phdr_Traits { |
|
64 public: |
|
65 typedef Elf32_Phdr Type32; |
|
66 typedef Elf64_Phdr Type64; |
|
67 |
|
68 template <class endian, typename R, typename T> |
|
69 static void swap(T &t, R &r); |
|
70 }; |
|
71 |
|
72 class Elf_Shdr_Traits { |
|
73 public: |
|
74 typedef Elf32_Shdr Type32; |
|
75 typedef Elf64_Shdr Type64; |
|
76 |
|
77 template <class endian, typename R, typename T> |
|
78 static void swap(T &t, R &r); |
|
79 }; |
|
80 |
|
81 class Elf_Dyn_Traits { |
|
82 public: |
|
83 typedef Elf32_Dyn Type32; |
|
84 typedef Elf64_Dyn Type64; |
|
85 |
|
86 template <class endian, typename R, typename T> |
|
87 static void swap(T &t, R &r); |
|
88 }; |
|
89 |
|
90 class Elf_Sym_Traits { |
|
91 public: |
|
92 typedef Elf32_Sym Type32; |
|
93 typedef Elf64_Sym Type64; |
|
94 |
|
95 template <class endian, typename R, typename T> |
|
96 static void swap(T &t, R &r); |
|
97 }; |
|
98 |
|
99 class Elf_Rel_Traits { |
|
100 public: |
|
101 typedef Elf32_Rel Type32; |
|
102 typedef Elf64_Rel Type64; |
|
103 |
|
104 template <class endian, typename R, typename T> |
|
105 static void swap(T &t, R &r); |
|
106 }; |
|
107 |
|
108 class Elf_Rela_Traits { |
|
109 public: |
|
110 typedef Elf32_Rela Type32; |
|
111 typedef Elf64_Rela Type64; |
|
112 |
|
113 template <class endian, typename R, typename T> |
|
114 static void swap(T &t, R &r); |
|
115 }; |
|
116 |
|
117 class ElfValue { |
|
118 public: |
|
119 virtual unsigned int getValue() { return 0; } |
|
120 virtual ElfSection *getSection() { return nullptr; } |
|
121 }; |
|
122 |
|
123 class ElfPlainValue: public ElfValue { |
|
124 unsigned int value; |
|
125 public: |
|
126 ElfPlainValue(unsigned int val): value(val) {}; |
|
127 unsigned int getValue() { return value; } |
|
128 }; |
|
129 |
|
130 class ElfLocation: public ElfValue { |
|
131 ElfSection *section; |
|
132 unsigned int offset; |
|
133 public: |
|
134 enum position { ABSOLUTE, RELATIVE }; |
|
135 ElfLocation(): section(nullptr), offset(0) {}; |
|
136 ElfLocation(ElfSection *section, unsigned int off, enum position pos = RELATIVE); |
|
137 ElfLocation(unsigned int location, Elf *elf); |
|
138 unsigned int getValue(); |
|
139 ElfSection *getSection() { return section; } |
|
140 const char *getBuffer(); |
|
141 }; |
|
142 |
|
143 class ElfSize: public ElfValue { |
|
144 ElfSection *section; |
|
145 public: |
|
146 ElfSize(ElfSection *s): section(s) {}; |
|
147 unsigned int getValue(); |
|
148 ElfSection *getSection() { return section; } |
|
149 }; |
|
150 |
|
151 class ElfEntSize: public ElfValue { |
|
152 ElfSection *section; |
|
153 public: |
|
154 ElfEntSize(ElfSection *s): section(s) {}; |
|
155 unsigned int getValue(); |
|
156 ElfSection *getSection() { return section; } |
|
157 }; |
|
158 |
|
159 template <typename T> |
|
160 class serializable: public T::Type32 { |
|
161 public: |
|
162 serializable() {}; |
|
163 serializable(const typename T::Type32 &p): T::Type32(p) {}; |
|
164 |
|
165 private: |
|
166 template <typename R> |
|
167 void init(const char *buf, size_t len, char ei_data) |
|
168 { |
|
169 R e; |
|
170 assert(len >= sizeof(e)); |
|
171 memcpy(&e, buf, sizeof(e)); |
|
172 if (ei_data == ELFDATA2LSB) { |
|
173 T::template swap<little_endian>(e, *this); |
|
174 return; |
|
175 } else if (ei_data == ELFDATA2MSB) { |
|
176 T::template swap<big_endian>(e, *this); |
|
177 return; |
|
178 } |
|
179 throw std::runtime_error("Unsupported ELF data encoding"); |
|
180 } |
|
181 |
|
182 template <typename R> |
|
183 void serialize(const char *buf, size_t len, char ei_data) |
|
184 { |
|
185 assert(len >= sizeof(R)); |
|
186 if (ei_data == ELFDATA2LSB) { |
|
187 T::template swap<little_endian>(*this, *(R *)buf); |
|
188 return; |
|
189 } else if (ei_data == ELFDATA2MSB) { |
|
190 T::template swap<big_endian>(*this, *(R *)buf); |
|
191 return; |
|
192 } |
|
193 throw std::runtime_error("Unsupported ELF data encoding"); |
|
194 } |
|
195 |
|
196 public: |
|
197 serializable(const char *buf, size_t len, char ei_class, char ei_data) |
|
198 { |
|
199 if (ei_class == ELFCLASS32) { |
|
200 init<typename T::Type32>(buf, len, ei_data); |
|
201 return; |
|
202 } else if (ei_class == ELFCLASS64) { |
|
203 init<typename T::Type64>(buf, len, ei_data); |
|
204 return; |
|
205 } |
|
206 throw std::runtime_error("Unsupported ELF class"); |
|
207 } |
|
208 |
|
209 serializable(std::ifstream &file, char ei_class, char ei_data) |
|
210 { |
|
211 if (ei_class == ELFCLASS32) { |
|
212 typename T::Type32 e; |
|
213 file.read((char *)&e, sizeof(e)); |
|
214 init<typename T::Type32>((char *)&e, sizeof(e), ei_data); |
|
215 return; |
|
216 } else if (ei_class == ELFCLASS64) { |
|
217 typename T::Type64 e; |
|
218 file.read((char *)&e, sizeof(e)); |
|
219 init<typename T::Type64>((char *)&e, sizeof(e), ei_data); |
|
220 return; |
|
221 } |
|
222 throw std::runtime_error("Unsupported ELF class or data encoding"); |
|
223 } |
|
224 |
|
225 void serialize(std::ofstream &file, char ei_class, char ei_data) |
|
226 { |
|
227 if (ei_class == ELFCLASS32) { |
|
228 typename T::Type32 e; |
|
229 serialize<typename T::Type32>((char *)&e, sizeof(e), ei_data); |
|
230 file.write((char *)&e, sizeof(e)); |
|
231 return; |
|
232 } else if (ei_class == ELFCLASS64) { |
|
233 typename T::Type64 e; |
|
234 serialize<typename T::Type64>((char *)&e, sizeof(e), ei_data); |
|
235 file.write((char *)&e, sizeof(e)); |
|
236 return; |
|
237 } |
|
238 throw std::runtime_error("Unsupported ELF class or data encoding"); |
|
239 } |
|
240 |
|
241 void serialize(char *buf, size_t len, char ei_class, char ei_data) |
|
242 { |
|
243 if (ei_class == ELFCLASS32) { |
|
244 serialize<typename T::Type32>(buf, len, ei_data); |
|
245 return; |
|
246 } else if (ei_class == ELFCLASS64) { |
|
247 serialize<typename T::Type64>(buf, len, ei_data); |
|
248 return; |
|
249 } |
|
250 throw std::runtime_error("Unsupported ELF class"); |
|
251 } |
|
252 |
|
253 static inline unsigned int size(char ei_class) |
|
254 { |
|
255 if (ei_class == ELFCLASS32) |
|
256 return sizeof(typename T::Type32); |
|
257 else if (ei_class == ELFCLASS64) |
|
258 return sizeof(typename T::Type64); |
|
259 return 0; |
|
260 } |
|
261 }; |
|
262 |
|
263 typedef serializable<Elf_Shdr_Traits> Elf_Shdr; |
|
264 |
|
265 class Elf { |
|
266 public: |
|
267 Elf(std::ifstream &file); |
|
268 ~Elf(); |
|
269 |
|
270 /* index == -1 is treated as index == ehdr.e_shstrndx */ |
|
271 ElfSection *getSection(int index); |
|
272 |
|
273 ElfSection *getSectionAt(unsigned int offset); |
|
274 |
|
275 ElfSegment *getSegmentByType(unsigned int type, ElfSegment *last = nullptr); |
|
276 |
|
277 ElfDynamic_Section *getDynSection(); |
|
278 |
|
279 void normalize(); |
|
280 void write(std::ofstream &file); |
|
281 |
|
282 char getClass(); |
|
283 char getData(); |
|
284 char getType(); |
|
285 char getMachine(); |
|
286 unsigned int getSize(); |
|
287 |
|
288 void insertSegmentAfter(ElfSegment *previous, ElfSegment *segment) { |
|
289 std::vector<ElfSegment *>::iterator prev = std::find(segments.begin(), segments.end(), previous); |
|
290 segments.insert(prev + 1, segment); |
|
291 } |
|
292 |
|
293 void removeSegment(ElfSegment *segment); |
|
294 |
|
295 private: |
|
296 Elf_Ehdr *ehdr; |
|
297 ElfLocation eh_entry; |
|
298 ElfStrtab_Section *eh_shstrndx; |
|
299 ElfSection **sections; |
|
300 std::vector<ElfSegment *> segments; |
|
301 ElfSection *shdr_section, *phdr_section; |
|
302 /* Values used only during initialization */ |
|
303 Elf_Shdr **tmp_shdr; |
|
304 std::ifstream *tmp_file; |
|
305 }; |
|
306 |
|
307 class ElfSection { |
|
308 public: |
|
309 typedef union { |
|
310 ElfSection *section; |
|
311 int index; |
|
312 } SectionInfo; |
|
313 |
|
314 ElfSection(Elf_Shdr &s, std::ifstream *file, Elf *parent); |
|
315 |
|
316 virtual ~ElfSection() { |
|
317 delete[] data; |
|
318 } |
|
319 |
|
320 const char *getName() { return name; } |
|
321 unsigned int getType() { return shdr.sh_type; } |
|
322 unsigned int getFlags() { return shdr.sh_flags; } |
|
323 unsigned int getAddr(); |
|
324 unsigned int getSize() { return shdr.sh_size; } |
|
325 unsigned int getAddrAlign() { return shdr.sh_addralign; } |
|
326 unsigned int getEntSize() { return shdr.sh_entsize; } |
|
327 const char *getData() { return data; } |
|
328 ElfSection *getLink() { return link; } |
|
329 SectionInfo getInfo() { return info; } |
|
330 |
|
331 void shrink(unsigned int newsize) { |
|
332 if (newsize < shdr.sh_size) |
|
333 shdr.sh_size = newsize; |
|
334 } |
|
335 |
|
336 unsigned int getOffset(); |
|
337 int getIndex(); |
|
338 Elf_Shdr &getShdr(); |
|
339 |
|
340 ElfSection *getNext() { return next; } |
|
341 ElfSection *getPrevious() { return previous; } |
|
342 |
|
343 virtual bool isRelocatable() { |
|
344 return ((getType() == SHT_SYMTAB) || |
|
345 (getType() == SHT_STRTAB) || |
|
346 (getType() == SHT_RELA) || |
|
347 (getType() == SHT_HASH) || |
|
348 (getType() == SHT_NOTE) || |
|
349 (getType() == SHT_REL) || |
|
350 (getType() == SHT_DYNSYM) || |
|
351 (getType() == SHT_GNU_HASH) || |
|
352 (getType() == SHT_GNU_verdef) || |
|
353 (getType() == SHT_GNU_verneed) || |
|
354 (getType() == SHT_GNU_versym) || |
|
355 getSegmentByType(PT_INTERP)) && |
|
356 (getFlags() & SHF_ALLOC); |
|
357 } |
|
358 |
|
359 void insertAfter(ElfSection *section, bool dirty = true) { |
|
360 if (previous != nullptr) |
|
361 previous->next = next; |
|
362 if (next != nullptr) |
|
363 next->previous = previous; |
|
364 previous = section; |
|
365 if (section != nullptr) { |
|
366 next = section->next; |
|
367 section->next = this; |
|
368 } else |
|
369 next = nullptr; |
|
370 if (next != nullptr) |
|
371 next->previous = this; |
|
372 if (dirty) |
|
373 markDirty(); |
|
374 insertInSegments(section->segments); |
|
375 } |
|
376 |
|
377 void insertBefore(ElfSection *section, bool dirty = true) { |
|
378 if (previous != nullptr) |
|
379 previous->next = next; |
|
380 if (next != nullptr) |
|
381 next->previous = previous; |
|
382 next = section; |
|
383 if (section != nullptr) { |
|
384 previous = section->previous; |
|
385 section->previous = this; |
|
386 } else |
|
387 previous = nullptr; |
|
388 if (previous != nullptr) |
|
389 previous->next = this; |
|
390 if (dirty) |
|
391 markDirty(); |
|
392 insertInSegments(section->segments); |
|
393 } |
|
394 |
|
395 void markDirty() { |
|
396 if (link != nullptr) |
|
397 shdr.sh_link = -1; |
|
398 if (info.index) |
|
399 shdr.sh_info = -1; |
|
400 shdr.sh_offset = -1; |
|
401 if (isRelocatable()) |
|
402 shdr.sh_addr = -1; |
|
403 if (next) |
|
404 next->markDirty(); |
|
405 } |
|
406 |
|
407 virtual void serialize(std::ofstream &file, char ei_class, char ei_data) |
|
408 { |
|
409 if (getType() == SHT_NOBITS) |
|
410 return; |
|
411 file.seekp(getOffset()); |
|
412 file.write(data, getSize()); |
|
413 } |
|
414 |
|
415 private: |
|
416 friend class ElfSegment; |
|
417 |
|
418 void addToSegment(ElfSegment *segment) { |
|
419 segments.push_back(segment); |
|
420 } |
|
421 |
|
422 void removeFromSegment(ElfSegment *segment) { |
|
423 std::vector<ElfSegment *>::iterator i = std::find(segments.begin(), segments.end(), segment); |
|
424 segments.erase(i, i + 1); |
|
425 } |
|
426 |
|
427 ElfSegment *getSegmentByType(unsigned int type); |
|
428 |
|
429 void insertInSegments(std::vector<ElfSegment *> &segs); |
|
430 |
|
431 protected: |
|
432 Elf_Shdr shdr; |
|
433 char *data; |
|
434 const char *name; |
|
435 private: |
|
436 ElfSection *link; |
|
437 SectionInfo info; |
|
438 ElfSection *next, *previous; |
|
439 int index; |
|
440 std::vector<ElfSegment *> segments; |
|
441 }; |
|
442 |
|
443 class ElfSegment { |
|
444 public: |
|
445 ElfSegment(Elf_Phdr *phdr); |
|
446 |
|
447 unsigned int getType() { return type; } |
|
448 unsigned int getFlags() { return flags; } |
|
449 unsigned int getAlign() { return align; } |
|
450 |
|
451 ElfSection *getFirstSection() { return sections.empty() ? nullptr : sections.front(); } |
|
452 int getVPDiff() { return v_p_diff; } |
|
453 unsigned int getFileSize(); |
|
454 unsigned int getMemSize(); |
|
455 unsigned int getOffset(); |
|
456 unsigned int getAddr(); |
|
457 |
|
458 void addSection(ElfSection *section); |
|
459 void removeSection(ElfSection *section); |
|
460 |
|
461 std::list<ElfSection *>::iterator begin() { return sections.begin(); } |
|
462 std::list<ElfSection *>::iterator end() { return sections.end(); } |
|
463 |
|
464 void clear(); |
|
465 |
|
466 bool isElfHackFillerSegment() { |
|
467 return type == PT_LOAD && flags == 0; |
|
468 } |
|
469 private: |
|
470 unsigned int type; |
|
471 int v_p_diff; // Difference between physical and virtual address |
|
472 unsigned int flags; |
|
473 unsigned int align; |
|
474 std::list<ElfSection *> sections; |
|
475 // The following are only really used for PT_GNU_RELRO until something |
|
476 // better is found. |
|
477 unsigned int vaddr; |
|
478 unsigned int filesz, memsz; |
|
479 }; |
|
480 |
|
481 class Elf_Ehdr: public serializable<Elf_Ehdr_Traits>, public ElfSection { |
|
482 public: |
|
483 Elf_Ehdr(std::ifstream &file, char ei_class, char ei_data); |
|
484 void serialize(std::ofstream &file, char ei_class, char ei_data) |
|
485 { |
|
486 serializable<Elf_Ehdr_Traits>::serialize(file, ei_class, ei_data); |
|
487 } |
|
488 }; |
|
489 |
|
490 class Elf_Phdr: public serializable<Elf_Phdr_Traits> { |
|
491 public: |
|
492 Elf_Phdr() {}; |
|
493 Elf_Phdr(std::ifstream &file, char ei_class, char ei_data) |
|
494 : serializable<Elf_Phdr_Traits>(file, ei_class, ei_data) {}; |
|
495 bool contains(ElfSection *section) |
|
496 { |
|
497 unsigned int size = section->getSize(); |
|
498 unsigned int addr = section->getAddr(); |
|
499 // This may be biased, but should work in most cases |
|
500 if ((section->getFlags() & SHF_ALLOC) == 0) |
|
501 return false; |
|
502 // Special case for PT_DYNAMIC. Eventually, this should |
|
503 // be better handled than special cases |
|
504 if ((p_type == PT_DYNAMIC) && (section->getType() != SHT_DYNAMIC)) |
|
505 return false; |
|
506 // Special case for PT_TLS. |
|
507 if ((p_type == PT_TLS) && !(section->getFlags() & SHF_TLS)) |
|
508 return false; |
|
509 return (addr >= p_vaddr) && |
|
510 (addr + size <= p_vaddr + p_memsz); |
|
511 |
|
512 } |
|
513 }; |
|
514 |
|
515 typedef serializable<Elf_Dyn_Traits> Elf_Dyn; |
|
516 |
|
517 struct Elf_DynValue { |
|
518 unsigned int tag; |
|
519 ElfValue *value; |
|
520 }; |
|
521 |
|
522 class ElfDynamic_Section: public ElfSection { |
|
523 public: |
|
524 ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent); |
|
525 ~ElfDynamic_Section(); |
|
526 |
|
527 void serialize(std::ofstream &file, char ei_class, char ei_data); |
|
528 |
|
529 ElfValue *getValueForType(unsigned int tag); |
|
530 ElfSection *getSectionForType(unsigned int tag); |
|
531 bool setValueForType(unsigned int tag, ElfValue *val); |
|
532 private: |
|
533 std::vector<Elf_DynValue> dyns; |
|
534 }; |
|
535 |
|
536 typedef serializable<Elf_Sym_Traits> Elf_Sym; |
|
537 |
|
538 struct Elf_SymValue { |
|
539 const char *name; |
|
540 unsigned char info; |
|
541 unsigned char other; |
|
542 ElfLocation value; |
|
543 unsigned int size; |
|
544 bool defined; |
|
545 }; |
|
546 |
|
547 #define STT(type) (1 << STT_ ##type) |
|
548 |
|
549 class ElfSymtab_Section: public ElfSection { |
|
550 public: |
|
551 ElfSymtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent); |
|
552 |
|
553 void serialize(std::ofstream &file, char ei_class, char ei_data); |
|
554 |
|
555 Elf_SymValue *lookup(const char *name, unsigned int type_filter = STT(OBJECT) | STT(FUNC)); |
|
556 |
|
557 //private: // Until we have a real API |
|
558 std::vector<Elf_SymValue> syms; |
|
559 }; |
|
560 |
|
561 class Elf_Rel: public serializable<Elf_Rel_Traits> { |
|
562 public: |
|
563 Elf_Rel(std::ifstream &file, char ei_class, char ei_data) |
|
564 : serializable<Elf_Rel_Traits>(file, ei_class, ei_data) {}; |
|
565 |
|
566 static const unsigned int sh_type = SHT_REL; |
|
567 static const unsigned int d_tag = DT_REL; |
|
568 static const unsigned int d_tag_count = DT_RELCOUNT; |
|
569 }; |
|
570 |
|
571 class Elf_Rela: public serializable<Elf_Rela_Traits> { |
|
572 public: |
|
573 Elf_Rela(std::ifstream &file, char ei_class, char ei_data) |
|
574 : serializable<Elf_Rela_Traits>(file, ei_class, ei_data) {}; |
|
575 |
|
576 static const unsigned int sh_type = SHT_RELA; |
|
577 static const unsigned int d_tag = DT_RELA; |
|
578 static const unsigned int d_tag_count = DT_RELACOUNT; |
|
579 }; |
|
580 |
|
581 template <class Rel> |
|
582 class ElfRel_Section: public ElfSection { |
|
583 public: |
|
584 ElfRel_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent) |
|
585 : ElfSection(s, file, parent) |
|
586 { |
|
587 int pos = file->tellg(); |
|
588 file->seekg(shdr.sh_offset); |
|
589 for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) { |
|
590 Rel r(*file, parent->getClass(), parent->getData()); |
|
591 rels.push_back(r); |
|
592 } |
|
593 file->seekg(pos); |
|
594 } |
|
595 |
|
596 void serialize(std::ofstream &file, char ei_class, char ei_data) |
|
597 { |
|
598 for (typename std::vector<Rel>::iterator i = rels.begin(); |
|
599 i != rels.end(); ++i) |
|
600 (*i).serialize(file, ei_class, ei_data); |
|
601 } |
|
602 //private: // Until we have a real API |
|
603 std::vector<Rel> rels; |
|
604 }; |
|
605 |
|
606 class ElfStrtab_Section: public ElfSection { |
|
607 public: |
|
608 ElfStrtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent) |
|
609 : ElfSection(s, file, parent) |
|
610 { |
|
611 table.push_back(table_storage(data, shdr.sh_size)); |
|
612 } |
|
613 |
|
614 ~ElfStrtab_Section() |
|
615 { |
|
616 for (std::vector<table_storage>::iterator t = table.begin() + 1; |
|
617 t != table.end(); t++) |
|
618 delete[] t->buf; |
|
619 } |
|
620 |
|
621 const char *getStr(unsigned int index); |
|
622 |
|
623 const char *getStr(const char *string); |
|
624 |
|
625 unsigned int getStrIndex(const char *string); |
|
626 |
|
627 void serialize(std::ofstream &file, char ei_class, char ei_data); |
|
628 private: |
|
629 struct table_storage { |
|
630 unsigned int size, used; |
|
631 char *buf; |
|
632 |
|
633 table_storage(): size(4096), used(0), buf(new char[4096]) {} |
|
634 table_storage(const char *data, unsigned int sz) |
|
635 : size(sz), used(sz), buf(const_cast<char *>(data)) {} |
|
636 }; |
|
637 std::vector<table_storage> table; |
|
638 }; |
|
639 |
|
640 inline char Elf::getClass() { |
|
641 return ehdr->e_ident[EI_CLASS]; |
|
642 } |
|
643 |
|
644 inline char Elf::getData() { |
|
645 return ehdr->e_ident[EI_DATA]; |
|
646 } |
|
647 |
|
648 inline char Elf::getType() { |
|
649 return ehdr->e_type; |
|
650 } |
|
651 |
|
652 inline char Elf::getMachine() { |
|
653 return ehdr->e_machine; |
|
654 } |
|
655 |
|
656 inline unsigned int Elf::getSize() { |
|
657 ElfSection *section; |
|
658 for (section = shdr_section /* It's usually not far from the end */; |
|
659 section->getNext() != nullptr; section = section->getNext()); |
|
660 return section->getOffset() + section->getSize(); |
|
661 } |
|
662 |
|
663 inline ElfSegment *ElfSection::getSegmentByType(unsigned int type) { |
|
664 for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++) |
|
665 if ((*seg)->getType() == type) |
|
666 return *seg; |
|
667 return nullptr; |
|
668 } |
|
669 |
|
670 inline void ElfSection::insertInSegments(std::vector<ElfSegment *> &segs) { |
|
671 for (std::vector<ElfSegment *>::iterator it = segs.begin(); it != segs.end(); ++it) { |
|
672 (*it)->addSection(this); |
|
673 } |
|
674 } |
|
675 |
|
676 inline ElfLocation::ElfLocation(ElfSection *section, unsigned int off, enum position pos) |
|
677 : section(section) { |
|
678 if ((pos == ABSOLUTE) && section) |
|
679 offset = off - section->getAddr(); |
|
680 else |
|
681 offset = off; |
|
682 } |
|
683 |
|
684 inline ElfLocation::ElfLocation(unsigned int location, Elf *elf) { |
|
685 section = elf->getSectionAt(location); |
|
686 offset = location - (section ? section->getAddr() : 0); |
|
687 } |
|
688 |
|
689 inline unsigned int ElfLocation::getValue() { |
|
690 return (section ? section->getAddr() : 0) + offset; |
|
691 } |
|
692 |
|
693 inline const char *ElfLocation::getBuffer() { |
|
694 return section ? section->getData() + offset : nullptr; |
|
695 } |
|
696 |
|
697 inline unsigned int ElfSize::getValue() { |
|
698 return section->getSize(); |
|
699 } |
|
700 |
|
701 inline unsigned int ElfEntSize::getValue() { |
|
702 return section->getEntSize(); |
|
703 } |