4b8b230baf2294b1d0a4ee76d413af8fb66c5c8f
[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 int 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       int 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     int rv = f(me, ms, aux1, aux2);
31
32     if (rv) {
33       return rv;
34     }
35   }
36
37   return 0;
38 }
39
40
41
42
43 /* Counting */
44
45 static int 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 1;
52   }
53
54   *i += 1;
55
56   return 0;
57 }
58
59
60 size_t elfu_mScnCount(ElfuElf *me)
61 {
62   /* NULL section *is not* counted */
63   size_t i = 0;
64
65   assert(me);
66
67   elfu_mScnForall(me, subCounter, &i, NULL);
68
69   return i;
70 }
71
72
73 /* Returns the section index equivalent to the model flattened to ELF */
74 size_t elfu_mScnIndex(ElfuElf *me, ElfuScn *ms)
75 {
76   /* NULL section *is* counted */
77   size_t i = 1;
78
79   assert(me);
80   assert(ms);
81
82   elfu_mScnForall(me, subCounter, &i, ms);
83
84   /* If this assertion is broken then ms is not a section in me. */
85   assert(i <= elfu_mScnCount(me));
86   return i;
87 }
88
89
90
91
92 /* Convenience */
93
94 char* elfu_mScnName(ElfuElf *me, ElfuScn *ms)
95 {
96   assert(me);
97   assert(ms);
98
99   if (!me->shstrtab) {
100     return NULL;
101   }
102
103   if (!me->shstrtab->data.d_buf) {
104     return NULL;
105   }
106
107   return &((char*)me->shstrtab->data.d_buf)[ms->shdr.sh_name];
108 }
109
110
111 static int subScnsToArray(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
112 {
113   ElfuScn **arr = (ElfuScn**)aux1;
114   size_t *i = (size_t*)aux2;
115
116   arr[(*i)] = ms;
117   *i += 1;
118
119   return 0;
120 }
121
122 static int cmpScnOffs(const void *ms1, const void *ms2)
123 {
124   assert(ms1);
125   assert(ms2);
126
127   ElfuScn *s1 = *(ElfuScn**)ms1;
128   ElfuScn *s2 = *(ElfuScn**)ms2;
129
130   assert(s1);
131   assert(s2);
132
133
134   if (s1->shdr.sh_offset < s2->shdr.sh_offset) {
135     return -1;
136   } else if (s1->shdr.sh_offset == s2->shdr.sh_offset) {
137     return 0;
138   } else /* if (s1->shdr.sh_offset > s2->shdr.sh_offset) */ {
139     return 1;
140   }
141 }
142
143 ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count)
144 {
145   assert(me);
146
147   size_t numSecs;
148   ElfuScn **sortedSecs;
149   size_t i;
150
151   /* Sort sections by offset in file */
152   numSecs = elfu_mScnCount(me);
153   sortedSecs = malloc(numSecs * sizeof(*sortedSecs));
154   if (!sortedSecs) {
155     ELFU_WARN("elfu_mScnSortedByOffset: Failed to allocate memory.\n");
156     return NULL;
157   }
158
159   i = 0;
160   elfu_mScnForall(me, subScnsToArray, sortedSecs, &i);
161   assert(i == numSecs);
162
163   qsort(sortedSecs, numSecs, sizeof(*sortedSecs), cmpScnOffs);
164
165   *count = numSecs;
166
167   return sortedSecs;
168 }