Copy section contents into newly allocated buffers
[centaur.git] / src / model / fromFile.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <libelf.h>
7 #include <gelf.h>
8 #include <libelfu/libelfu.h>
9
10
11 static ElfuPhdr* modelFromPhdr(GElf_Phdr *phdr)
12 {
13   ElfuPhdr *mp;
14
15   mp = malloc(sizeof(ElfuPhdr));
16   if (!mp) {
17     return NULL;
18   }
19
20   mp->phdr = *phdr;
21
22   return mp;
23 }
24
25
26 static ElfuScn* modelFromSection(Elf_Scn *scn)
27 {
28   ElfuScn *ms;
29
30
31   ms = malloc(sizeof(ElfuScn));
32   if (!ms) {
33     return NULL;
34   }
35
36
37   if (gelf_getshdr(scn, &ms->shdr) != &ms->shdr) {
38     fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1));
39     goto out;
40   }
41
42
43   /* Copy each data part in source segment */
44   ms->data.d_align = 1;
45   ms->data.d_buf  = NULL;
46   ms->data.d_off  = 0;
47   ms->data.d_type = ELF_T_BYTE;
48   ms->data.d_size = ms->shdr.sh_size;
49   ms->data.d_version = elf_version(EV_NONE);
50   if (ms->shdr.sh_type != SHT_NOBITS
51       && ms->shdr.sh_size > 1) {
52     Elf_Data *data;
53
54     ms->data.d_buf = malloc(ms->shdr.sh_size);
55     if (!ms->data.d_buf) {
56       fprintf(stderr, "modelFromSection: Could not allocate data buffer (%jx bytes).\n", ms->shdr.sh_size);
57       goto out;
58     }
59
60     /* A non-empty section should contain at least on data block. */
61     data = elf_rawdata(scn, NULL);
62
63     assert(data);
64
65     ms->data.d_align = data->d_align;
66     ms->data.d_type = data->d_type;
67     ms->data.d_version = data->d_version;
68
69     while (data) {
70       if (data->d_off + data->d_size > ms->shdr.sh_size) {
71         fprintf(stderr, "modelFromSection: libelf delivered a bogus data blob. Skipping\n");
72       } else {
73         memcpy(ms->data.d_buf + data->d_off, data->d_buf, data->d_size);
74       }
75
76       data = elf_rawdata(scn, data);
77     }
78   }
79
80
81   return ms;
82
83   out:
84   // FIXME
85   return NULL;
86 }
87
88
89
90
91 ElfuElf* elfu_mFromElf(Elf *e)
92 {
93   ElfuElf *me;
94   Elf_Scn *scn;
95   size_t shstrndx;
96   size_t i, n;
97
98   if (elf_getshdrstrndx(e, &shstrndx) != 0) {
99     shstrndx = 0;
100   }
101
102   me = malloc(sizeof(ElfuElf));
103   if (!me) {
104     return NULL;
105   }
106
107   CIRCLEQ_INIT(&me->scnList);
108   CIRCLEQ_INIT(&me->phdrList);
109   me->shstrtab = NULL;
110
111   /*
112    * General stuff
113    */
114   me->elfclass = gelf_getclass(e);
115   if (me->elfclass == ELFCLASSNONE) {
116     fprintf(stderr, "getclass() failed: %s\n", elf_errmsg(-1));
117   }
118
119   if (!gelf_getehdr(e, &me->ehdr)) {
120     fprintf(stderr, "gelf_getehdr() failed: %s\n", elf_errmsg(-1));
121     goto out;
122   }
123
124
125   /*
126    * Sections
127    */
128   scn = elf_getscn(e, 1);
129   i = 1;
130   while (scn) {
131     ElfuScn *ms = modelFromSection(scn);
132
133     if (ms) {
134       CIRCLEQ_INSERT_TAIL(&me->scnList, ms, elem);
135       if (i == shstrndx) {
136         me->shstrtab = ms;
137       }
138     } else {
139       goto out;
140     }
141
142     scn = elf_nextscn(e, scn);
143     i++;
144   }
145
146
147
148   /*
149    * Segments
150    */
151   if (elf_getphdrnum(e, &n)) {
152     fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
153   }
154
155   for (i = 0; i < n; i++) {
156     GElf_Phdr phdr;
157     ElfuPhdr *mp;
158
159     if (gelf_getphdr(e, i, &phdr) != &phdr) {
160       fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
161       break;
162     }
163
164     mp = modelFromPhdr(&phdr);
165
166     if (mp) {
167       CIRCLEQ_INSERT_TAIL(&me->phdrList, mp, elem);
168     } else {
169       goto out;
170     }
171   }
172
173
174
175   return me;
176
177   out:
178   // FIXME
179   return NULL;
180 }