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/. */
10
template <class endian, typename R, typename T>
11
void Elf_Ehdr_Traits::swap(T &t, R &r)
13
memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident));
14
r.e_type = endian::swap(t.e_type);
15
r.e_machine = endian::swap(t.e_machine);
16
r.e_version = endian::swap(t.e_version);
17
r.e_entry = endian::swap(t.e_entry);
18
r.e_phoff = endian::swap(t.e_phoff);
19
r.e_shoff = endian::swap(t.e_shoff);
20
r.e_flags = endian::swap(t.e_flags);
21
r.e_ehsize = endian::swap(t.e_ehsize);
22
r.e_phentsize = endian::swap(t.e_phentsize);
23
r.e_phnum = endian::swap(t.e_phnum);
24
r.e_shentsize = endian::swap(t.e_shentsize);
25
r.e_shnum = endian::swap(t.e_shnum);
26
r.e_shstrndx = endian::swap(t.e_shstrndx);
29
template <class endian, typename R, typename T>
30
void Elf_Phdr_Traits::swap(T &t, R &r)
32
r.p_type = endian::swap(t.p_type);
33
r.p_offset = endian::swap(t.p_offset);
34
r.p_vaddr = endian::swap(t.p_vaddr);
35
r.p_paddr = endian::swap(t.p_paddr);
36
r.p_filesz = endian::swap(t.p_filesz);
37
r.p_memsz = endian::swap(t.p_memsz);
38
r.p_flags = endian::swap(t.p_flags);
39
r.p_align = endian::swap(t.p_align);
42
template <class endian, typename R, typename T>
43
void Elf_Shdr_Traits::swap(T &t, R &r)
45
r.sh_name = endian::swap(t.sh_name);
46
r.sh_type = endian::swap(t.sh_type);
47
r.sh_flags = endian::swap(t.sh_flags);
48
r.sh_addr = endian::swap(t.sh_addr);
49
r.sh_offset = endian::swap(t.sh_offset);
50
r.sh_size = endian::swap(t.sh_size);
51
r.sh_link = endian::swap(t.sh_link);
52
r.sh_info = endian::swap(t.sh_info);
53
r.sh_addralign = endian::swap(t.sh_addralign);
54
r.sh_entsize = endian::swap(t.sh_entsize);
57
template <class endian, typename R, typename T>
58
void Elf_Dyn_Traits::swap(T &t, R &r)
60
r.d_tag = endian::swap(t.d_tag);
61
r.d_un.d_val = endian::swap(t.d_un.d_val);
64
template <class endian, typename R, typename T>
65
void Elf_Sym_Traits::swap(T &t, R &r)
67
r.st_name = endian::swap(t.st_name);
68
r.st_value = endian::swap(t.st_value);
69
r.st_size = endian::swap(t.st_size);
70
r.st_info = t.st_info;
71
r.st_other = t.st_other;
72
r.st_shndx = endian::swap(t.st_shndx);
75
template <class endian>
77
static inline void swap(Elf32_Word &t, Elf32_Word &r) { r = endian::swap(t); }
78
static inline void swap(Elf64_Xword &t, Elf64_Xword &r) { r = endian::swap(t); }
79
static inline void swap(Elf64_Xword &t, Elf32_Word &r) {
80
r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t)));
82
static inline void swap(Elf32_Word &t, Elf64_Xword &r) {
83
r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t)));
87
template <class endian, typename R, typename T>
88
void Elf_Rel_Traits::swap(T &t, R &r)
90
r.r_offset = endian::swap(t.r_offset);
91
_Rel_info<endian>::swap(t.r_info, r.r_info);
94
template <class endian, typename R, typename T>
95
void Elf_Rela_Traits::swap(T &t, R &r)
97
r.r_offset = endian::swap(t.r_offset);
98
_Rel_info<endian>::swap(t.r_info, r.r_info);
99
r.r_addend = endian::swap(t.r_addend);
102
static const Elf32_Shdr null32_section =
103
{ 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 };
105
Elf_Shdr null_section(null32_section);
107
Elf_Ehdr::Elf_Ehdr(std::ifstream &file, char ei_class, char ei_data)
108
: serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data),
109
ElfSection(null_section, NULL, NULL)
111
shdr.sh_size = Elf_Ehdr::size(ei_class);
114
Elf::Elf(std::ifstream &file)
117
throw std::runtime_error("Error opening file");
119
file.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit);
120
// Read ELF magic number and identification information
121
char e_ident[EI_VERSION];
123
file.read(e_ident, sizeof(e_ident));
125
ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
127
// ELFOSABI_LINUX is kept unsupported because I haven't looked whether
128
// STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing.
129
if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) && (ehdr->e_ident[EI_ABIVERSION] != 0))
130
throw std::runtime_error("unsupported ELF ABI");
132
if (ehdr->e_version != 1)
133
throw std::runtime_error("unsupported ELF version");
136
if (ehdr->e_shnum == 0)
137
throw std::runtime_error("sstripped ELF files aren't supported");
139
if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS]))
140
throw std::runtime_error("unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)");
142
if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS]))
143
throw std::runtime_error("unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)");
145
if (ehdr->e_phnum == 0) {
146
if (ehdr->e_phoff != 0)
147
throw std::runtime_error("unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0");
148
if (ehdr->e_phentsize != 0)
149
throw std::runtime_error("unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0");
150
} else if (ehdr->e_phoff != ehdr->e_ehsize)
151
throw std::runtime_error("unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize");
152
else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS]))
153
throw std::runtime_error("unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)");
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]);
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("Section header for index 0 contains unsupported values");
169
if ((shdr[ehdr->e_shstrndx]->sh_link != 0) || (shdr[ehdr->e_shstrndx]->sh_info != 0))
170
throw std::runtime_error("unsupported ELF content: string table with sh_link != 0 || sh_info != 0");
172
// Store these temporarily
176
// Fill sections list
177
sections = new ElfSection *[ehdr->e_shnum];
178
for (int i = 0; i < ehdr->e_shnum; i++)
180
for (int i = 1; i < ehdr->e_shnum; i++) {
181
if (sections[i] != NULL)
187
s.sh_type = SHT_NULL;
190
s.sh_offset = ehdr->e_shoff;
191
s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]);
192
s.sh_size = s.sh_entsize * ehdr->e_shnum;
195
s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8;
196
shdr_section = new ElfSection(s, NULL, NULL);
198
// Fake section for program headers
199
s.sh_offset = ehdr->e_phoff;
200
s.sh_addr = ehdr->e_phoff;
201
s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]);
202
s.sh_size = s.sh_entsize * ehdr->e_phnum;
203
phdr_section = new ElfSection(s, NULL, NULL);
205
phdr_section->insertAfter(ehdr, false);
207
sections[1]->insertAfter(phdr_section, false);
208
for (int i = 2; i < ehdr->e_shnum; i++) {
209
// TODO: this should be done in a better way
210
if ((shdr_section->getPrevious() == NULL) && (shdr[i]->sh_offset > ehdr->e_shoff)) {
211
shdr_section->insertAfter(sections[i - 1], false);
212
sections[i]->insertAfter(shdr_section, false);
214
sections[i]->insertAfter(sections[i - 1], false);
216
if (shdr_section->getPrevious() == NULL)
217
shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false);
221
for (int i = 0; i < ehdr->e_shnum; i++)
225
eh_shstrndx = (ElfStrtab_Section *)sections[ehdr->e_shstrndx];
227
// Skip reading program headers if there aren't any
228
if (ehdr->e_phnum == 0)
231
// Read program headers
232
file.seekg(ehdr->e_phoff);
233
for (int i = 0; i < ehdr->e_phnum; i++) {
234
Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
235
if (phdr.p_type == PT_LOAD) {
236
// Default alignment for PT_LOAD on x86-64 prevents elfhack from
237
// doing anything useful. However, the system doesn't actually
238
// require such a big alignment, so in order for elfhack to work
239
// efficiently, reduce alignment when it's originally the default
241
if ((ehdr->e_machine == EM_X86_64) && (phdr.p_align == 0x200000))
242
phdr.p_align = 0x1000;
244
ElfSegment *segment = new ElfSegment(&phdr);
245
// Some segments aren't entirely filled (if at all) by sections
246
// For those, we use fake sections
247
if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) {
248
// Use a fake section for ehdr and phdr
249
ehdr->getShdr().sh_addr = phdr.p_vaddr;
250
phdr_section->getShdr().sh_addr += phdr.p_vaddr;
251
segment->addSection(ehdr);
252
segment->addSection(phdr_section);
254
if (phdr.p_type == PT_PHDR)
255
segment->addSection(phdr_section);
256
for (int j = 1; j < ehdr->e_shnum; j++)
257
if (phdr.contains(sections[j]))
258
segment->addSection(sections[j]);
259
// Make sure that our view of segments corresponds to the original
261
assert(segment->getFileSize() == phdr.p_filesz);
262
assert(segment->getMemSize() == phdr.p_memsz);
263
segments.push_back(segment);
266
new (&eh_entry) ElfLocation(ehdr->e_entry, this);
271
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
274
ElfSection *section = ehdr;
275
while (section != NULL) {
276
ElfSection *next = section->getNext();
282
// TODO: This shouldn't fail after inserting sections
283
ElfSection *Elf::getSection(int index)
285
if ((index < -1) || (index >= ehdr->e_shnum))
286
throw std::runtime_error("Section index out of bounds");
288
index = ehdr->e_shstrndx; // TODO: should be fixed to use the actual current number
289
// Special case: the section at index 0 is void
292
// Infinite recursion guard
293
if (sections[index] == (ElfSection *)this)
295
if (sections[index] == NULL) {
296
sections[index] = (ElfSection *)this;
297
switch (tmp_shdr[index]->sh_type) {
299
sections[index] = new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this);
302
sections[index] = new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this);
305
sections[index] = new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this);
309
sections[index] = new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this);
312
sections[index] = new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this);
315
sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this);
318
return sections[index];
321
ElfSection *Elf::getSectionAt(unsigned int offset)
323
for (int i = 1; i < ehdr->e_shnum; i++) {
324
ElfSection *section = getSection(i);
325
if ((section != NULL) && (section->getFlags() & SHF_ALLOC) && !(section->getFlags() & SHF_TLS) &&
326
(offset >= section->getAddr()) && (offset < section->getAddr() + section->getSize()))
332
ElfSegment *Elf::getSegmentByType(unsigned int type)
334
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
335
if ((*seg)->getType() == type)
340
ElfDynamic_Section *Elf::getDynSection()
342
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
343
if (((*seg)->getType() == PT_DYNAMIC) && ((*seg)->getFirstSection() != NULL) &&
344
(*seg)->getFirstSection()->getType() == SHT_DYNAMIC)
345
return (ElfDynamic_Section *)(*seg)->getFirstSection();
350
void Elf::normalize()
352
// fixup section headers sh_name; TODO: that should be done by sections
354
for (ElfSection *section = ehdr; section != NULL; section = section->getNext()) {
355
if (section->getIndex() == 0)
358
ehdr->e_shnum = section->getIndex() + 1;
359
section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
362
// Adjust PT_LOAD segments
364
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++, i++) {
365
if ((*seg)->getType() == PT_LOAD) {
366
std::list<ElfSection *>::iterator it = (*seg)->begin();
367
for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
368
if (((*it)->getType() != SHT_NOBITS) &&
369
((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
370
std::vector<ElfSegment *>::iterator next = seg;
371
segments.insert(++next, (*seg)->splitBefore(*it));
372
seg = segments.begin() + i;
378
// fixup ehdr before writing
379
if (ehdr->e_phnum != segments.size()) {
380
ehdr->e_phnum = segments.size();
381
phdr_section->getShdr().sh_size = segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]);
382
phdr_section->getNext()->markDirty();
384
// fixup shdr before writing
385
if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize())
386
shdr_section->getShdr().sh_size = ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]);
387
ehdr->e_shoff = shdr_section->getOffset();
388
ehdr->e_entry = eh_entry.getValue();
389
ehdr->e_shstrndx = eh_shstrndx->getIndex();
392
void Elf::write(std::ofstream &file)
395
for (ElfSection *section = ehdr;
396
section != NULL; section = section->getNext()) {
397
file.seekp(section->getOffset());
398
if (section == phdr_section) {
399
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++) {
401
phdr.p_type = (*seg)->getType();
402
phdr.p_flags = (*seg)->getFlags();
403
phdr.p_offset = (*seg)->getOffset();
404
phdr.p_vaddr = (*seg)->getAddr();
405
phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff();
406
phdr.p_filesz = (*seg)->getFileSize();
407
phdr.p_memsz = (*seg)->getMemSize();
408
phdr.p_align = (*seg)->getAlign();
409
phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
411
} else if (section == shdr_section) {
412
null_section.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
413
for (ElfSection *sec = ehdr; sec!= NULL; sec = sec->getNext()) {
414
if (sec->getType() != SHT_NULL)
415
sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
418
section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
422
ElfSection::ElfSection(Elf_Shdr &s, std::ifstream *file, Elf *parent)
424
link(shdr.sh_link == SHN_UNDEF ? NULL : parent->getSection(shdr.sh_link)),
425
next(NULL), previous(NULL), index(-1)
427
if ((file == NULL) || (shdr.sh_type == SHT_NULL) || (shdr.sh_type == SHT_NOBITS))
430
data = new char[shdr.sh_size];
431
int pos = file->tellg();
432
file->seekg(shdr.sh_offset);
433
file->read(data, shdr.sh_size);
436
if (shdr.sh_name == 0)
439
ElfStrtab_Section *strtab = (ElfStrtab_Section *) parent->getSection(-1);
440
// Special case (see elfgeneric.cpp): if strtab is NULL, the
441
// section being created is the strtab.
443
name = &data[shdr.sh_name];
445
name = strtab->getStr(shdr.sh_name);
447
// Only SHT_REL/SHT_RELA sections use sh_info to store a section
449
if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA))
450
info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : NULL;
452
info.index = shdr.sh_info;
455
unsigned int ElfSection::getAddr()
457
if (shdr.sh_addr != (Elf32_Word)-1)
460
// It should be safe to adjust sh_addr for all allocated sections that
461
// are neither SHT_NOBITS nor SHT_PROGBITS
462
if ((previous != NULL) && isRelocatable()) {
463
unsigned int addr = previous->getAddr();
464
if (previous->getType() != SHT_NOBITS)
465
addr += previous->getSize();
467
if (addr & (getAddrAlign() - 1))
468
addr = (addr | (getAddrAlign() - 1)) + 1;
470
return (shdr.sh_addr = addr);
475
unsigned int ElfSection::getOffset()
477
if (shdr.sh_offset != (Elf32_Word)-1)
478
return shdr.sh_offset;
480
if (previous == NULL)
481
return (shdr.sh_offset = 0);
483
unsigned int offset = previous->getOffset();
484
if (previous->getType() != SHT_NOBITS)
485
offset += previous->getSize();
487
Elf32_Word align = 0x1000;
488
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
489
align = std::max(align, (*seg)->getAlign());
491
Elf32_Word mask = align - 1;
492
// SHF_TLS is used for .tbss which is some kind of special case.
493
if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) && (getFlags() & SHF_ALLOC)) {
494
if ((getAddr() & mask) < (offset & mask))
495
offset = (offset | mask) + (getAddr() & mask) + 1;
497
offset = (offset & ~mask) + (getAddr() & mask);
499
if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
500
offset = (offset | (getAddrAlign() - 1)) + 1;
502
// Two subsequent sections can't be mapped in the same page in memory
503
// if they aren't in the same 4K block on disk.
504
if ((getType() != SHT_NOBITS) && getAddr()) {
505
if (((offset >> 12) != (previous->getOffset() >> 12)) &&
506
((getAddr() >> 12) == (previous->getAddr() >> 12)))
507
throw std::runtime_error("Moving section would require overlapping segments");
510
return (shdr.sh_offset = offset);
513
int ElfSection::getIndex()
517
if (getType() == SHT_NULL)
519
ElfSection *reference;
520
for (reference = previous; (reference != NULL) && (reference->getType() == SHT_NULL); reference = reference->getPrevious());
521
if (reference == NULL)
523
return (index = reference->getIndex() + 1);
526
Elf_Shdr &ElfSection::getShdr()
529
if (shdr.sh_link == (Elf32_Word)-1)
530
shdr.sh_link = getLink() ? getLink()->getIndex() : 0;
531
if (shdr.sh_info == (Elf32_Word)-1)
532
shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA)) ?
533
(getInfo().section ? getInfo().section->getIndex() : 0) :
539
ElfSegment::ElfSegment(Elf_Phdr *phdr)
540
: type(phdr->p_type), v_p_diff(phdr->p_paddr - phdr->p_vaddr),
541
flags(phdr->p_flags), align(phdr->p_align), vaddr(phdr->p_vaddr),
542
filesz(phdr->p_filesz), memsz(phdr->p_memsz) {}
544
void ElfSegment::addSection(ElfSection *section)
546
// Make sure all sections in PT_GNU_RELRO won't be moved by elfhack
547
assert(!((type == PT_GNU_RELRO) && (section->isRelocatable())));
549
//TODO: Check overlapping sections
550
std::list<ElfSection *>::iterator i;
551
for (i = sections.begin(); i != sections.end(); ++i)
552
if ((*i)->getAddr() > section->getAddr())
554
sections.insert(i, section);
555
section->addToSegment(this);
558
unsigned int ElfSegment::getFileSize()
560
if (type == PT_GNU_RELRO)
563
if (sections.empty())
565
// Search the last section that is not SHT_NOBITS
566
std::list<ElfSection *>::reverse_iterator i;
567
for (i = sections.rbegin(); (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i);
568
// All sections are SHT_NOBITS
569
if (i == sections.rend())
572
unsigned int end = (*i)->getAddr() + (*i)->getSize();
574
return end - sections.front()->getAddr();
577
unsigned int ElfSegment::getMemSize()
579
if (type == PT_GNU_RELRO)
582
if (sections.empty())
585
unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
587
return end - sections.front()->getAddr();
590
unsigned int ElfSegment::getOffset()
592
if ((type == PT_GNU_RELRO) && !sections.empty() &&
593
(sections.front()->getAddr() != vaddr))
594
throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
596
return sections.empty() ? 0 : sections.front()->getOffset();
599
unsigned int ElfSegment::getAddr()
601
if ((type == PT_GNU_RELRO) && !sections.empty() &&
602
(sections.front()->getAddr() != vaddr))
603
throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
605
return sections.empty() ? 0 : sections.front()->getAddr();
608
ElfSegment *ElfSegment::splitBefore(ElfSection *section)
610
std::list<ElfSection *>::iterator i, rm;
611
for (i = sections.begin(); (*i != section) && (i != sections.end()); ++i);
612
if (i == sections.end())
615
// Probably very wrong.
619
phdr.p_paddr = phdr.p_vaddr + v_p_diff;
620
phdr.p_flags = flags;
621
phdr.p_align = getAlign();
622
phdr.p_filesz = (unsigned int)-1;
623
phdr.p_memsz = (unsigned int)-1;
624
ElfSegment *segment = new ElfSegment(&phdr);
626
for (rm = i; i != sections.end(); ++i) {
627
(*i)->removeFromSegment(this);
628
segment->addSection(*i);
630
sections.erase(rm, sections.end());
635
ElfValue *ElfDynamic_Section::getValueForType(unsigned int tag)
637
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
638
if (dyns[i].tag == tag)
639
return dyns[i].value;
644
ElfSection *ElfDynamic_Section::getSectionForType(unsigned int tag)
646
ElfValue *value = getValueForType(tag);
647
return value ? value->getSection() : NULL;
650
bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
653
unsigned int shnum = shdr.sh_size / shdr.sh_entsize;
654
for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++)
655
if (dyns[i].tag == tag) {
656
delete dyns[i].value;
660
// If we get here, this means we didn't match for the given tag
661
// Most of the time, there are a few DT_NULL entries, that we can
662
// use to add our value, but if we are on the last entry, we can't.
671
ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
672
: ElfSection(s, file, parent)
674
int pos = file->tellg();
675
dyns.resize(s.sh_size / s.sh_entsize);
676
file->seekg(shdr.sh_offset);
677
// Here we assume tags refer to only one section (e.g. DT_RELSZ accounts
678
// for .rel.dyn size)
679
for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
680
Elf_Dyn dyn(*file, parent->getClass(), parent->getData());
681
dyns[i].tag = dyn.d_tag;
687
dyns[i].value = new ElfValue();
699
dyns[i].value = new ElfPlainValue(dyn.d_un.d_val);
716
dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent);
719
dyns[i].value = NULL;
722
// Another loop to get the section sizes
723
for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++)
724
switch (dyns[i].tag) {
726
dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL));
729
dyns[i].value = new ElfSize(getSectionForType(DT_RELA));
732
dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB));
735
dyns[i].value = new ElfSize(getSectionForType(DT_REL));
737
case DT_INIT_ARRAYSZ:
738
dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY));
740
case DT_FINI_ARRAYSZ:
741
dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY));
744
dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA));
747
dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB));
750
dyns[i].value = new ElfEntSize(getSectionForType(DT_REL));
757
ElfDynamic_Section::~ElfDynamic_Section()
759
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
760
delete dyns[i].value;
763
void ElfDynamic_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
765
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
767
dyn.d_tag = dyns[i].tag;
768
dyn.d_un.d_val = (dyns[i].value != NULL) ? dyns[i].value->getValue() : 0;
769
dyn.serialize(file, ei_class, ei_data);
773
ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
774
: ElfSection(s, file, parent)
776
int pos = file->tellg();
777
syms.resize(s.sh_size / s.sh_entsize);
778
ElfStrtab_Section *strtab = (ElfStrtab_Section *)getLink();
779
file->seekg(shdr.sh_offset);
780
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
781
Elf_Sym sym(*file, parent->getClass(), parent->getData());
782
syms[i].name = strtab->getStr(sym.st_name);
783
syms[i].info = sym.st_info;
784
syms[i].other = sym.st_other;
785
ElfSection *section = (sym.st_shndx == SHN_ABS) ? NULL : parent->getSection(sym.st_shndx);
786
new (&syms[i].value) ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE);
787
syms[i].size = sym.st_size;
788
syms[i].defined = (sym.st_shndx != SHN_UNDEF);
794
ElfSymtab_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
796
ElfStrtab_Section *strtab = (ElfStrtab_Section *)getLink();
797
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
799
sym.st_name = strtab->getStrIndex(syms[i].name);
800
sym.st_info = syms[i].info;
801
sym.st_other = syms[i].other;
802
sym.st_value = syms[i].value.getValue();
803
ElfSection *section = syms[i].value.getSection();
805
sym.st_shndx = section ? section->getIndex() : SHN_ABS;
807
sym.st_shndx = SHN_UNDEF;
808
sym.st_size = syms[i].size;
809
sym.serialize(file, ei_class, ei_data);
814
ElfSymtab_Section::lookup(const char *name, unsigned int type_filter)
816
for (std::vector<Elf_SymValue>::iterator sym = syms.begin();
817
sym != syms.end(); sym++) {
818
if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) &&
819
(strcmp(sym->name, name) == 0)) {
827
ElfStrtab_Section::getStr(unsigned int index)
829
for (std::vector<table_storage>::iterator t = table.begin();
830
t != table.end(); t++) {
832
return t->buf + index;
840
ElfStrtab_Section::getStr(const char *string)
845
// If the given string is within the section, return it
846
for (std::vector<table_storage>::iterator t = table.begin();
847
t != table.end(); t++)
848
if ((string >= t->buf) && (string < t->buf + t->used))
851
// TODO: should scan in the section to find an existing string
853
// If not, we need to allocate the string in the section
854
size_t len = strlen(string) + 1;
856
if (table.back().size - table.back().used < len)
857
table.resize(table.size() + 1);
859
char *alloc_str = table.back().buf + table.back().used;
860
memcpy(alloc_str, string, len);
861
table.back().used += len;
870
ElfStrtab_Section::getStrIndex(const char *string)
875
unsigned int index = 0;
876
string = getStr(string);
877
for (std::vector<table_storage>::iterator t = table.begin();
878
t != table.end(); t++) {
879
if ((string >= t->buf) && (string < t->buf + t->used))
880
return index + (string - t->buf);
889
ElfStrtab_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
891
file.seekp(getOffset());
892
for (std::vector<table_storage>::iterator t = table.begin();
893
t != table.end(); t++)
894
file.write(t->buf, t->used);