source: soft/giet_vm/memo/src/libelfpp/elfpp_access.cc

Last change on this file was 171, checked in by karaoui, 14 years ago

Testing the placement of the kernel segments without the identity mapping.
debugging memo.
debugging the vm_handler to disable the interrupts while passing in physical addressing.

File size: 21.5 KB
Line 
1/*
2 This file is part of Libelfpp.
3
4 Libelfpp is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of the
7 License, or (at your option) any later version.
8
9 Libelfpp is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with Libelfpp. If not, see
16 <http://www.gnu.org/licenses/>.
17
18 Copyright (c) Alexandre Becoulet <alexandre.becoulet@free.fr>
19*/
20
21#include <stdexcept>
22#include <iostream>
23#include <cassert>
24#include <algorithm>
25#include <cstring>
26
27#include <dpp/foreach>
28
29#include <elfpp/access>
30#include <elfpp/object>
31#include <elfpp/section>
32#include <elfpp/symbol>
33#include <elfpp/reloc>
34#include <elfpp/segment>
35
36namespace elfpp
37{
38
39 template <typename bits_t, int width>
40 void elfn_access<bits_t, width>::load_symtab(object &obj)
41 {
42 section &table = obj.get_section(".symtab");
43
44 if (table.get_type() != SHT_SYMTAB)
45 throw std::runtime_error("not a symbol table section");
46
47 // get symbol table content
48 elf_sym_t *symtab = (elf_sym_t*)table.get_content();
49 size_t count = table.get_size() / sizeof (elf_sym_t);
50
51 // get symbol string section
52 section &strtab = *table.get_link();
53 const char *symstr = (char*)strtab.get_content();
54
55 // create symbol objects from table
56 obj.symidx_.resize(count);
57
58 for (unsigned int i = 1; i < count; i++)
59 {
60 unsigned int idx = swap(symtab[i].st_shndx);
61
62 symbol *sym = new symbol(symstr + swap(symtab[i].st_name));
63
64 obj.symidx_[i] = sym;
65
66 sym->set_value(swap(symtab[i].st_value));
67 sym->set_size(swap(symtab[i].st_size));
68 sym->set_info(symtab[i].st_info);
69 sym->set_other(symtab[i].st_other);
70
71 if (idx > 0 && idx < SHN_LORESERVE)
72 {
73 section *symsec = obj.secidx_.at(idx);
74 if (!symsec)
75 continue;
76
77 sym->set_section(*symsec);
78 symsec->add_symbol(*sym);
79
80 if (obj.type_ != ET_REL)
81 sym->set_value(sym->get_value() - symsec->get_vaddr());
82
83 if (symsec && sym->get_size() > 0 && symsec->get_type() != SHT_NOBITS)
84 {
85 if (symsec->get_size() < sym->get_value())
86 std::cerr << "elfpp: symbol value above section size " << sym->get_name()
87 << ":" << std::hex << sym->get_value() << std::endl;
88 // else
89 // sym->set_content(symsec->get_content() + sym->get_value());
90 }
91 }
92 else
93 {
94 sym->set_section_ndx(idx);
95 obj.add_symbol(*sym);
96 }
97 }
98
99 // discard symbol table sections
100 delete &table;
101 delete &strtab;
102 }
103
104 template <typename bits_t, int width>
105 void elfn_access<bits_t, width>::load_addend(const object &obj, reloc &r, const elf_rel_t *reltab,
106 size_t count, int index, uint8_t *data)
107 {
108 // r->set_addend(rel_read(obj, type, sec->get_content() + ro));
109 uint64_t offset = swap(reltab[index].r_offset);
110 r.set_offset(offset);
111
112 switch (obj.machine_)
113 {
114 case EM_MIPS:
115 switch (r.get_type())
116 {
117 case R_MIPS_26:
118 r.set_addend((swap(*(uint32_t*)(data + offset)) & 0x3ffffff) << 2);
119 return;
120
121 case R_MIPS_32:
122 r.set_addend(swap(*(uint32_t*)(data + offset)));
123 return;
124
125 case R_MIPS_HI16: {
126 int32_t value = (swap(*(uint32_t*)(data + offset)) & 0xffff) << 16;
127 // get next LO16 relocation
128 for (index++; index < (int)count && rel_type(swap(reltab[index].r_info)) != R_MIPS_LO16; index++)
129 ;
130 if (index != (int)count)
131 {
132 offset = swap(reltab[index].r_offset);
133 value += (int16_t)swap(*(uint32_t*)(data + offset));
134 r.set_addend(value);
135 }
136 else
137 {
138 std::cerr << "elfpp: can not find matching LO16 relocation" << std::endl;
139 }
140 return;
141 }
142
143 case R_MIPS_LO16: {
144 int32_t value = (int16_t)swap(*(uint32_t*)(data + offset));
145 // get prev HI16 relocation if any
146 if (index > 0 && rel_type(swap(reltab[index - 1].r_info)) == R_MIPS_HI16)
147 {
148 offset = swap(reltab[index - 1].r_offset);
149 value += (swap(*(uint32_t*)(data + offset)) & 0xffff) << 16;
150 }
151 r.set_addend(value);
152 return;
153 }
154
155 default: ;
156 }
157 break;
158
159 case EM_ARM:
160 switch (r.get_type())
161 {
162 case R_ARM_PC24:
163 r.set_addend(((swap(*(uint32_t*)(data + offset)) & 0xffffff) << 2) + 8);
164 return;
165
166 case R_ARM_ABS32:
167 r.set_addend(swap(*(uint32_t*)(data + offset)));
168 return;
169
170 default: ;
171 }
172 break;
173
174 default: ;
175 }
176
177 std::cerr << "elfpp: unhandled relocation (machine=" << obj.machine_
178 << ", type=" << r.get_type() << ")" << std::endl;
179 return;
180 }
181
182 template <typename bits_t, int width>
183 void elfn_access<bits_t, width>::rel_write(const object &obj, enum reloc_e type, void *data, int64_t value)
184 {
185 uint32_t mask;
186
187 switch (obj.machine_)
188 {
189 case EM_MIPS:
190 switch (type)
191 {
192 case R_MIPS_26:
193 mask = 0x3ffffff;
194 if (value & 0x3)
195 std::cerr << "elfpp: R_MIPS_26 relocation with 2 LSB set" << std::endl;
196 value >>= 2;
197 goto done;
198
199 case R_MIPS_32:
200 mask = 0xffffffff;
201 goto done;
202
203 case R_MIPS_HI16:
204 mask = 0xffff;
205 value >>= 16;
206 goto done;
207
208 case R_MIPS_LO16:
209 mask = 0xffff;
210 goto done;
211
212 default: ;
213 }
214 break;
215
216 case EM_ARM:
217 switch (type)
218 {
219 case R_ARM_PC24:
220 mask = 0x00ffffff;
221 value = (value - 8) >> 2;
222 goto done;
223
224 case R_ARM_ABS32:
225 mask = 0xffffffff;
226 goto done;
227
228 default: ;
229 }
230 break;
231
232 default: ;
233 }
234
235 std::cerr << "elfpp: unhandled relocation (machine=" << obj.machine_ << ", type=" << type << ")" << std::endl;
236 return;
237
238 done:
239 *(uint32_t*)data = swap(mask & value) | (*(uint32_t*)data & swap(~mask));
240 }
241
242 template <typename bits_t, int width>
243 void elfn_access<bits_t, width>::load_reltab(object &obj)
244 {
245 // load all reloaction table sections
246
247 if (obj.type_ != ET_REL)
248 return;
249
250 FOREACH2(relsec, obj.get_section_table())
251 {
252 switch (relsec->get_type())
253 {
254 case SHT_REL: {
255 elf_rel_t *reltab = (elf_rel_t*)relsec->get_content();
256 size_t count = relsec->get_size() / sizeof (elf_rel_t);
257 obj.rel_with_addend_ = false;
258
259 for (unsigned int i = 0; i < count; i++)
260 {
261 if (!rel_sym(swap(reltab[i].r_info)))
262 continue;
263
264 reloc *r = new reloc();
265
266 section *sec = relsec->get_info();
267 symbol *sym = obj.symidx_.at(rel_sym(swap(reltab[i].r_info)));
268 assert(sym);
269
270 r->set_symbol(sym);
271 r->set_section(sec);
272
273 reloc_e type = rel_type(swap(reltab[i].r_info));
274 r->set_type(type);
275 load_addend(obj, *r, reltab, count, i, sec->get_content());
276 }
277
278 // std::cerr << "elfpp: relocation " << i << " offset " << ro << " out of section" << std::endl;
279
280 delete &*relsec;
281 break;
282 }
283
284 case SHT_RELA: {
285 elf_rela_t *reltab = (elf_rela_t*)relsec->get_content();
286 size_t count = relsec->get_size() / sizeof (elf_rela_t);
287 obj.rel_with_addend_ = true;
288
289 for (unsigned int i = 0; i < count; i++)
290 {
291 if (!rel_sym(swap(reltab[i].r_info)))
292 continue;
293
294 reloc *r = new reloc();
295
296 section *sec = relsec->get_info();
297 symbol *sym = obj.symidx_[rel_sym(swap(reltab[i].r_info))];
298 assert(sym);
299
300 r->set_symbol(sym);
301 r->set_section(sec);
302
303 r->set_type(rel_type(swap(reltab[i].r_info)));
304 uint32_t ro = swap(reltab[i].r_offset);
305 r->set_offset(ro);
306 r->set_addend(swap(reltab[i].r_addend));
307 }
308
309 delete &*relsec;
310 break;
311 }
312
313 default:
314 break;
315 }
316
317 }
318
319 obj.generate_symtab_ = true;
320 }
321
322 static bool sort_predicate(const symbol *a, const symbol *b)
323 {
324 return a->get_info() < b->get_info();
325 }
326
327 template <typename bits_t, int width>
328 void elfn_access<bits_t, width>::save_symtab(object &obj)
329 {
330 size_t shnum = 1;
331
332 // renumber current section table
333 FOREACH(s, obj.get_section_table())
334 s->index_ = shnum++;
335
336 // create symbol and associated string sections
337 section *symtab = new section(obj, SHT_SYMTAB);
338 section *strtab = new section(obj, SHT_STRTAB);
339 std::string str(1, '\0');
340
341 symtab->set_name(".symtab");
342 symtab->set_entsize(sizeof (elf_sym_t));
343 symtab->set_link(strtab);
344
345 strtab->set_name(".strtab");
346 strtab->set_flags(SHF_STRINGS);
347
348 obj.add_section(*symtab);
349 obj.add_section(*strtab);
350
351 // prepare sorted symbol array
352
353 unsigned int i = 0;
354 std::vector<symbol *> table;
355
356 table.resize(obj.get_symbol_table().size());
357
358 FOREACH(sym, obj.get_symbol_table())
359 table[i++] = sym->second;
360
361 FOREACH(sec, obj.get_section_table())
362 {
363 table.resize(i + sec->get_symbol_table().size());
364
365 FOREACH(sym, sec->get_symbol_table())
366 table[i++] = sym->second;
367 }
368
369 sort(table.begin(), table.end(), sort_predicate);
370
371 for (i = 0; i < table.size(); i++)
372 {
373 if (ELF_ST_BIND(table[i]->get_info()) != STB_LOCAL)
374 break;
375 }
376
377 symtab->set_info_last(i + 1);
378
379 // generate symbol table section content
380
381 std::vector<reloc*> reloclist[shnum];
382 elf_sym_t symdata[table.size() + 1];
383 i = 1;
384
385 std::memset(symdata, 0, sizeof(elf_sym_t));
386
387 FOREACH(sym_, table)
388 {
389 elf_sym_t &ent = symdata[i];
390 symbol *sym = *sym_;
391
392 swap(&ent.st_name, str.size());
393 str.append(sym->get_name().c_str(), sym->get_name().size() + 1);
394 swap(&ent.st_value, sym->get_value());
395 swap(&ent.st_size, sym->get_size());
396 ent.st_info = sym->get_info();
397 ent.st_other = sym->get_other();
398
399 FOREACH(rel, sym->reloc_tab_)
400 reloclist[rel->get_section()->index_].push_back(&*rel);
401
402 if (sym->get_section())
403 swap(&ent.st_shndx, sym->get_section()->index_);
404 else
405 swap(&ent.st_shndx, sym->get_section_ndx());
406
407 sym->index_ = i++;
408 }
409
410 strtab->set_size(str.size());
411 std::memcpy(strtab->get_content(), str.data(), str.size());
412
413 symtab->set_size(sizeof(symdata));
414 std::memcpy(symtab->get_content(), symdata, sizeof(symdata));
415
416 // generate relocation table
417
418 FOREACH(sec, obj.get_section_table())
419 {
420 if (!sec->index_)
421 continue;
422
423 std::vector<reloc*> &rl = reloclist[sec->index_];
424
425 if (rl.empty())
426 continue;
427
428 section *reltab = new section(obj, obj.rel_with_addend_ ? SHT_RELA : SHT_REL);
429
430 reltab->set_entsize(sizeof (elf_rel_t));
431 reltab->set_link(symtab);
432 reltab->set_info(&*sec);
433
434 obj.add_section(*reltab);
435
436 if (obj.rel_with_addend_)
437 {
438 elf_rela_t reldata[rl.size()];
439
440 reltab->set_name(".rela" + sec->get_name());
441 i = 0;
442
443 FOREACH(rel_, rl)
444 {
445 reloc *rel = *rel_;
446
447 if (symbol *ms = rel->get_mangled_symbol())
448 swap(&reldata[i].r_offset, ms->get_value() + rel->get_offset());
449 else
450 swap(&reldata[i].r_offset, rel->get_offset());
451
452 swap(&reldata[i].r_info, rel_info(rel->get_symbol()->index_, rel->get_type()));
453 swap(&reldata[i].r_addend, rel->get_addend());
454 i++;
455 }
456
457 reltab->set_size(sizeof(reldata));
458 std::memcpy(reltab->get_content(), reldata, sizeof(reldata));
459 }
460 else
461 {
462 elf_rel_t reldata[rl.size()];
463
464 reltab->set_name(".rel" + sec->get_name());
465 i = 0;
466
467 FOREACH(rel_, rl)
468 {
469 reloc *rel = *rel_;
470
471 uint64_t ro = rel->get_offset();
472 if (symbol *ms = rel->get_mangled_symbol())
473 {
474 // relocation offset is relative to mangled symbol value
475 if (ro < ms->get_size())
476 rel_write(obj, rel->get_type(), ms->get_content() + ro, rel->get_addend());
477 else
478 std::cerr << "elfpp: relocation offset above mangled symbol size" << std::endl;
479 ro += ms->get_value();
480 }
481 else
482 {
483 // relocation offset is relative to mangled section
484 if (ro < sec->get_size())
485 rel_write(obj, rel->get_type(), sec->get_content() + ro, rel->get_addend());
486 else
487 std::cerr << "elfpp: relocation offset above section size" << std::endl;
488 }
489
490 swap(&reldata[i].r_offset, ro);
491
492 swap(&reldata[i].r_info, rel_info(rel->get_symbol()->index_, rel->get_type()));
493 i++;
494 }
495
496 reltab->set_size(sizeof(reldata));
497 std::memcpy(reltab->get_content(), reldata, sizeof(reldata));
498 }
499
500 }
501 }
502
503 template <typename bits_t, int width>
504 void elfn_access<bits_t, width>::read(object &obj, FILE *file)
505 {
506 // read file header
507
508 elf_hdr_t head_;
509
510 fseek(file, 0, SEEK_SET);
511 if (fread(&head_, sizeof (head_), 1, file) != 1)
512 throw std::runtime_error("unable to read file");
513
514 obj.word_width_ = (ei_class_e)head_.e_ident[EI_CLASS];
515 obj.byteorder_ = byteorder_ = (ei_data_e)head_.e_ident[EI_DATA];
516 obj.os_abi_ = (ei_osabi_e)head_.e_ident[EI_OSABI];
517 obj.abi_ver_ = head_.e_ident[EI_ABIVERSION];
518 obj.type_ = (e_type_e)swap(head_.e_type);
519 obj.machine_ = (e_machine_e)swap(head_.e_machine);
520 obj.entry_ = swap(head_.e_entry);
521 obj.flags_ = swap(head_.e_flags);
522
523 // read segment table
524 size_t phnum = swap(head_.e_phnum);
525 elf_phdr_t phdr[phnum];
526
527 fseek(file, swap(head_.e_phoff), SEEK_SET);
528 if (fread(phdr, sizeof (elf_phdr_t), phnum, file) != phnum)
529 throw std::runtime_error("unable to read file");
530
531 // create segment objects
532
533 for (unsigned int i = 0; i < phnum; i++)
534 {
535 segment *s = new segment(obj);
536
537 s->set_type((p_type_e)swap(phdr[i].p_type));
538 s->set_file_offset(swap(phdr[i].p_offset));
539 s->set_vaddr(swap(phdr[i].p_vaddr));
540 s->set_paddr(swap(phdr[i].p_paddr));
541 s->set_mem_size(swap(phdr[i].p_memsz));
542 s->set_file_size(swap(phdr[i].p_filesz));
543 s->set_flags((p_flags_e)swap(phdr[i].p_flags));
544 s->set_align(swap(phdr[i].p_align));
545
546 obj.add_segment(*s);
547 }
548
549 // read section table
550 size_t shnum = swap(head_.e_shnum);
551 elf_shdr_t shdr[shnum];
552 obj.secidx_.resize(shnum);
553
554 fseek(file, swap(head_.e_shoff), SEEK_SET);
555
556 if (fread(shdr, sizeof (elf_shdr_t), shnum, file) != shnum)
557 throw std::runtime_error("unable to read file");
558
559 // create section objects
560
561 for (unsigned int i = 1; i < shnum; i++)
562 {
563 sh_type_e type = (sh_type_e)swap(shdr[i].sh_type);
564
565 section *s = new section(obj, type);
566 off_t offset = swap(shdr[i].sh_offset);
567
568 obj.secidx_[i] = s;
569 s->index_ = i;
570
571 s->set_flags((sh_flags_e)swap(shdr[i].sh_flags));
572 s->set_vaddr(swap(shdr[i].sh_addr));
573 s->set_file_offset(offset);
574 s->set_size(swap(shdr[i].sh_size));
575 s->set_align(swap(shdr[i].sh_addralign));
576 s->set_entsize(swap(shdr[i].sh_entsize));
577
578 if (type != SHT_NOBITS && s->get_size())
579 {
580 fseek(file, offset, SEEK_SET);
581 if (fread(s->get_content(), s->get_size(), 1, file) != 1)
582 throw std::runtime_error("unable to read file");
583 }
584
585 obj.add_section(*s);
586 }
587
588 // update sections links
589
590 for (unsigned int i = 1; i < shnum; i++)
591 {
592 section &s = *obj.secidx_[i];
593
594 unsigned int link = swap(shdr[i].sh_link);
595
596 if (link)
597 s.set_link(obj.secidx_.at(link));
598
599 unsigned int info = swap(shdr[i].sh_info);
600
601 switch (s.type_)
602 {
603 case SHT_REL:
604 case SHT_RELA:
605 if (info)
606 s.set_info(obj.secidx_.at(info));
607 break;
608
609 case SHT_DYNSYM:
610 case SHT_SYMTAB:
611 s.set_info_last(info);
612 break;
613
614 default:
615 ;
616 }
617 }
618
619 // set sections names
620
621 unsigned int shstrndx = swap(head_.e_shstrndx);
622
623 if (shstrndx != SHN_UNDEF)
624 {
625 section &shstr = *obj.secidx_.at(shstrndx);
626 const char *str = (char*)shstr.get_content();
627
628 for (unsigned int i = 1; i < shnum; i++)
629 obj.secidx_[i]->set_name(str + swap(shdr[i].sh_name));
630
631 delete &shstr;
632 }
633
634 }
635
636 template <typename bits_t, int width>
637 void elfn_access<bits_t, width>::create_segments(object &obj)
638 {
639 p_flags_e flag;
640
641
642 FOREACH(sec, obj.get_section_table())
643 {
644 segment *s = new segment(obj);
645
646 if(!(sec->get_flags() & elfpp::SHF_ALLOC))
647 {
648 s->set_type(PT_NULL);
649 continue;
650 }
651
652 s->set_type(PT_LOAD);
653 s->set_file_offset(0);//done while writing section in file
654#ifdef MEMO_DEBUG
655 std::cout << "seg building (" << std::hex << sec->get_vaddr() << ") for: " << *sec << std::endl;
656#endif
657 s->set_vaddr(sec->get_vaddr());
658 s->set_paddr(sec->get_vaddr());
659
660 s->set_mem_size(sec->get_size());
661 s->set_file_size(sec->get_size());
662
663 flag = PF_R ;//ALLOC ==> read ?
664 flag = flag | (p_flags_e)(sec->get_flags() & SHF_WRITE)? PF_W : PF_R ;
665 flag = flag | (p_flags_e)(sec->get_flags() & SHF_EXECINSTR)? PF_X : PF_R ;
666 s->set_flags(flag);
667 s->set_align(0);//FIXME!
668
669#ifdef MEMO_DEBUG
670 std::cout <<"New segment " << s->get_file_size() << std::endl;
671#endif
672 obj.add_segment(*s);
673 }
674 }
675
676 template <typename bits_t, int width>
677 void elfn_access<bits_t, width>::write(object &obj, FILE *file)
678 {
679 byteorder_ = obj.byteorder_;
680
681 if (obj.generate_symtab_)
682 save_symtab(obj);
683
684 // create all segments
685
686 create_segments(obj);
687
688 // write symbol contents
689
690 FOREACH(sec, obj.get_section_table())
691 {
692 if (sec->get_type() == SHT_NOBITS)
693 continue;
694
695 FOREACH(sym_, sec->get_symbol_table())
696 {
697 symbol *sym = sym_->second;
698
699 if (!sym->get_content())
700 continue;
701
702 if (sec->get_size() < sym->get_value() + sym->get_size())
703 sec->set_size(sym->get_value() + sym->get_size());
704
705 std::memcpy(sec->get_content() + sym->get_value(), sym->get_content(), sym->get_size());
706 }
707 }
708
709 elf_hdr_t head;
710
711 // create a new section name section
712
713 section *shstrtab = new section(obj, SHT_STRTAB);
714 shstrtab->set_name(".shstrtab");
715 shstrtab->set_flags(SHF_STRINGS);
716 obj.add_section(*shstrtab);
717
718 size_t shnum = 1;
719
720 FOREACH(s, obj.get_section_table())
721 s->index_ = shnum++;
722
723 std::string strtab(1, '\0');
724 unsigned int stridx[shnum];
725
726 stridx[0] = 0;
727
728 FOREACH(s, obj.get_section_table())
729 {
730 stridx[s->index_] = strtab.size();
731 strtab.append(s->get_name().c_str(), s->get_name().size() + 1);
732 }
733
734 shstrtab->set_size(strtab.size());
735 std::memcpy(shstrtab->get_content(), strtab.data(), strtab.size());
736
737 size_t phnum = shnum;//FIXME!:only relevent section
738 // update header
739
740 std::memset(head.e_ident, 0, sizeof(head.e_ident));
741 std::memcpy(head.e_ident, ELFMAG, 4);
742 head.e_ident[EI_CLASS] = obj.word_width_;
743 head.e_ident[EI_DATA] = byteorder_;
744 head.e_ident[EI_VERSION] = EV_CURRENT;
745 head.e_ident[EI_OSABI] = obj.os_abi_;
746 head.e_ident[EI_ABIVERSION] = obj.abi_ver_;
747
748 swap(&head.e_type, obj.type_);
749 swap(&head.e_machine, obj.machine_);
750 swap(&head.e_version, EV_CURRENT);
751 swap(&head.e_entry, obj.entry_);
752 swap(&head.e_phoff, sizeof (elf_hdr_t));
753 swap(&head.e_shoff, sizeof (elf_hdr_t)+ (sizeof(elf_phdr_t)*phnum));//!
754 swap(&head.e_flags, obj.flags_);
755 swap(&head.e_ehsize, sizeof (elf_hdr_t));
756 swap(&head.e_phentsize, sizeof (elf_phdr_t));
757 swap(&head.e_phnum, phnum);
758 swap(&head.e_shentsize, sizeof (elf_shdr_t));
759 swap(&head.e_shnum, shnum);
760 swap(&head.e_shstrndx, shstrtab->index_);
761
762 // update section table
763
764 elf_shdr_t shdr[shnum];
765
766 std::memset(shdr, 0, sizeof(shdr));
767
768 FOREACH(s, obj.get_section_table())
769 {
770 unsigned int i = s->index_;
771
772 swap(&shdr[i].sh_name, stridx[i]);
773
774 swap(&shdr[i].sh_type, s->get_type());
775 swap(&shdr[i].sh_flags, s->get_flags());
776 swap(&shdr[i].sh_addr, s->get_vaddr());
777
778
779 swap(&shdr[i].sh_size, s->get_size());
780 if (s->get_link())
781 swap(&shdr[i].sh_link, s->get_link()->index_);
782
783 switch (s->get_type())
784 {
785 case SHT_REL:
786 case SHT_RELA:
787 assert(s->get_info());
788 swap(&shdr[i].sh_info, s->get_info()->index_);
789 break;
790
791 case SHT_DYNSYM:
792 case SHT_SYMTAB:
793 swap(&shdr[i].sh_info, s->get_info_last());
794 default:
795 break;
796 }
797
798 swap(&shdr[i].sh_addralign, s->get_align());
799 swap(&shdr[i].sh_entsize, s->get_entsize());
800 }
801
802 // update program header
803 elf_phdr_t phdr[phnum];
804
805 std::memset(phdr, 0, sizeof(phdr));
806
807 unsigned int i = 1;//to keep the same order as sections
808 FOREACH(s, obj.get_segment_table())
809 {
810
811 swap(&phdr[i].p_type, s->get_type());
812 swap(&phdr[i].p_flags, s->get_flags());
813 swap(&phdr[i].p_vaddr, s->get_vaddr());
814 swap(&phdr[i].p_paddr, s->get_paddr());
815
816
817 swap(&phdr[i].p_filesz, s->get_file_size());
818 swap(&phdr[i].p_memsz, s->get_mem_size());
819
820
821 swap(&phdr[i].p_align, s->get_align());
822 //note: offset done while writing sections
823 i++;
824 }
825 //assert((i == phnum)and (i == shnum));
826
827 // write header to file
828
829 fseek(file, 0, SEEK_SET);
830 if (fwrite(&head, sizeof(head), 1, file) != 1)
831 throw std::runtime_error("unable to write header to file");
832
833 fseek(file, sizeof(phdr)+sizeof(shdr), SEEK_CUR);
834
835 // write sections to file
836
837 FOREACH(s, obj.get_section_table())
838 {
839 if (s->get_type() == SHT_NOBITS)
840 continue;
841
842#ifdef MEMO_DEBUG
843 std::cout << "offset: " << ftell(file) << " for " << *s << std::endl;
844 std::cout << std::hex << "paddr: " << phdr[s->index_].p_paddr << ", sect vaddr: " << s->get_vaddr() << "/" <<shdr[s->index_].sh_addr << std::endl;
845#endif
846 swap(&shdr[s->index_].sh_offset, ftell(file));
847 swap(&phdr[s->index_].p_offset, ftell(file));
848 if (s->get_size() && fwrite(s->get_content(), s->get_size(), 1, file) != 1)
849 throw std::runtime_error("unable to write section to file");
850 }
851
852 // write program header to file
853
854 fseek(file, sizeof(head), SEEK_SET);
855 if (fwrite(phdr, sizeof(phdr), 1, file) != 1)
856 throw std::runtime_error("unable to write section table to file");
857
858 // write section table to file
859
860 //toDO:assert(cur_seek == phnum*sizeof(ph_t)+...)
861 //fseek(file, sizeof(phdr)+sizeof(head), SEEK_CUR);
862 if (fwrite(shdr, sizeof(shdr), 1, file) != 1)
863 throw std::runtime_error("unable to write section table to file");
864
865 }
866
867 template class elfn_access<elf32_bits_s, 32>;
868 template class elfn_access<elf64_bits_s, 64>;
869
870}
871
Note: See TracBrowser for help on using the repository browser.