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

Last change on this file since 708 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.