1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is elfhack.
16
* The Initial Developer of the Original Code is
18
* Portions created by the Initial Developer are Copyright (C) 2010
19
* the Initial Developer. All Rights Reserved.
22
* Mike Hommey <mh@glandium.org>
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
43
template <class endian, typename R, typename T>
44
inline void Elf_Ehdr_Traits::swap(T &t, R &r)
46
memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident));
47
r.e_type = endian::swap(t.e_type);
48
r.e_machine = endian::swap(t.e_machine);
49
r.e_version = endian::swap(t.e_version);
50
r.e_entry = endian::swap(t.e_entry);
51
r.e_phoff = endian::swap(t.e_phoff);
52
r.e_shoff = endian::swap(t.e_shoff);
53
r.e_flags = endian::swap(t.e_flags);
54
r.e_ehsize = endian::swap(t.e_ehsize);
55
r.e_phentsize = endian::swap(t.e_phentsize);
56
r.e_phnum = endian::swap(t.e_phnum);
57
r.e_shentsize = endian::swap(t.e_shentsize);
58
r.e_shnum = endian::swap(t.e_shnum);
59
r.e_shstrndx = endian::swap(t.e_shstrndx);
62
template <class endian, typename R, typename T>
63
inline void Elf_Phdr_Traits::swap(T &t, R &r)
65
r.p_type = endian::swap(t.p_type);
66
r.p_offset = endian::swap(t.p_offset);
67
r.p_vaddr = endian::swap(t.p_vaddr);
68
r.p_paddr = endian::swap(t.p_paddr);
69
r.p_filesz = endian::swap(t.p_filesz);
70
r.p_memsz = endian::swap(t.p_memsz);
71
r.p_flags = endian::swap(t.p_flags);
72
r.p_align = endian::swap(t.p_align);
75
template <class endian, typename R, typename T>
76
inline void Elf_Shdr_Traits::swap(T &t, R &r)
78
r.sh_name = endian::swap(t.sh_name);
79
r.sh_type = endian::swap(t.sh_type);
80
r.sh_flags = endian::swap(t.sh_flags);
81
r.sh_addr = endian::swap(t.sh_addr);
82
r.sh_offset = endian::swap(t.sh_offset);
83
r.sh_size = endian::swap(t.sh_size);
84
r.sh_link = endian::swap(t.sh_link);
85
r.sh_info = endian::swap(t.sh_info);
86
r.sh_addralign = endian::swap(t.sh_addralign);
87
r.sh_entsize = endian::swap(t.sh_entsize);
90
template <class endian, typename R, typename T>
91
inline void Elf_Dyn_Traits::swap(T &t, R &r)
93
r.d_tag = endian::swap(t.d_tag);
94
r.d_un.d_val = endian::swap(t.d_un.d_val);
97
template <class endian, typename R, typename T>
98
inline void Elf_Sym_Traits::swap(T &t, R &r)
100
r.st_name = endian::swap(t.st_name);
101
r.st_value = endian::swap(t.st_value);
102
r.st_size = endian::swap(t.st_size);
103
r.st_info = t.st_info;
104
r.st_other = t.st_other;
105
r.st_shndx = endian::swap(t.st_shndx);
108
template <class endian>
110
static inline void swap(Elf32_Word &t, Elf32_Word &r) { r = endian::swap(t); }
111
static inline void swap(Elf64_Xword &t, Elf64_Xword &r) { r = endian::swap(t); }
112
static inline void swap(Elf64_Xword &t, Elf32_Word &r) {
113
r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t)));
115
static inline void swap(Elf32_Word &t, Elf64_Xword &r) {
116
r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t)));
120
template <class endian, typename R, typename T>
121
inline void Elf_Rel_Traits::swap(T &t, R &r)
123
r.r_offset = endian::swap(t.r_offset);
124
_Rel_info<endian>::swap(t.r_info, r.r_info);
127
template <class endian, typename R, typename T>
128
inline void Elf_Rela_Traits::swap(T &t, R &r)
130
r.r_offset = endian::swap(t.r_offset);
131
_Rel_info<endian>::swap(t.r_info, r.r_info);
132
r.r_addend = endian::swap(t.r_addend);
135
static const Elf32_Shdr null32_section =
136
{ 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 };
138
Elf_Shdr null_section(null32_section);
140
Elf_Ehdr::Elf_Ehdr(std::ifstream &file, char ei_class, char ei_data)
141
: serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data),
142
ElfSection(null_section, NULL, NULL)
144
shdr.sh_size = Elf_Ehdr::size(ei_class);
147
Elf::Elf(std::ifstream &file)
150
throw std::runtime_error("Error opening file");
152
file.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit);
153
// Read ELF magic number and identification information
154
char e_ident[EI_VERSION];
156
file.read(e_ident, sizeof(e_ident));
158
ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
160
// ELFOSABI_LINUX is kept unsupported because I haven't looked whether
161
// STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing.
162
if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) && (ehdr->e_ident[EI_ABIVERSION] != 0))
163
throw std::runtime_error("unsupported ELF ABI");
165
if (ehdr->e_version != 1)
166
throw std::runtime_error("unsupported ELF version");
169
if (ehdr->e_shnum == 0)
170
throw std::runtime_error("sstripped ELF files aren't supported");
172
if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS]))
173
throw std::runtime_error("unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)");
175
if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS]))
176
throw std::runtime_error("unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)");
178
if (ehdr->e_phnum == 0) {
179
if (ehdr->e_phoff != 0)
180
throw std::runtime_error("unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0");
181
if (ehdr->e_phentsize != 0)
182
throw std::runtime_error("unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0");
183
} else if (ehdr->e_phoff != ehdr->e_ehsize)
184
throw std::runtime_error("unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize");
185
else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS]))
186
throw std::runtime_error("unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)");
188
// Read section headers
189
Elf_Shdr **shdr = new Elf_Shdr *[ehdr->e_shnum];
190
file.seekg(ehdr->e_shoff);
191
for (int i = 0; i < ehdr->e_shnum; i++)
192
shdr[i] = new Elf_Shdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
194
// Sanity check in section header for index 0
195
if ((shdr[0]->sh_name != 0) || (shdr[0]->sh_type != SHT_NULL) ||
196
(shdr[0]->sh_flags != 0) || (shdr[0]->sh_addr != 0) ||
197
(shdr[0]->sh_offset != 0) || (shdr[0]->sh_size != 0) ||
198
(shdr[0]->sh_link != SHN_UNDEF) || (shdr[0]->sh_info != 0) ||
199
(shdr[0]->sh_addralign != 0) || (shdr[0]->sh_entsize != 0))
200
throw std::runtime_error("Section header for index 0 contains unsupported values");
202
if ((shdr[ehdr->e_shstrndx]->sh_link != 0) || (shdr[ehdr->e_shstrndx]->sh_info != 0))
203
throw std::runtime_error("unsupported ELF content: string table with sh_link != 0 || sh_info != 0");
205
// Store these temporarily
209
// Fill sections list
210
sections = new ElfSection *[ehdr->e_shnum];
211
for (int i = 0; i < ehdr->e_shnum; i++)
213
for (int i = 1; i < ehdr->e_shnum; i++) {
214
if (sections[i] != NULL)
220
s.sh_type = SHT_NULL;
223
s.sh_offset = ehdr->e_shoff;
224
s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]);
225
s.sh_size = s.sh_entsize * ehdr->e_shnum;
228
s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8;
229
shdr_section = new ElfSection(s, NULL, NULL);
231
// Fake section for program headers
232
s.sh_offset = ehdr->e_phoff;
233
s.sh_addr = ehdr->e_phoff;
234
s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]);
235
s.sh_size = s.sh_entsize * ehdr->e_phnum;
236
phdr_section = new ElfSection(s, NULL, NULL);
238
phdr_section->insertAfter(ehdr, false);
240
sections[1]->insertAfter(phdr_section, false);
241
for (int i = 2; i < ehdr->e_shnum; i++) {
242
// TODO: this should be done in a better way
243
if ((shdr_section->getPrevious() == NULL) && (shdr[i]->sh_offset > ehdr->e_shoff)) {
244
shdr_section->insertAfter(sections[i - 1], false);
245
sections[i]->insertAfter(shdr_section, false);
247
sections[i]->insertAfter(sections[i - 1], false);
249
if (shdr_section->getPrevious() == NULL)
250
shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false);
254
for (int i = 0; i < ehdr->e_shnum; i++)
258
eh_shstrndx = (ElfStrtab_Section *)sections[ehdr->e_shstrndx];
260
// Skip reading program headers if there aren't any
261
if (ehdr->e_phnum == 0)
264
// Read program headers
265
file.seekg(ehdr->e_phoff);
266
for (int i = 0; i < ehdr->e_phnum; i++) {
267
Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
268
ElfSegment *segment = new ElfSegment(&phdr);
269
// Some segments aren't entirely filled (if at all) by sections
270
// For those, we use fake sections
271
if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) {
272
// Use a fake section for ehdr and phdr
273
ehdr->getShdr().sh_addr = phdr.p_vaddr;
274
phdr_section->getShdr().sh_addr += phdr.p_vaddr;
275
segment->addSection(ehdr);
276
segment->addSection(phdr_section);
278
if (phdr.p_type == PT_PHDR)
279
segment->addSection(phdr_section);
280
for (int j = 1; j < ehdr->e_shnum; j++)
281
if (phdr.contains(sections[j]))
282
segment->addSection(sections[j]);
283
// Make sure that our view of segments corresponds to the original
285
assert(segment->getFileSize() == phdr.p_filesz);
286
assert(segment->getMemSize() == phdr.p_memsz);
287
segments.push_back(segment);
290
new (&eh_entry) ElfLocation(ehdr->e_entry, this);
295
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
298
ElfSection *section = ehdr;
299
while (section != NULL) {
300
ElfSection *next = section->getNext();
306
// TODO: This shouldn't fail after inserting sections
307
ElfSection *Elf::getSection(int index)
309
if ((index < -1) || (index >= ehdr->e_shnum))
310
throw std::runtime_error("Section index out of bounds");
312
index = ehdr->e_shstrndx; // TODO: should be fixed to use the actual current number
313
// Special case: the section at index 0 is void
316
// Infinite recursion guard
317
if (sections[index] == (ElfSection *)this)
319
if (sections[index] == NULL) {
320
sections[index] = (ElfSection *)this;
321
switch (tmp_shdr[index]->sh_type) {
323
sections[index] = new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this);
326
sections[index] = new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this);
329
sections[index] = new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this);
333
sections[index] = new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this);
336
sections[index] = new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this);
339
sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this);
342
return sections[index];
345
ElfSection *Elf::getSectionAt(unsigned int offset)
347
for (int i = 1; i < ehdr->e_shnum; i++) {
348
ElfSection *section = getSection(i);
349
if ((section != NULL) && (section->getFlags() & SHF_ALLOC) && !(section->getFlags() & SHF_TLS) &&
350
(offset >= section->getAddr()) && (offset < section->getAddr() + section->getSize()))
356
ElfSegment *Elf::getSegmentByType(unsigned int type)
358
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
359
if ((*seg)->getType() == type)
364
ElfDynamic_Section *Elf::getDynSection()
366
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
367
if (((*seg)->getType() == PT_DYNAMIC) && ((*seg)->getFirstSection() != NULL) &&
368
(*seg)->getFirstSection()->getType() == SHT_DYNAMIC)
369
return (ElfDynamic_Section *)(*seg)->getFirstSection();
374
void Elf::write(std::ofstream &file)
376
// fixup section headers sh_name; TODO: that should be done by sections
378
for (ElfSection *section = ehdr; section != NULL; section = section->getNext()) {
379
if (section->getIndex() == 0)
382
ehdr->e_shnum = section->getIndex() + 1;
383
section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
386
// Adjust PT_LOAD segments
388
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++, i++) {
389
if ((*seg)->getType() == PT_LOAD) {
390
std::list<ElfSection *>::iterator it = (*seg)->begin();
391
for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
392
if (((*it)->getType() != SHT_NOBITS) &&
393
((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
394
std::vector<ElfSegment *>::iterator next = seg;
395
segments.insert(++next, (*seg)->splitBefore(*it));
396
seg = segments.begin() + i;
402
// fixup ehdr before writing
403
if (ehdr->e_phnum != segments.size()) {
404
ehdr->e_phnum = segments.size();
405
phdr_section->getShdr().sh_size = segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]);
406
phdr_section->getNext()->markDirty();
408
// fixup shdr before writing
409
if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize())
410
shdr_section->getShdr().sh_size = ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]);
411
ehdr->e_shoff = shdr_section->getOffset();
412
ehdr->e_entry = eh_entry.getValue();
413
ehdr->e_shstrndx = eh_shstrndx->getIndex();
414
for (ElfSection *section = ehdr;
415
section != NULL; section = section->getNext()) {
416
file.seekp(section->getOffset());
417
if (section == phdr_section) {
418
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++) {
420
phdr.p_type = (*seg)->getType();
421
phdr.p_flags = (*seg)->getFlags();
422
phdr.p_offset = (*seg)->getOffset();
423
phdr.p_vaddr = (*seg)->getAddr();
424
phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff();
425
phdr.p_filesz = (*seg)->getFileSize();
426
phdr.p_memsz = (*seg)->getMemSize();
427
phdr.p_align = (*seg)->getAlign();
428
phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
430
} else if (section == shdr_section) {
431
null_section.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
432
for (ElfSection *sec = ehdr; sec!= NULL; sec = sec->getNext()) {
433
if (sec->getType() != SHT_NULL)
434
sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
437
section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
441
ElfSection::ElfSection(Elf_Shdr &s, std::ifstream *file, Elf *parent)
443
link(shdr.sh_link == SHN_UNDEF ? NULL : parent->getSection(shdr.sh_link)),
444
next(NULL), previous(NULL), index(-1)
446
if ((file == NULL) || (shdr.sh_type == SHT_NULL) || (shdr.sh_type == SHT_NOBITS))
449
data = new char[shdr.sh_size];
450
int pos = file->tellg();
451
file->seekg(shdr.sh_offset);
452
file->read(data, shdr.sh_size);
455
if (shdr.sh_name == 0)
458
ElfStrtab_Section *strtab = (ElfStrtab_Section *) parent->getSection(-1);
459
// Special case (see elfgeneric.cpp): if strtab is NULL, the
460
// section being created is the strtab.
462
name = &data[shdr.sh_name];
464
name = strtab->getStr(shdr.sh_name);
466
// Only SHT_REL/SHT_RELA sections use sh_info to store a section
468
if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA))
469
info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : NULL;
471
info.index = shdr.sh_info;
474
unsigned int ElfSection::getAddr()
476
if (shdr.sh_addr != (Elf32_Word)-1)
479
// It should be safe to adjust sh_addr for all allocated sections that
480
// are neither SHT_NOBITS nor SHT_PROGBITS
481
if ((previous != NULL) && isRelocatable()) {
482
unsigned int addr = previous->getAddr();
483
if (previous->getType() != SHT_NOBITS)
484
addr += previous->getSize();
486
if (addr & (getAddrAlign() - 1))
487
addr = (addr | (getAddrAlign() - 1)) + 1;
489
return (shdr.sh_addr = addr);
494
unsigned int ElfSection::getOffset()
496
if (shdr.sh_offset != (Elf32_Word)-1)
497
return shdr.sh_offset;
499
if (previous == NULL)
500
return (shdr.sh_offset = 0);
502
unsigned int offset = previous->getOffset();
503
if (previous->getType() != SHT_NOBITS)
504
offset += previous->getSize();
506
// SHF_TLS is used for .tbss which is some kind of special case.
507
if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) && (getFlags() & SHF_ALLOC)) {
508
if ((getAddr() & 4095) < (offset & 4095))
509
offset = (offset | 4095) + (getAddr() & 4095) + 1;
511
offset = (offset & ~4095) + (getAddr() & 4095);
513
if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
514
offset = (offset | (getAddrAlign() - 1)) + 1;
516
// Two subsequent sections can't be mapped in the same page in memory
517
// if they aren't in the same 4K block on disk.
518
if ((getType() != SHT_NOBITS) && getAddr()) {
519
if (((offset >> 12) != (previous->getOffset() >> 12)) &&
520
((getAddr() >> 12) == (previous->getAddr() >> 12)))
521
throw std::runtime_error("Moving section would require overlapping segments");
524
return (shdr.sh_offset = offset);
527
int ElfSection::getIndex()
531
if (getType() == SHT_NULL)
533
ElfSection *reference;
534
for (reference = previous; (reference != NULL) && (reference->getType() == SHT_NULL); reference = reference->getPrevious());
535
if (reference == NULL)
537
return (index = reference->getIndex() + 1);
540
Elf_Shdr &ElfSection::getShdr()
543
if (shdr.sh_link == (Elf32_Word)-1)
544
shdr.sh_link = getLink() ? getLink()->getIndex() : 0;
545
if (shdr.sh_info == (Elf32_Word)-1)
546
shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA)) ?
547
(getInfo().section ? getInfo().section->getIndex() : 0) :
553
ElfSegment::ElfSegment(Elf_Phdr *phdr)
554
: type(phdr->p_type), v_p_diff(phdr->p_paddr - phdr->p_vaddr),
555
flags(phdr->p_flags), align(phdr->p_align), vaddr(phdr->p_vaddr),
556
filesz(phdr->p_filesz), memsz(phdr->p_memsz) {}
558
void ElfSegment::addSection(ElfSection *section)
560
// Make sure all sections in PT_GNU_RELRO won't be moved by elfhack
561
assert(!((type == PT_GNU_RELRO) && (section->isRelocatable())));
563
//TODO: Check overlapping sections
564
std::list<ElfSection *>::iterator i;
565
for (i = sections.begin(); i != sections.end(); ++i)
566
if ((*i)->getAddr() > section->getAddr())
568
sections.insert(i, section);
571
unsigned int ElfSegment::getFileSize()
573
if (type == PT_GNU_RELRO)
576
if (sections.empty())
578
// Search the last section that is not SHT_NOBITS
579
std::list<ElfSection *>::reverse_iterator i;
580
for (i = sections.rbegin(); (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i);
581
// All sections are SHT_NOBITS
582
if (i == sections.rend())
585
unsigned int end = (*i)->getAddr() + (*i)->getSize();
587
return end - sections.front()->getAddr();
590
unsigned int ElfSegment::getMemSize()
592
if (type == PT_GNU_RELRO)
595
if (sections.empty())
598
unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
600
return end - sections.front()->getAddr();
603
unsigned int ElfSegment::getOffset()
605
if ((type == PT_GNU_RELRO) && !sections.empty() &&
606
(sections.front()->getAddr() != vaddr))
607
throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
609
return sections.empty() ? 0 : sections.front()->getOffset();
612
unsigned int ElfSegment::getAddr()
614
if ((type == PT_GNU_RELRO) && !sections.empty() &&
615
(sections.front()->getAddr() != vaddr))
616
throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
618
return sections.empty() ? 0 : sections.front()->getAddr();
621
ElfSegment *ElfSegment::splitBefore(ElfSection *section)
623
std::list<ElfSection *>::iterator i, rm;
624
for (i = sections.begin(); (*i != section) && (i != sections.end()); ++i);
625
if (i == sections.end())
628
// Probably very wrong.
632
phdr.p_paddr = phdr.p_vaddr + v_p_diff;
633
phdr.p_flags = flags;
634
phdr.p_align = 0x1000;
635
phdr.p_filesz = (unsigned int)-1;
636
phdr.p_memsz = (unsigned int)-1;
637
ElfSegment *segment = new ElfSegment(&phdr);
639
for (rm = i; i != sections.end(); ++i)
640
segment->addSection(*i);
641
sections.erase(rm, sections.end());
646
ElfValue *ElfDynamic_Section::getValueForType(unsigned int tag)
648
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
649
if (dyns[i].tag == tag)
650
return dyns[i].value;
655
ElfSection *ElfDynamic_Section::getSectionForType(unsigned int tag)
657
ElfValue *value = getValueForType(tag);
658
return value ? value->getSection() : NULL;
661
void ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
664
for (i = 0; (i < shdr.sh_size / shdr.sh_entsize) && (dyns[i].tag != DT_NULL); i++)
665
if (dyns[i].tag == tag) {
666
delete dyns[i].value;
670
// This should never happen, as the last entry is always tagged DT_NULL
671
assert(i < shdr.sh_size / shdr.sh_entsize);
672
// If we get here, this means we didn't match for the given tag
674
dyns[i++].value = val;
676
// If we were on the last entry, we need to grow the section.
677
// Most of the time, though, there are a few DT_NULL entries.
678
if (i < shdr.sh_size / shdr.sh_entsize)
684
dyns.push_back(value);
685
// Resize the section accordingly
686
shdr.sh_size += shdr.sh_entsize;
687
if (getNext() != NULL)
688
getNext()->markDirty();
691
ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
692
: ElfSection(s, file, parent)
694
int pos = file->tellg();
695
dyns.resize(s.sh_size / s.sh_entsize);
696
file->seekg(shdr.sh_offset);
697
// Here we assume tags refer to only one section (e.g. DT_RELSZ accounts
698
// for .rel.dyn size)
699
for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
700
Elf_Dyn dyn(*file, parent->getClass(), parent->getData());
701
dyns[i].tag = dyn.d_tag;
707
dyns[i].value = new ElfValue();
719
dyns[i].value = new ElfPlainValue(dyn.d_un.d_val);
736
dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent);
739
dyns[i].value = NULL;
742
// Another loop to get the section sizes
743
for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++)
744
switch (dyns[i].tag) {
746
dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL));
749
dyns[i].value = new ElfSize(getSectionForType(DT_RELA));
752
dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB));
755
dyns[i].value = new ElfSize(getSectionForType(DT_REL));
757
case DT_INIT_ARRAYSZ:
758
dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY));
760
case DT_FINI_ARRAYSZ:
761
dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY));
764
dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA));
767
dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB));
770
dyns[i].value = new ElfEntSize(getSectionForType(DT_REL));
777
ElfDynamic_Section::~ElfDynamic_Section()
779
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
780
delete dyns[i].value;
783
void ElfDynamic_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
785
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
787
dyn.d_tag = dyns[i].tag;
788
dyn.d_un.d_val = (dyns[i].value != NULL) ? dyns[i].value->getValue() : 0;
789
dyn.serialize(file, ei_class, ei_data);
793
ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
794
: ElfSection(s, file, parent)
796
int pos = file->tellg();
797
syms.resize(s.sh_size / s.sh_entsize);
798
ElfStrtab_Section *strtab = (ElfStrtab_Section *)getLink();
799
file->seekg(shdr.sh_offset);
800
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
801
Elf_Sym sym(*file, parent->getClass(), parent->getData());
802
syms[i].name = strtab->getStr(sym.st_name);
803
syms[i].info = sym.st_info;
804
syms[i].other = sym.st_other;
805
ElfSection *section = (sym.st_shndx == SHN_ABS) ? NULL : parent->getSection(sym.st_shndx);
806
new (&syms[i].value) ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE);
807
syms[i].size = sym.st_size;
808
syms[i].defined = (sym.st_shndx != SHN_UNDEF);
814
ElfSymtab_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
816
ElfStrtab_Section *strtab = (ElfStrtab_Section *)getLink();
817
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
819
sym.st_name = strtab->getStrIndex(syms[i].name);
820
sym.st_info = syms[i].info;
821
sym.st_other = syms[i].other;
822
sym.st_value = syms[i].value.getValue();
823
ElfSection *section = syms[i].value.getSection();
825
sym.st_shndx = section ? section->getIndex() : SHN_ABS;
827
sym.st_shndx = SHN_UNDEF;
828
sym.st_size = syms[i].size;
829
sym.serialize(file, ei_class, ei_data);
834
ElfStrtab_Section::getStr(unsigned int index)
836
for (std::vector<table_storage>::iterator t = table.begin();
837
t != table.end(); t++) {
839
return t->buf + index;
847
ElfStrtab_Section::getStr(const char *string)
852
// If the given string is within the section, return it
853
for (std::vector<table_storage>::iterator t = table.begin();
854
t != table.end(); t++)
855
if ((string >= t->buf) && (string < t->buf + t->used))
858
// TODO: should scan in the section to find an existing string
860
// If not, we need to allocate the string in the section
861
size_t len = strlen(string) + 1;
863
if (table.back().size - table.back().used < len)
864
table.resize(table.size() + 1);
866
char *alloc_str = table.back().buf + table.back().used;
867
memcpy(alloc_str, string, len);
868
table.back().used += len;
877
ElfStrtab_Section::getStrIndex(const char *string)
882
unsigned int index = 0;
883
string = getStr(string);
884
for (std::vector<table_storage>::iterator t = table.begin();
885
t != table.end(); t++) {
886
if ((string >= t->buf) && (string < t->buf + t->used))
887
return index + (string - t->buf);
896
ElfStrtab_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
898
file.seekp(getOffset());
899
for (std::vector<table_storage>::iterator t = table.begin();
900
t != table.end(); t++)
901
file.write(t->buf, t->used);