1159fbb56c3988790c7d5c66544d778955294f2d
[centaur.git] / src / libelfu / model / phdr.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <libelfu/libelfu.h>
5
6
7 /* Meta-functions */
8
9 void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2)
10 {
11   ElfuPhdr *mp;
12
13   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
14     ElfuPhdr *mp2;
15     void *rv = f(me, mp, aux1, aux2);
16     if (rv) {
17       return rv;
18     }
19
20     CIRCLEQ_FOREACH(mp2, &mp->childPhdrList, elemChildPhdr) {
21       void *rv = f(me, mp2, aux1, aux2);
22       if (rv) {
23         return rv;
24       }
25     }
26   }
27
28   return NULL;
29 }
30
31
32
33
34 /* Counting */
35
36 static void* subCounter(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
37 {
38   size_t *i = (size_t*)aux1;
39   (void)aux2;
40
41   *i += 1;
42
43   /* Continue */
44   return NULL;
45 }
46
47
48 size_t elfu_mPhdrCount(ElfuElf *me)
49 {
50   size_t i = 0;
51
52   assert(me);
53
54   elfu_mPhdrForall(me, subCounter, &i, NULL);
55
56   return i;
57 }
58
59
60
61 /* Layout update */
62
63 void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp)
64 {
65   ElfuScn *ms;
66   ElfuPhdr *mpc;
67
68   assert(mp);
69   assert(mp->phdr.p_type == PT_LOAD);
70
71   CIRCLEQ_FOREACH(mpc, &mp->childPhdrList, elemChildPhdr) {
72     mpc->phdr.p_offset = mp->phdr.p_offset + (mpc->phdr.p_vaddr - mp->phdr.p_vaddr);
73   }
74
75   CIRCLEQ_FOREACH(ms, &mp->childScnList, elemChildScn) {
76     ms->shdr.sh_offset = mp->phdr.p_offset + (ms->shdr.sh_addr - mp->phdr.p_vaddr);
77   }
78 }
79
80
81
82 /*
83  * Allocation, destruction
84  */
85
86 ElfuPhdr* elfu_mPhdrAlloc()
87 {
88   ElfuPhdr *mp;
89
90   mp = malloc(sizeof(ElfuPhdr));
91   if (!mp) {
92     ELFU_WARN("mPhdrAlloc: malloc() failed for ElfuPhdr.\n");
93     return NULL;
94   }
95
96   memset(mp, 0, sizeof(*mp));
97
98   CIRCLEQ_INIT(&mp->childScnList);
99   CIRCLEQ_INIT(&mp->childPhdrList);
100
101   return mp;
102 }
103
104 void elfu_mPhdrDestroy(ElfuPhdr* mp)
105 {
106   ElfuPhdr *mp2;
107   ElfuScn *ms;
108
109   assert(mp);
110
111   CIRCLEQ_FOREACH(mp2, &mp->childPhdrList, elem) {
112     CIRCLEQ_REMOVE(&mp->childPhdrList, mp2, elem);
113     elfu_mPhdrDestroy(mp2);
114   }
115
116   CIRCLEQ_FOREACH(ms, &mp->childScnList, elem) {
117     CIRCLEQ_REMOVE(&mp->childScnList, ms, elem);
118     elfu_mScnDestroy(ms);
119   }
120
121   free(mp);
122 }