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

Last change on this file was 171, checked in by karaoui, 12 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.