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