Do not insert STRTAB sections explicitly
[centaur.git] / src / model / section.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <libelfu/libelfu.h>
4
5
6 /* Meta-functions */
7
8 void* elfu_mScnForall(ElfuElf *me, SectionHandlerFunc f, void *aux1, void *aux2)
9 {
10   ElfuPhdr *mp;
11   ElfuScn *ms;
12
13   // TODO: Sort PHDRs by offset before interating
14
15   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
16     if (mp->phdr.p_type != PT_LOAD) {
17       continue;
18     }
19
20     CIRCLEQ_FOREACH(ms, &mp->childScnList, elemChildScn) {
21       void *rv = f(me, ms, aux1, aux2);
22
23       if (rv) {
24         return rv;
25       }
26     }
27   }
28
29   CIRCLEQ_FOREACH(ms, &me->orphanScnList, elemChildScn) {
30     void *rv = f(me, ms, aux1, aux2);
31
32     if (rv) {
33       return rv;
34     }
35   }
36
37   return NULL;
38 }
39
40
41
42
43 /* Counting */
44
45 static void* subCounter(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
46 {
47   size_t *i = (size_t*)aux1;
48   ElfuScn *otherScn = (ElfuScn*)aux2;
49
50   if (ms == otherScn) {
51     return ms;
52   }
53
54   *i += 1;
55
56   /* Continue */
57   return NULL;
58 }
59
60
61 size_t elfu_mScnCount(ElfuElf *me)
62 {
63   /* NULL section *is not* counted */
64   size_t i = 0;
65
66   assert(me);
67
68   elfu_mScnForall(me, subCounter, &i, NULL);
69
70   return i;
71 }
72
73
74 /* Returns the index a section would have in the flattened ELF */
75 size_t elfu_mScnIndex(ElfuElf *me, ElfuScn *ms)
76 {
77   /* NULL section *is* counted */
78   size_t i = 1;
79
80   assert(me);
81   assert(ms);
82
83   elfu_mScnForall(me, subCounter, &i, ms);
84
85   /* If this assertion is broken then ms is not a section in me. */
86   assert(i <= elfu_mScnCount(me));
87   return i;
88 }
89
90
91 static void* subOldscn(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
92 {
93   ElfuScn *otherScn = (ElfuScn*)aux1;
94   (void)aux2;
95
96   if (ms->oldptr == otherScn) {
97     return ms;
98   }
99
100   /* Continue */
101   return NULL;
102 }
103
104 /* Returns the section with oldscn == oldscn */
105 ElfuScn* elfu_mScnByOldscn(ElfuElf *me, ElfuScn *oldscn)
106 {
107   assert(me);
108   assert(oldscn);
109
110   return elfu_mScnForall(me, subOldscn, oldscn, NULL);
111 }
112
113
114
115
116 /* Convenience */
117
118 char* elfu_mScnName(ElfuElf *me, ElfuScn *ms)
119 {
120   assert(me);
121   assert(ms);
122
123   if (!me->shstrtab) {
124     return NULL;
125   }
126
127   if (!me->shstrtab->data.d_buf) {
128     return NULL;
129   }
130
131   return &((char*)me->shstrtab->data.d_buf)[ms->shdr.sh_name];
132 }
133
134
135 static void* subScnsToArray(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
136 {
137   ElfuScn **arr = (ElfuScn**)aux1;
138   size_t *i = (size_t*)aux2;
139
140   arr[(*i)] = ms;
141   *i += 1;
142
143   /* Continue */
144   return NULL;
145 }
146
147 static int cmpScnOffs(const void *ms1, const void *ms2)
148 {
149   assert(ms1);
150   assert(ms2);
151
152   ElfuScn *s1 = *(ElfuScn**)ms1;
153   ElfuScn *s2 = *(ElfuScn**)ms2;
154
155   assert(s1);
156   assert(s2);
157
158
159   if (s1->shdr.sh_offset < s2->shdr.sh_offset) {
160     return -1;
161   } else if (s1->shdr.sh_offset == s2->shdr.sh_offset) {
162     return 0;
163   } else /* if (s1->shdr.sh_offset > s2->shdr.sh_offset) */ {
164     return 1;
165   }
166 }
167
168 ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count)
169 {
170   assert(me);
171
172   size_t numSecs;
173   ElfuScn **sortedSecs;
174   size_t i;
175
176   /* Sort sections by offset in file */
177   numSecs = elfu_mScnCount(me);
178   sortedSecs = malloc(numSecs * sizeof(*sortedSecs));
179   if (!sortedSecs) {
180     ELFU_WARN("elfu_mScnSortedByOffset: Failed to allocate memory.\n");
181     return NULL;
182   }
183
184   i = 0;
185   elfu_mScnForall(me, subScnsToArray, sortedSecs, &i);
186   assert(i == numSecs);
187
188   qsort(sortedSecs, numSecs, sizeof(*sortedSecs), cmpScnOffs);
189
190   *count = numSecs;
191
192   return sortedSecs;
193 }