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 #undef NDEBUG
6 #include <cstring>
7 #include <assert.h>
8 #include "elfxx.h"
9 
10 template <class endian, typename R, typename T>
swap(T & t,R & r)11 void Elf_Ehdr_Traits::swap(T& t, R& r) {
12   memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident));
13   r.e_type = endian::swap(t.e_type);
14   r.e_machine = endian::swap(t.e_machine);
15   r.e_version = endian::swap(t.e_version);
16   r.e_entry = endian::swap(t.e_entry);
17   r.e_phoff = endian::swap(t.e_phoff);
18   r.e_shoff = endian::swap(t.e_shoff);
19   r.e_flags = endian::swap(t.e_flags);
20   r.e_ehsize = endian::swap(t.e_ehsize);
21   r.e_phentsize = endian::swap(t.e_phentsize);
22   r.e_phnum = endian::swap(t.e_phnum);
23   r.e_shentsize = endian::swap(t.e_shentsize);
24   r.e_shnum = endian::swap(t.e_shnum);
25   r.e_shstrndx = endian::swap(t.e_shstrndx);
26 }
27 
28 template <class endian, typename R, typename T>
swap(T & t,R & r)29 void Elf_Phdr_Traits::swap(T& t, R& r) {
30   r.p_type = endian::swap(t.p_type);
31   r.p_offset = endian::swap(t.p_offset);
32   r.p_vaddr = endian::swap(t.p_vaddr);
33   r.p_paddr = endian::swap(t.p_paddr);
34   r.p_filesz = endian::swap(t.p_filesz);
35   r.p_memsz = endian::swap(t.p_memsz);
36   r.p_flags = endian::swap(t.p_flags);
37   r.p_align = endian::swap(t.p_align);
38 }
39 
40 template <class endian, typename R, typename T>
swap(T & t,R & r)41 void Elf_Shdr_Traits::swap(T& t, R& r) {
42   r.sh_name = endian::swap(t.sh_name);
43   r.sh_type = endian::swap(t.sh_type);
44   r.sh_flags = endian::swap(t.sh_flags);
45   r.sh_addr = endian::swap(t.sh_addr);
46   r.sh_offset = endian::swap(t.sh_offset);
47   r.sh_size = endian::swap(t.sh_size);
48   r.sh_link = endian::swap(t.sh_link);
49   r.sh_info = endian::swap(t.sh_info);
50   r.sh_addralign = endian::swap(t.sh_addralign);
51   r.sh_entsize = endian::swap(t.sh_entsize);
52 }
53 
54 template <class endian, typename R, typename T>
swap(T & t,R & r)55 void Elf_Dyn_Traits::swap(T& t, R& r) {
56   r.d_tag = endian::swap(t.d_tag);
57   r.d_un.d_val = endian::swap(t.d_un.d_val);
58 }
59 
60 template <class endian, typename R, typename T>
swap(T & t,R & r)61 void Elf_Sym_Traits::swap(T& t, R& r) {
62   r.st_name = endian::swap(t.st_name);
63   r.st_value = endian::swap(t.st_value);
64   r.st_size = endian::swap(t.st_size);
65   r.st_info = t.st_info;
66   r.st_other = t.st_other;
67   r.st_shndx = endian::swap(t.st_shndx);
68 }
69 
70 template <class endian>
71 struct _Rel_info {
swap_Rel_info72   static inline void swap(Elf32_Word& t, Elf32_Word& r) { r = endian::swap(t); }
swap_Rel_info73   static inline void swap(Elf64_Xword& t, Elf64_Xword& r) {
74     r = endian::swap(t);
75   }
swap_Rel_info76   static inline void swap(Elf64_Xword& t, Elf32_Word& r) {
77     r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t)));
78   }
swap_Rel_info79   static inline void swap(Elf32_Word& t, Elf64_Xword& r) {
80     r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t)));
81   }
82 };
83 
84 template <class endian, typename R, typename T>
swap(T & t,R & r)85 void Elf_Rel_Traits::swap(T& t, R& r) {
86   r.r_offset = endian::swap(t.r_offset);
87   _Rel_info<endian>::swap(t.r_info, r.r_info);
88 }
89 
90 template <class endian, typename R, typename T>
swap(T & t,R & r)91 void Elf_Rela_Traits::swap(T& t, R& r) {
92   r.r_offset = endian::swap(t.r_offset);
93   _Rel_info<endian>::swap(t.r_info, r.r_info);
94   r.r_addend = endian::swap(t.r_addend);
95 }
96 
97 static const Elf64_Shdr null64_section = {0, SHT_NULL,  0, 0, 0,
98                                           0, SHN_UNDEF, 0, 0, 0};
99 
100 Elf_Shdr null_section(null64_section);
101 
Elf_Ehdr(std::ifstream & file,unsigned char ei_class,unsigned char ei_data)102 Elf_Ehdr::Elf_Ehdr(std::ifstream& file, unsigned char ei_class,
103                    unsigned char ei_data)
104     : serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data),
105       ElfSection(null_section, nullptr, nullptr) {
106   shdr.sh_size = Elf_Ehdr::size(ei_class);
107 }
108 
Elf(std::ifstream & file)109 Elf::Elf(std::ifstream& file) {
110   if (!file.is_open()) throw std::runtime_error("Error opening file");
111 
112   file.exceptions(std::ifstream::eofbit | std::ifstream::failbit |
113                   std::ifstream::badbit);
114   // Read ELF magic number and identification information
115   unsigned char e_ident[EI_VERSION];
116   file.seekg(0);
117   file.read((char*)e_ident, sizeof(e_ident));
118   file.seekg(0);
119   ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
120 
121   // ELFOSABI_LINUX is kept unsupported because I haven't looked whether
122   // STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing.
123   if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) &&
124       (ehdr->e_ident[EI_ABIVERSION] != 0))
125     throw std::runtime_error("unsupported ELF ABI");
126 
127   if (ehdr->e_version != 1) throw std::runtime_error("unsupported ELF version");
128 
129   // Sanity checks
130   if (ehdr->e_shnum == 0)
131     throw std::runtime_error("sstripped ELF files aren't supported");
132 
133   if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS]))
134     throw std::runtime_error(
135         "unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)");
136 
137   if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS]))
138     throw std::runtime_error(
139         "unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)");
140 
141   if (ehdr->e_phnum == 0) {
142     if (ehdr->e_phoff != 0)
143       throw std::runtime_error(
144           "unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0");
145     if (ehdr->e_phentsize != 0)
146       throw std::runtime_error(
147           "unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0");
148   } else if (ehdr->e_phoff != ehdr->e_ehsize)
149     throw std::runtime_error(
150         "unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize");
151   else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS]))
152     throw std::runtime_error(
153         "unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)");
154 
155   // Read section headers
156   Elf_Shdr** shdr = new Elf_Shdr*[ehdr->e_shnum];
157   file.seekg(ehdr->e_shoff);
158   for (int i = 0; i < ehdr->e_shnum; i++)
159     shdr[i] = new Elf_Shdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
160 
161   // Sanity check in section header for index 0
162   if ((shdr[0]->sh_name != 0) || (shdr[0]->sh_type != SHT_NULL) ||
163       (shdr[0]->sh_flags != 0) || (shdr[0]->sh_addr != 0) ||
164       (shdr[0]->sh_offset != 0) || (shdr[0]->sh_size != 0) ||
165       (shdr[0]->sh_link != SHN_UNDEF) || (shdr[0]->sh_info != 0) ||
166       (shdr[0]->sh_addralign != 0) || (shdr[0]->sh_entsize != 0))
167     throw std::runtime_error(
168         "Section header for index 0 contains unsupported values");
169 
170   if ((shdr[ehdr->e_shstrndx]->sh_link != 0) ||
171       (shdr[ehdr->e_shstrndx]->sh_info != 0))
172     throw std::runtime_error(
173         "unsupported ELF content: string table with sh_link != 0 || sh_info != "
174         "0");
175 
176   // Store these temporarily
177   tmp_shdr = shdr;
178   tmp_file = &file;
179 
180   // Fill sections list
181   sections = new ElfSection*[ehdr->e_shnum];
182   for (int i = 0; i < ehdr->e_shnum; i++) sections[i] = nullptr;
183   for (int i = 1; i < ehdr->e_shnum; i++) {
184     // The .dynamic section is going to have references to other sections,
185     // so it's better to start with that one and recursively initialize those
186     // other sections first, to avoid possible infinite recursion (bug 1606739).
187     if (tmp_shdr[i]->sh_type == SHT_DYNAMIC) {
188       getSection(i);
189     }
190   }
191   for (int i = 1; i < ehdr->e_shnum; i++) {
192     if (sections[i] != nullptr) continue;
193     getSection(i);
194   }
195   Elf_Shdr s;
196   s.sh_name = 0;
197   s.sh_type = SHT_NULL;
198   s.sh_flags = 0;
199   s.sh_addr = 0;
200   s.sh_offset = ehdr->e_shoff;
201   s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]);
202   s.sh_size = s.sh_entsize * ehdr->e_shnum;
203   s.sh_link = 0;
204   s.sh_info = 0;
205   s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8;
206   shdr_section = new ElfSection(s, nullptr, nullptr);
207 
208   // Fake section for program headers
209   s.sh_offset = ehdr->e_phoff;
210   s.sh_addr = ehdr->e_phoff;
211   s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]);
212   s.sh_size = s.sh_entsize * ehdr->e_phnum;
213   phdr_section = new ElfSection(s, nullptr, nullptr);
214 
215   phdr_section->insertAfter(ehdr, false);
216 
217   sections[1]->insertAfter(phdr_section, false);
218   for (int i = 2; i < ehdr->e_shnum; i++) {
219     // TODO: this should be done in a better way
220     if ((shdr_section->getPrevious() == nullptr) &&
221         (shdr[i]->sh_offset > ehdr->e_shoff)) {
222       shdr_section->insertAfter(sections[i - 1], false);
223       sections[i]->insertAfter(shdr_section, false);
224     } else
225       sections[i]->insertAfter(sections[i - 1], false);
226   }
227   if (shdr_section->getPrevious() == nullptr)
228     shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false);
229 
230   tmp_file = nullptr;
231   tmp_shdr = nullptr;
232   for (int i = 0; i < ehdr->e_shnum; i++) delete shdr[i];
233   delete[] shdr;
234 
235   eh_shstrndx = (ElfStrtab_Section*)sections[ehdr->e_shstrndx];
236 
237   // Skip reading program headers if there aren't any
238   if (ehdr->e_phnum == 0) return;
239 
240   bool adjusted_phdr_section = false;
241   // Read program headers
242   file.seekg(ehdr->e_phoff);
243   for (int i = 0; i < ehdr->e_phnum; i++) {
244     Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
245     if (phdr.p_type == PT_LOAD) {
246       // Default alignment for PT_LOAD on x86-64 prevents elfhack from
247       // doing anything useful. However, the system doesn't actually
248       // require such a big alignment, so in order for elfhack to work
249       // efficiently, reduce alignment when it's originally the default
250       // one.
251       if ((ehdr->e_machine == EM_X86_64) && (phdr.p_align == 0x200000))
252         phdr.p_align = 0x1000;
253     }
254     ElfSegment* segment = new ElfSegment(&phdr);
255     // Some segments aren't entirely filled (if at all) by sections
256     // For those, we use fake sections
257     if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) {
258       // Use a fake section for ehdr and phdr
259       ehdr->getShdr().sh_addr = phdr.p_vaddr;
260       if (!adjusted_phdr_section) {
261         phdr_section->getShdr().sh_addr += phdr.p_vaddr;
262         adjusted_phdr_section = true;
263       }
264       segment->addSection(ehdr);
265       segment->addSection(phdr_section);
266     }
267     if (phdr.p_type == PT_PHDR) {
268       if (!adjusted_phdr_section) {
269         phdr_section->getShdr().sh_addr = phdr.p_vaddr;
270         adjusted_phdr_section = true;
271       }
272       segment->addSection(phdr_section);
273     }
274     for (int j = 1; j < ehdr->e_shnum; j++)
275       if (phdr.contains(sections[j])) segment->addSection(sections[j]);
276     // Make sure that our view of segments corresponds to the original
277     // ELF file.
278     // GNU gold likes to start some segments before the first section
279     // they contain. https://sourceware.org/bugzilla/show_bug.cgi?id=19392
280     unsigned int gold_adjustment = segment->getAddr() - phdr.p_vaddr;
281     assert(segment->getFileSize() == phdr.p_filesz - gold_adjustment);
282     // gold makes TLS segments end on an aligned virtual address, even
283     // when the underlying section ends before that, while bfd ld
284     // doesn't. It's fine if we don't keep that alignment.
285     unsigned int memsize = segment->getMemSize();
286     if (phdr.p_type == PT_TLS && memsize != phdr.p_memsz) {
287       unsigned int align = segment->getAlign();
288       memsize = (memsize + align - 1) & ~(align - 1);
289     }
290     assert(memsize == phdr.p_memsz - gold_adjustment);
291     segments.push_back(segment);
292   }
293 
294   new (&eh_entry) ElfLocation(ehdr->e_entry, this);
295 }
296 
~Elf()297 Elf::~Elf() {
298   for (std::vector<ElfSegment*>::iterator seg = segments.begin();
299        seg != segments.end(); seg++)
300     delete *seg;
301   delete[] sections;
302   ElfSection* section = ehdr;
303   while (section != nullptr) {
304     ElfSection* next = section->getNext();
305     delete section;
306     section = next;
307   }
308 }
309 
310 // TODO: This shouldn't fail after inserting sections
getSection(int index)311 ElfSection* Elf::getSection(int index) {
312   if ((index < -1) || (index >= ehdr->e_shnum))
313     throw std::runtime_error("Section index out of bounds");
314   if (index == -1)
315     index = ehdr->e_shstrndx;  // TODO: should be fixed to use the actual
316                                // current number
317   // Special case: the section at index 0 is void
318   if (index == 0) return nullptr;
319   // Infinite recursion guard
320   if (sections[index] == (ElfSection*)this) return nullptr;
321   if (sections[index] == nullptr) {
322     sections[index] = (ElfSection*)this;
323     switch (tmp_shdr[index]->sh_type) {
324       case SHT_DYNAMIC:
325         sections[index] =
326             new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this);
327         break;
328       case SHT_REL:
329         sections[index] =
330             new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this);
331         break;
332       case SHT_RELA:
333         sections[index] =
334             new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this);
335         break;
336       case SHT_DYNSYM:
337       case SHT_SYMTAB:
338         sections[index] =
339             new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this);
340         break;
341       case SHT_STRTAB:
342         sections[index] =
343             new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this);
344         break;
345       default:
346         sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this);
347     }
348   }
349   return sections[index];
350 }
351 
getSectionAt(unsigned int offset)352 ElfSection* Elf::getSectionAt(unsigned int offset) {
353   for (int i = 1; i < ehdr->e_shnum; i++) {
354     ElfSection* section = getSection(i);
355     if ((section != nullptr) && (section->getFlags() & SHF_ALLOC) &&
356         !(section->getFlags() & SHF_TLS) && (offset >= section->getAddr()) &&
357         (offset < section->getAddr() + section->getSize()))
358       return section;
359   }
360   return nullptr;
361 }
362 
getSegmentByType(unsigned int type,ElfSegment * last)363 ElfSegment* Elf::getSegmentByType(unsigned int type, ElfSegment* last) {
364   std::vector<ElfSegment*>::iterator seg;
365   if (last) {
366     seg = std::find(segments.begin(), segments.end(), last);
367     ++seg;
368   } else
369     seg = segments.begin();
370   for (; seg != segments.end(); seg++)
371     if ((*seg)->getType() == type) return *seg;
372   return nullptr;
373 }
374 
removeSegment(ElfSegment * segment)375 void Elf::removeSegment(ElfSegment* segment) {
376   if (!segment) return;
377   std::vector<ElfSegment*>::iterator seg;
378   seg = std::find(segments.begin(), segments.end(), segment);
379   if (seg == segments.end()) return;
380   segment->clear();
381   segments.erase(seg);
382 }
383 
getDynSection()384 ElfDynamic_Section* Elf::getDynSection() {
385   for (std::vector<ElfSegment*>::iterator seg = segments.begin();
386        seg != segments.end(); seg++)
387     if (((*seg)->getType() == PT_DYNAMIC) &&
388         ((*seg)->getFirstSection() != nullptr) &&
389         (*seg)->getFirstSection()->getType() == SHT_DYNAMIC)
390       return (ElfDynamic_Section*)(*seg)->getFirstSection();
391 
392   return nullptr;
393 }
394 
normalize()395 void Elf::normalize() {
396   // fixup section headers sh_name; TODO: that should be done by sections
397   // themselves
398   for (ElfSection* section = ehdr; section != nullptr;
399        section = section->getNext()) {
400     if (section->getIndex() == 0)
401       continue;
402     else
403       ehdr->e_shnum = section->getIndex() + 1;
404     section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
405   }
406   ehdr->markDirty();
407   // Check segments consistency
408   int i = 0;
409   for (std::vector<ElfSegment*>::iterator seg = segments.begin();
410        seg != segments.end(); seg++, i++) {
411     std::list<ElfSection*>::iterator it = (*seg)->begin();
412     for (ElfSection* last = *(it++); it != (*seg)->end(); last = *(it++)) {
413       if (((*it)->getType() != SHT_NOBITS) &&
414           ((*it)->getAddr() - last->getAddr()) !=
415               ((*it)->getOffset() - last->getOffset())) {
416         throw std::runtime_error("Segments inconsistency");
417       }
418     }
419   }
420 
421   ElfSegment* prevLoad = nullptr;
422   for (auto& it : segments) {
423     if (it->getType() == PT_LOAD) {
424       if (prevLoad) {
425         size_t alignedPrevEnd = (prevLoad->getAddr() + prevLoad->getMemSize() +
426                                  prevLoad->getAlign() - 1) &
427                                 ~(prevLoad->getAlign() - 1);
428         size_t alignedStart = it->getAddr() & ~(it->getAlign() - 1);
429         if (alignedPrevEnd > alignedStart) {
430           throw std::runtime_error("Segments overlap");
431         }
432       }
433       prevLoad = it;
434     }
435   }
436 
437   // fixup ehdr before writing
438   if (ehdr->e_phnum != segments.size()) {
439     ehdr->e_phnum = segments.size();
440     phdr_section->getShdr().sh_size =
441         segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]);
442     phdr_section->getNext()->markDirty();
443   }
444   // fixup shdr before writing
445   if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize())
446     shdr_section->getShdr().sh_size =
447         ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]);
448   ehdr->e_shoff = shdr_section->getOffset();
449   ehdr->e_entry = eh_entry.getValue();
450   ehdr->e_shstrndx = eh_shstrndx->getIndex();
451 
452   // Check sections consistency
453   unsigned int minOffset = 0;
454   for (ElfSection* section = ehdr; section != nullptr;
455        section = section->getNext()) {
456     unsigned int offset = section->getOffset();
457     if (offset < minOffset) {
458       throw std::runtime_error("Sections overlap");
459     }
460     if (section->getType() != SHT_NOBITS) {
461       minOffset = offset + section->getSize();
462     }
463   }
464 }
465 
write(std::ofstream & file)466 void Elf::write(std::ofstream& file) {
467   normalize();
468   for (ElfSection* section = ehdr; section != nullptr;
469        section = section->getNext()) {
470     file.seekp(section->getOffset());
471     if (section == phdr_section) {
472       for (std::vector<ElfSegment*>::iterator seg = segments.begin();
473            seg != segments.end(); seg++) {
474         Elf_Phdr phdr;
475         phdr.p_type = (*seg)->getType();
476         phdr.p_flags = (*seg)->getFlags();
477         phdr.p_offset = (*seg)->getOffset();
478         phdr.p_vaddr = (*seg)->getAddr();
479         phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff();
480         phdr.p_filesz = (*seg)->getFileSize();
481         phdr.p_memsz = (*seg)->getMemSize();
482         phdr.p_align = (*seg)->getAlign();
483         phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
484       }
485     } else if (section == shdr_section) {
486       null_section.serialize(file, ehdr->e_ident[EI_CLASS],
487                              ehdr->e_ident[EI_DATA]);
488       for (ElfSection* sec = ehdr; sec != nullptr; sec = sec->getNext()) {
489         if (sec->getType() != SHT_NULL)
490           sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS],
491                                    ehdr->e_ident[EI_DATA]);
492       }
493     } else
494       section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
495   }
496 }
497 
ElfSection(Elf_Shdr & s,std::ifstream * file,Elf * parent)498 ElfSection::ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent)
499     : shdr(s),
500       link(shdr.sh_link == SHN_UNDEF ? nullptr
501                                      : parent->getSection(shdr.sh_link)),
502       next(nullptr),
503       previous(nullptr),
504       index(-1) {
505   if ((file == nullptr) || (shdr.sh_type == SHT_NULL) ||
506       (shdr.sh_type == SHT_NOBITS))
507     data = nullptr;
508   else {
509     data = static_cast<char*>(malloc(shdr.sh_size));
510     if (!data) {
511       throw std::runtime_error("Could not malloc ElfSection data");
512     }
513     auto pos = file->tellg();
514     file->seekg(shdr.sh_offset);
515     file->read(data, shdr.sh_size);
516     file->seekg(pos);
517   }
518   if (shdr.sh_name == 0)
519     name = nullptr;
520   else {
521     ElfStrtab_Section* strtab = (ElfStrtab_Section*)parent->getSection(-1);
522     // Special case (see elfgeneric.cpp): if strtab is nullptr, the
523     // section being created is the strtab.
524     if (strtab == nullptr)
525       name = &data[shdr.sh_name];
526     else
527       name = strtab->getStr(shdr.sh_name);
528   }
529   // Only SHT_REL/SHT_RELA sections use sh_info to store a section
530   // number.
531   if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA))
532     info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : nullptr;
533   else
534     info.index = shdr.sh_info;
535 }
536 
getAddr()537 unsigned int ElfSection::getAddr() {
538   if (shdr.sh_addr != (Elf64_Addr)-1) return shdr.sh_addr;
539 
540   // It should be safe to adjust sh_addr for all allocated sections that
541   // are neither SHT_NOBITS nor SHT_PROGBITS
542   if ((previous != nullptr) && isRelocatable()) {
543     unsigned int addr = previous->getAddr();
544     if (previous->getType() != SHT_NOBITS) addr += previous->getSize();
545 
546     if (addr & (getAddrAlign() - 1)) addr = (addr | (getAddrAlign() - 1)) + 1;
547 
548     return (shdr.sh_addr = addr);
549   }
550   return shdr.sh_addr;
551 }
552 
getOffset()553 unsigned int ElfSection::getOffset() {
554   if (shdr.sh_offset != (Elf64_Off)-1) return shdr.sh_offset;
555 
556   if (previous == nullptr) return (shdr.sh_offset = 0);
557 
558   unsigned int offset = previous->getOffset();
559 
560   ElfSegment* ptload = getSegmentByType(PT_LOAD);
561   ElfSegment* prev_ptload = previous->getSegmentByType(PT_LOAD);
562 
563   if (ptload && (ptload == prev_ptload)) {
564     offset += getAddr() - previous->getAddr();
565     return (shdr.sh_offset = offset);
566   }
567 
568   if (previous->getType() != SHT_NOBITS) offset += previous->getSize();
569 
570   Elf32_Word align = 0x1000;
571   for (std::vector<ElfSegment*>::iterator seg = segments.begin();
572        seg != segments.end(); seg++)
573     align = std::max(align, (*seg)->getAlign());
574 
575   Elf32_Word mask = align - 1;
576   // SHF_TLS is used for .tbss which is some kind of special case.
577   if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) &&
578       (getFlags() & SHF_ALLOC)) {
579     if ((getAddr() & mask) < (offset & mask))
580       offset = (offset | mask) + (getAddr() & mask) + 1;
581     else
582       offset = (offset & ~mask) + (getAddr() & mask);
583   }
584   if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
585     offset = (offset | (getAddrAlign() - 1)) + 1;
586 
587   return (shdr.sh_offset = offset);
588 }
589 
getIndex()590 int ElfSection::getIndex() {
591   if (index != -1) return index;
592   if (getType() == SHT_NULL) return (index = 0);
593   ElfSection* reference;
594   for (reference = previous;
595        (reference != nullptr) && (reference->getType() == SHT_NULL);
596        reference = reference->getPrevious())
597     ;
598   if (reference == nullptr) return (index = 1);
599   return (index = reference->getIndex() + 1);
600 }
601 
getShdr()602 Elf_Shdr& ElfSection::getShdr() {
603   getOffset();
604   if (shdr.sh_link == (Elf64_Word)-1)
605     shdr.sh_link = getLink() ? getLink()->getIndex() : 0;
606   if (shdr.sh_info == (Elf64_Word)-1)
607     shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA))
608                        ? (getInfo().section ? getInfo().section->getIndex() : 0)
609                        : getInfo().index;
610 
611   return shdr;
612 }
613 
ElfSegment(Elf_Phdr * phdr)614 ElfSegment::ElfSegment(Elf_Phdr* phdr)
615     : type(phdr->p_type),
616       v_p_diff(phdr->p_paddr - phdr->p_vaddr),
617       flags(phdr->p_flags),
618       align(phdr->p_align),
619       vaddr(phdr->p_vaddr),
620       filesz(phdr->p_filesz),
621       memsz(phdr->p_memsz) {}
622 
addSection(ElfSection * section)623 void ElfSegment::addSection(ElfSection* section) {
624   // Make sure all sections in PT_GNU_RELRO won't be moved by elfhack
625   assert(!((type == PT_GNU_RELRO) && (section->isRelocatable())));
626 
627   // TODO: Check overlapping sections
628   std::list<ElfSection*>::iterator i;
629   for (i = sections.begin(); i != sections.end(); ++i)
630     if ((*i)->getAddr() > section->getAddr()) break;
631   sections.insert(i, section);
632   section->addToSegment(this);
633 }
634 
removeSection(ElfSection * section)635 void ElfSegment::removeSection(ElfSection* section) {
636   sections.remove(section);
637   section->removeFromSegment(this);
638 }
639 
getFileSize()640 unsigned int ElfSegment::getFileSize() {
641   if (type == PT_GNU_RELRO) return filesz;
642 
643   if (sections.empty()) return 0;
644   // Search the last section that is not SHT_NOBITS
645   std::list<ElfSection*>::reverse_iterator i;
646   for (i = sections.rbegin();
647        (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i)
648     ;
649   // All sections are SHT_NOBITS
650   if (i == sections.rend()) return 0;
651 
652   unsigned int end = (*i)->getAddr() + (*i)->getSize();
653 
654   return end - sections.front()->getAddr();
655 }
656 
getMemSize()657 unsigned int ElfSegment::getMemSize() {
658   if (type == PT_GNU_RELRO) return memsz;
659 
660   if (sections.empty()) return 0;
661 
662   unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
663 
664   return end - sections.front()->getAddr();
665 }
666 
getOffset()667 unsigned int ElfSegment::getOffset() {
668   if ((type == PT_GNU_RELRO) && !sections.empty() &&
669       (sections.front()->getAddr() != vaddr))
670     throw std::runtime_error(
671         "PT_GNU_RELRO segment doesn't start on a section start");
672 
673   return sections.empty() ? 0 : sections.front()->getOffset();
674 }
675 
getAddr()676 unsigned int ElfSegment::getAddr() {
677   if ((type == PT_GNU_RELRO) && !sections.empty() &&
678       (sections.front()->getAddr() != vaddr))
679     throw std::runtime_error(
680         "PT_GNU_RELRO segment doesn't start on a section start");
681 
682   return sections.empty() ? 0 : sections.front()->getAddr();
683 }
684 
clear()685 void ElfSegment::clear() {
686   for (std::list<ElfSection*>::iterator i = sections.begin();
687        i != sections.end(); ++i)
688     (*i)->removeFromSegment(this);
689   sections.clear();
690 }
691 
getValueForType(unsigned int tag)692 ElfValue* ElfDynamic_Section::getValueForType(unsigned int tag) {
693   for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
694     if (dyns[i].tag == tag) return dyns[i].value;
695 
696   return nullptr;
697 }
698 
getSectionForType(unsigned int tag)699 ElfSection* ElfDynamic_Section::getSectionForType(unsigned int tag) {
700   ElfValue* value = getValueForType(tag);
701   return value ? value->getSection() : nullptr;
702 }
703 
setValueForType(unsigned int tag,ElfValue * val)704 bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue* val) {
705   unsigned int i;
706   unsigned int shnum = shdr.sh_size / shdr.sh_entsize;
707   for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++)
708     if (dyns[i].tag == tag) {
709       delete dyns[i].value;
710       dyns[i].value = val;
711       return true;
712     }
713   // If we get here, this means we didn't match for the given tag
714   // Most of the time, there are a few DT_NULL entries, that we can
715   // use to add our value, but if we are on the last entry, we can't.
716   if (i >= shnum - 1) return false;
717 
718   dyns[i].tag = tag;
719   dyns[i].value = val;
720   return true;
721 }
722 
ElfDynamic_Section(Elf_Shdr & s,std::ifstream * file,Elf * parent)723 ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file,
724                                        Elf* parent)
725     : ElfSection(s, file, parent) {
726   auto pos = file->tellg();
727   dyns.resize(s.sh_size / s.sh_entsize);
728   file->seekg(shdr.sh_offset);
729   // Here we assume tags refer to only one section (e.g. DT_RELSZ accounts
730   // for .rel.dyn size)
731   for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
732     Elf_Dyn dyn(*file, parent->getClass(), parent->getData());
733     dyns[i].tag = dyn.d_tag;
734     switch (dyn.d_tag) {
735       case DT_NULL:
736       case DT_SYMBOLIC:
737       case DT_TEXTREL:
738       case DT_BIND_NOW:
739         dyns[i].value = new ElfValue();
740         break;
741       case DT_NEEDED:
742       case DT_SONAME:
743       case DT_RPATH:
744       case DT_PLTREL:
745       case DT_RUNPATH:
746       case DT_FLAGS:
747       case DT_RELACOUNT:
748       case DT_RELCOUNT:
749       case DT_VERDEFNUM:
750       case DT_VERNEEDNUM:
751         dyns[i].value = new ElfPlainValue(dyn.d_un.d_val);
752         break;
753       case DT_PLTGOT:
754       case DT_HASH:
755       case DT_STRTAB:
756       case DT_SYMTAB:
757       case DT_RELA:
758       case DT_INIT:
759       case DT_FINI:
760       case DT_REL:
761       case DT_JMPREL:
762       case DT_INIT_ARRAY:
763       case DT_FINI_ARRAY:
764       case DT_GNU_HASH:
765       case DT_VERSYM:
766       case DT_VERNEED:
767       case DT_VERDEF:
768         dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent);
769         break;
770       default:
771         dyns[i].value = nullptr;
772     }
773   }
774   // Another loop to get the section sizes
775   for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++)
776     switch (dyns[i].tag) {
777       case DT_PLTRELSZ:
778         dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL));
779         break;
780       case DT_RELASZ:
781         dyns[i].value = new ElfSize(getSectionForType(DT_RELA));
782         break;
783       case DT_STRSZ:
784         dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB));
785         break;
786       case DT_RELSZ:
787         dyns[i].value = new ElfSize(getSectionForType(DT_REL));
788         break;
789       case DT_INIT_ARRAYSZ:
790         dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY));
791         break;
792       case DT_FINI_ARRAYSZ:
793         dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY));
794         break;
795       case DT_RELAENT:
796         dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA));
797         break;
798       case DT_SYMENT:
799         dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB));
800         break;
801       case DT_RELENT:
802         dyns[i].value = new ElfEntSize(getSectionForType(DT_REL));
803         break;
804     }
805 
806   file->seekg(pos);
807 }
808 
~ElfDynamic_Section()809 ElfDynamic_Section::~ElfDynamic_Section() {
810   for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
811     delete dyns[i].value;
812 }
813 
serialize(std::ofstream & file,unsigned char ei_class,unsigned char ei_data)814 void ElfDynamic_Section::serialize(std::ofstream& file, unsigned char ei_class,
815                                    unsigned char ei_data) {
816   for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
817     Elf_Dyn dyn;
818     dyn.d_tag = dyns[i].tag;
819     dyn.d_un.d_val = (dyns[i].value != nullptr) ? dyns[i].value->getValue() : 0;
820     dyn.serialize(file, ei_class, ei_data);
821   }
822 }
823 
ElfSymtab_Section(Elf_Shdr & s,std::ifstream * file,Elf * parent)824 ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file,
825                                      Elf* parent)
826     : ElfSection(s, file, parent) {
827   auto pos = file->tellg();
828   syms.resize(s.sh_size / s.sh_entsize);
829   ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink();
830   file->seekg(shdr.sh_offset);
831   for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
832     Elf_Sym sym(*file, parent->getClass(), parent->getData());
833     syms[i].name = strtab->getStr(sym.st_name);
834     syms[i].info = sym.st_info;
835     syms[i].other = sym.st_other;
836     ElfSection* section =
837         (sym.st_shndx == SHN_ABS) ? nullptr : parent->getSection(sym.st_shndx);
838     new (&syms[i].value)
839         ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE);
840     syms[i].size = sym.st_size;
841     syms[i].defined = (sym.st_shndx != SHN_UNDEF);
842   }
843   file->seekg(pos);
844 }
845 
serialize(std::ofstream & file,unsigned char ei_class,unsigned char ei_data)846 void ElfSymtab_Section::serialize(std::ofstream& file, unsigned char ei_class,
847                                   unsigned char ei_data) {
848   ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink();
849   for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
850     Elf_Sym sym;
851     sym.st_name = strtab->getStrIndex(syms[i].name);
852     sym.st_info = syms[i].info;
853     sym.st_other = syms[i].other;
854     sym.st_value = syms[i].value.getValue();
855     ElfSection* section = syms[i].value.getSection();
856     if (syms[i].defined)
857       sym.st_shndx = section ? section->getIndex() : SHN_ABS;
858     else
859       sym.st_shndx = SHN_UNDEF;
860     sym.st_size = syms[i].size;
861     sym.serialize(file, ei_class, ei_data);
862   }
863 }
864 
lookup(const char * name,unsigned int type_filter)865 Elf_SymValue* ElfSymtab_Section::lookup(const char* name,
866                                         unsigned int type_filter) {
867   for (std::vector<Elf_SymValue>::iterator sym = syms.begin();
868        sym != syms.end(); sym++) {
869     if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) &&
870         (strcmp(sym->name, name) == 0)) {
871       return &*sym;
872     }
873   }
874   return nullptr;
875 }
876 
getStr(unsigned int index)877 const char* ElfStrtab_Section::getStr(unsigned int index) {
878   for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
879        t++) {
880     if (index < t->used) return t->buf + index;
881     index -= t->used;
882   }
883   assert(1 == 0);
884   return nullptr;
885 }
886 
getStr(const char * string)887 const char* ElfStrtab_Section::getStr(const char* string) {
888   if (string == nullptr) return nullptr;
889 
890   // If the given string is within the section, return it
891   for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
892        t++)
893     if ((string >= t->buf) && (string < t->buf + t->used)) return string;
894 
895   // TODO: should scan in the section to find an existing string
896 
897   // If not, we need to allocate the string in the section
898   size_t len = strlen(string) + 1;
899 
900   if (table.back().size - table.back().used < len)
901     table.resize(table.size() + 1);
902 
903   char* alloc_str = table.back().buf + table.back().used;
904   memcpy(alloc_str, string, len);
905   table.back().used += len;
906 
907   shdr.sh_size += len;
908   markDirty();
909 
910   return alloc_str;
911 }
912 
getStrIndex(const char * string)913 unsigned int ElfStrtab_Section::getStrIndex(const char* string) {
914   if (string == nullptr) return 0;
915 
916   unsigned int index = 0;
917   string = getStr(string);
918   for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
919        t++) {
920     if ((string >= t->buf) && (string < t->buf + t->used))
921       return index + (string - t->buf);
922     index += t->used;
923   }
924 
925   assert(1 == 0);
926   return 0;
927 }
928 
serialize(std::ofstream & file,unsigned char ei_class,unsigned char ei_data)929 void ElfStrtab_Section::serialize(std::ofstream& file, unsigned char ei_class,
930                                   unsigned char ei_data) {
931   file.seekp(getOffset());
932   for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
933        t++)
934     file.write(t->buf, t->used);
935 }
936