summaryrefslogtreecommitdiff
path: root/src/model/toFile.c
blob: 294cfe458ce82a18c3dd8e79bc1415f569a44a05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdio.h>
#include <stdlib.h>

#include <libelf.h>
#include <gelf.h>

#include <libelfu/libelfu.h>



static void elfu_modelToPhdrs(ElfuElf *me, Elf *e)
{
  ElfuPhdr *mp;
  size_t i;

  /* Count PHDRs */
  i = 0;
  for (mp = me->phdrList.cqh_first;
        mp != (void *)&me->phdrList;
        mp = mp->elem.cqe_next) {
    i++;
  }

  if (!gelf_newphdr(e, i)) {
    fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1));
  }

  /* Copy PHDRs */
  i = 0;
  for (mp = me->phdrList.cqh_first;
        mp != (void *)&me->phdrList;
        mp = mp->elem.cqe_next) {
    if (!gelf_update_phdr (e, i, &mp->phdr)) {
      fprintf(stderr, "gelf_update_phdr() failed: %s\n", elf_errmsg(-1));
    }

    i++;
  }
}



static void elfu_modelToSection(ElfuScn *ms, Elf *e)
{
  Elf_Scn *scnOut;

  scnOut = elf_newscn(e);
  if (!scnOut) {
    fprintf(stderr, "elf_newscn() failed: %s\n", elf_errmsg(-1));
    return;
  }


  /* SHDR */
  if (!gelf_update_shdr(scnOut, &ms->shdr)) {
    fprintf(stderr, "gelf_update_shdr() failed: %s\n", elf_errmsg(-1));
  }


  /* Data */
  ElfuData *md;
  for (md = ms->dataList.cqh_first;
        md != (void *)&ms->dataList;
        md = md->elem.cqe_next) {
    Elf_Data *dataOut = elf_newdata(scnOut);
    if (!dataOut) {
      fprintf(stderr, "elf_newdata() failed: %s\n", elf_errmsg(-1));
    }

    dataOut->d_align = md->data.d_align;
    dataOut->d_buf  = md->data.d_buf;
    dataOut->d_off  = md->data.d_off;
    dataOut->d_type = md->data.d_type;
    dataOut->d_size = md->data.d_size;
    dataOut->d_version = md->data.d_version;
  }
}





void elfu_modelToElf(ElfuElf *me, Elf *e)
{
  ElfuScn *ms;

  /* We control the ELF file's layout now. */
  /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections. */
  elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);


  /* EHDR */
  if (!gelf_newehdr(e, me->elfclass)) {
    fprintf(stderr, "gelf_newehdr() failed: %s\n", elf_errmsg(-1));
  }

  if (!gelf_update_ehdr(e, &me->ehdr)) {
    fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1));
  }


  /* Sections */
  for (ms = me->scnList.cqh_first;
        ms != (void *)&me->scnList;
        ms = ms->elem.cqe_next) {
    elfu_modelToSection(ms, e);
  }


  /* PHDRs */
  elfu_modelToPhdrs(me, e);


  elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
}