1 /* This file is part of centaur.
3 * centaur is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License 2 as
5 * published by the Free Software Foundation.
7 * centaur is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with centaur. If not, see <http://www.gnu.org/licenses/>.
19 #include <libelfu/libelfu.h>
24 void* elfu_mScnForall(ElfuElf *me, SectionHandlerFunc f, void *aux1, void *aux2)
29 CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
30 if (mp->phdr.p_type != PT_LOAD) {
34 CIRCLEQ_FOREACH(ms, &mp->childScnList, elemChildScn) {
35 void *rv = f(me, ms, aux1, aux2);
43 CIRCLEQ_FOREACH(ms, &me->orphanScnList, elemChildScn) {
44 void *rv = f(me, ms, aux1, aux2);
59 static void* subCounter(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
61 size_t *i = (size_t*)aux1;
62 ElfuScn *otherScn = (ElfuScn*)aux2;
75 size_t elfu_mScnCount(ElfuElf *me)
77 /* NULL section *is not* counted */
82 elfu_mScnForall(me, subCounter, &i, NULL);
88 /* Returns the index a section would have in the flattened ELF */
89 size_t elfu_mScnIndex(ElfuElf *me, ElfuScn *ms)
91 /* NULL section *is* counted */
97 elfu_mScnForall(me, subCounter, &i, ms);
99 /* If this assertion is broken then ms is not a section in me. */
100 assert(i <= elfu_mScnCount(me));
105 static void* subOldscn(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
107 ElfuScn *otherScn = (ElfuScn*)aux1;
110 if (ms->oldptr == otherScn) {
118 /* Returns the section with oldscn == oldscn */
119 ElfuScn* elfu_mScnByOldscn(ElfuElf *me, ElfuScn *oldscn)
124 return elfu_mScnForall(me, subOldscn, oldscn, NULL);
132 char* elfu_mScnName(ElfuElf *me, ElfuScn *ms)
141 if (!me->shstrtab->databuf) {
145 return &me->shstrtab->databuf[ms->shdr.sh_name];
149 static void* subScnsToArray(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
151 ElfuScn **arr = (ElfuScn**)aux1;
152 size_t *i = (size_t*)aux2;
161 static int cmpScnOffs(const void *ms1, const void *ms2)
169 s1 = *(ElfuScn**)ms1;
170 s2 = *(ElfuScn**)ms2;
176 if (s1->shdr.sh_offset < s2->shdr.sh_offset) {
178 } else if (s1->shdr.sh_offset == s2->shdr.sh_offset) {
180 } else /* if (s1->shdr.sh_offset > s2->shdr.sh_offset) */ {
185 ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count)
188 ElfuScn **sortedSecs;
193 /* Sort sections by offset in file */
194 numSecs = elfu_mScnCount(me);
195 sortedSecs = malloc(numSecs * sizeof(*sortedSecs));
197 ELFU_WARN("elfu_mScnSortedByOffset: Failed to allocate memory.\n");
202 elfu_mScnForall(me, subScnsToArray, sortedSecs, &i);
203 assert(i == numSecs);
205 qsort(sortedSecs, numSecs, sizeof(*sortedSecs), cmpScnOffs);
214 int elfu_mScnAppendData(ElfuScn *ms, void *buf, size_t len)
219 assert(ms->shdr.sh_type != SHT_NOBITS);
222 newbuf = realloc(ms->databuf, ms->shdr.sh_size + len);
224 ELFU_WARN("elfu_mScnAppendData: malloc() failed for newbuf.\n");
228 ms->databuf = newbuf;
229 memcpy(newbuf + ms->shdr.sh_size, buf, len);
230 ms->shdr.sh_size += len;
231 assert(ms->shdr.sh_size == ms->shdr.sh_size);
239 * Allocation, destruction
242 ElfuScn* elfu_mScnAlloc()
246 ms = malloc(sizeof(ElfuScn));
248 ELFU_WARN("mScnCreate: malloc() failed for ElfuScn.\n");
252 memset(ms, 0, sizeof(*ms));
254 CIRCLEQ_INIT(&ms->symtab.syms);
255 CIRCLEQ_INIT(&ms->reltab.rels);
260 void elfu_mScnDestroy(ElfuScn* ms)
264 if (!CIRCLEQ_EMPTY(&ms->symtab.syms)) {
267 nextsym = CIRCLEQ_FIRST(&ms->symtab.syms);
268 while ((void*)nextsym != (void*)&ms->symtab.syms) {
269 ElfuSym *cursym = nextsym;
270 nextsym = CIRCLEQ_NEXT(cursym, elem);
271 CIRCLEQ_REMOVE(&ms->symtab.syms, cursym, elem);
276 if (!CIRCLEQ_EMPTY(&ms->reltab.rels)) {
279 nextrel = CIRCLEQ_FIRST(&ms->reltab.rels);
280 while ((void*)nextrel != (void*)&ms->reltab.rels) {
281 ElfuRel *currel = nextrel;
282 nextrel = CIRCLEQ_NEXT(currel, elem);
283 CIRCLEQ_REMOVE(&ms->reltab.rels, currel, elem);