Refactor mdoel-related code
[centaur.git] / src / model / fromFile.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <libelf.h>
5 #include <gelf.h>
6 #include <libelfu/libelfu.h>
7
8
9 static ElfuPhdr* modelFromPhdr(GElf_Phdr *phdr)
10 {
11   ElfuPhdr *mp;
12
13   mp = malloc(sizeof(ElfuPhdr));
14   if (!mp) {
15     return NULL;
16   }
17
18   mp->phdr = *phdr;
19
20   return mp;
21 }
22
23
24 static ElfuScn* modelFromSection(Elf_Scn *scn)
25 {
26   ElfuScn *ms;
27   Elf_Data *data;
28
29   ms = malloc(sizeof(ElfuScn));
30   if (!ms) {
31     return NULL;
32   }
33
34   CIRCLEQ_INIT(&ms->dataList);
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
44   /* Copy each data part in source segment */
45   data = elf_rawdata(scn, NULL);
46   while (data) {
47     ElfuData *md;
48
49     md = malloc(sizeof(ElfuData));
50     if (!md) {
51       goto out;
52     }
53
54     md->data = *data;
55
56     CIRCLEQ_INSERT_TAIL(&ms->dataList, md, elem);
57
58     data = elf_rawdata(scn, data);
59   }
60
61   return ms;
62
63   out:
64   // FIXME
65   return NULL;
66 }
67
68
69
70
71 ElfuElf* elfu_mFromElf(Elf *e)
72 {
73   ElfuElf *me;
74   Elf_Scn *scn;
75   size_t shstrndx;
76   size_t i, n;
77
78   if (elf_getshdrstrndx(e, &shstrndx) != 0) {
79     shstrndx = 0;
80   }
81
82   me = malloc(sizeof(ElfuElf));
83   if (!me) {
84     return NULL;
85   }
86
87   CIRCLEQ_INIT(&me->scnList);
88   CIRCLEQ_INIT(&me->phdrList);
89   me->shstrtab = NULL;
90
91   /*
92    * General stuff
93    */
94   me->elfclass = gelf_getclass(e);
95   if (me->elfclass == ELFCLASSNONE) {
96     fprintf(stderr, "getclass() failed: %s\n", elf_errmsg(-1));
97   }
98
99   if (!gelf_getehdr(e, &me->ehdr)) {
100     fprintf(stderr, "gelf_getehdr() failed: %s\n", elf_errmsg(-1));
101     goto out;
102   }
103
104
105   /*
106    * Sections
107    */
108   scn = elf_getscn(e, 1);
109   i = 1;
110   while (scn) {
111     ElfuScn *ms = modelFromSection(scn);
112
113     if (ms) {
114       CIRCLEQ_INSERT_TAIL(&me->scnList, ms, elem);
115       if (i == shstrndx) {
116         me->shstrtab = ms;
117       }
118     } else {
119       goto out;
120     }
121
122     scn = elf_nextscn(e, scn);
123     i++;
124   }
125
126
127
128   /*
129    * Segments
130    */
131   if (elf_getphdrnum(e, &n)) {
132     fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
133   }
134
135   for (i = 0; i < n; i++) {
136     GElf_Phdr phdr;
137     ElfuPhdr *mp;
138
139     if (gelf_getphdr(e, i, &phdr) != &phdr) {
140       fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
141       break;
142     }
143
144     mp = modelFromPhdr(&phdr);
145
146     if (mp) {
147       CIRCLEQ_INSERT_TAIL(&me->phdrList, mp, elem);
148     } else {
149       goto out;
150     }
151   }
152
153
154
155   return me;
156
157   out:
158   // FIXME
159   return NULL;
160 }