4 #include <libelfu/libelfu.h>
9 void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2)
13 CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
15 void *rv = f(me, mp, aux1, aux2);
20 CIRCLEQ_FOREACH(mp2, &mp->childPhdrList, elemChildPhdr) {
21 void *rv = f(me, mp2, aux1, aux2);
36 static void* subCounter(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
38 size_t *i = (size_t*)aux1;
47 size_t elfu_mPhdrCount(ElfuElf *me)
53 elfu_mPhdrForall(me, subCounter, &i, NULL);
61 /* Finding by exact address/offset */
63 static void* subFindLoadByAddr(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
65 GElf_Addr addr = *(GElf_Addr*)aux1;
68 if (mp->phdr.p_type == PT_LOAD
69 && FULLY_OVERLAPPING(mp->phdr.p_vaddr, mp->phdr.p_memsz, addr, 1)) {
77 ElfuPhdr* elfu_mPhdrByAddr(ElfuElf *me, GElf_Addr addr)
79 return elfu_mPhdrForall(me, subFindLoadByAddr, &addr, NULL);
83 static void* subFindLoadByOffset(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
85 GElf_Off offset = *(GElf_Off*)aux1;
88 if (mp->phdr.p_type == PT_LOAD
89 && FULLY_OVERLAPPING(mp->phdr.p_offset, mp->phdr.p_filesz, offset, 1)) {
97 ElfuPhdr* elfu_mPhdrByOffset(ElfuElf *me, GElf_Off offset)
99 return elfu_mPhdrForall(me, subFindLoadByOffset, &offset, NULL);
105 /* Find lowest/highest address/offset */
107 void elfu_mPhdrLoadLowestHighest(ElfuElf *me,
108 ElfuPhdr **lowestAddr, ElfuPhdr **highestAddr,
109 ElfuPhdr **lowestOffs, ElfuPhdr **highestOffsEnd)
117 assert(highestOffsEnd);
122 *highestOffsEnd = NULL;
124 /* Find first and last LOAD PHDRs.
125 * Don't compare p_memsz - segments don't overlap in memory. */
126 CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
127 if (mp->phdr.p_type != PT_LOAD) {
130 if (!*lowestAddr || mp->phdr.p_vaddr < (*lowestAddr)->phdr.p_vaddr) {
133 if (!*highestAddr || mp->phdr.p_vaddr > (*highestAddr)->phdr.p_vaddr) {
136 if (!*lowestOffs || mp->phdr.p_offset < (*lowestOffs)->phdr.p_offset) {
140 || (OFFS_END(mp->phdr.p_offset,
142 > OFFS_END((*highestOffsEnd)->phdr.p_offset,
143 (*highestOffsEnd)->phdr.p_filesz))) {
144 *highestOffsEnd = mp;
154 void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp)
160 assert(mp->phdr.p_type == PT_LOAD);
162 CIRCLEQ_FOREACH(mpc, &mp->childPhdrList, elemChildPhdr) {
163 mpc->phdr.p_offset = mp->phdr.p_offset + (mpc->phdr.p_vaddr - mp->phdr.p_vaddr);
166 CIRCLEQ_FOREACH(ms, &mp->childScnList, elemChildScn) {
167 ms->shdr.sh_offset = mp->phdr.p_offset + (ms->shdr.sh_addr - mp->phdr.p_vaddr);
174 * Allocation, destruction
177 ElfuPhdr* elfu_mPhdrAlloc()
181 mp = malloc(sizeof(ElfuPhdr));
183 ELFU_WARN("mPhdrAlloc: malloc() failed for ElfuPhdr.\n");
187 memset(mp, 0, sizeof(*mp));
189 CIRCLEQ_INIT(&mp->childScnList);
190 CIRCLEQ_INIT(&mp->childPhdrList);
195 void elfu_mPhdrDestroy(ElfuPhdr* mp)
202 CIRCLEQ_FOREACH(mp2, &mp->childPhdrList, elemChildPhdr) {
203 CIRCLEQ_REMOVE(&mp->childPhdrList, mp2, elemChildPhdr);
204 elfu_mPhdrDestroy(mp2);
207 CIRCLEQ_FOREACH(ms, &mp->childScnList, elemChildScn) {
208 CIRCLEQ_REMOVE(&mp->childScnList, ms, elemChildScn);
209 elfu_mScnDestroy(ms);