summaryrefslogtreecommitdiff
path: root/src/libelfu
diff options
context:
space:
mode:
Diffstat (limited to 'src/libelfu')
-rw-r--r--src/libelfu/model/phdr.c51
-rw-r--r--src/libelfu/modelops/fromFile.c2
-rw-r--r--src/libelfu/modelops/toFile.c37
3 files changed, 64 insertions, 26 deletions
diff --git a/src/libelfu/model/phdr.c b/src/libelfu/model/phdr.c
index 6896845..1159fbb 100644
--- a/src/libelfu/model/phdr.c
+++ b/src/libelfu/model/phdr.c
@@ -4,22 +4,62 @@
#include <libelfu/libelfu.h>
-size_t elfu_mPhdrCount(ElfuElf *me)
+/* Meta-functions */
+
+void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2)
{
ElfuPhdr *mp;
+
+ CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
+ ElfuPhdr *mp2;
+ void *rv = f(me, mp, aux1, aux2);
+ if (rv) {
+ return rv;
+ }
+
+ CIRCLEQ_FOREACH(mp2, &mp->childPhdrList, elemChildPhdr) {
+ void *rv = f(me, mp2, aux1, aux2);
+ if (rv) {
+ return rv;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
+/* Counting */
+
+static void* subCounter(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
+{
+ size_t *i = (size_t*)aux1;
+ (void)aux2;
+
+ *i += 1;
+
+ /* Continue */
+ return NULL;
+}
+
+
+size_t elfu_mPhdrCount(ElfuElf *me)
+{
size_t i = 0;
assert(me);
- CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
- i++;
- }
+ elfu_mPhdrForall(me, subCounter, &i, NULL);
return i;
}
+/* Layout update */
+
void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp)
{
ElfuScn *ms;
@@ -69,7 +109,8 @@ void elfu_mPhdrDestroy(ElfuPhdr* mp)
assert(mp);
CIRCLEQ_FOREACH(mp2, &mp->childPhdrList, elem) {
- // TODO ?
+ CIRCLEQ_REMOVE(&mp->childPhdrList, mp2, elem);
+ elfu_mPhdrDestroy(mp2);
}
CIRCLEQ_FOREACH(ms, &mp->childScnList, elem) {
diff --git a/src/libelfu/modelops/fromFile.c b/src/libelfu/modelops/fromFile.c
index e19df7b..c4e8c45 100644
--- a/src/libelfu/modelops/fromFile.c
+++ b/src/libelfu/modelops/fromFile.c
@@ -340,6 +340,8 @@ ElfuElf* elfu_mFromElf(Elf *e)
if (mp->phdr.p_vaddr <= mp2->phdr.p_vaddr
&& OFFS_END(mp2->phdr.p_vaddr, mp2->phdr.p_memsz) <= OFFS_END(mp->phdr.p_vaddr, mp->phdr.p_memsz)) {
+ /* Remove from the main list so only LOADs remain there */
+ CIRCLEQ_REMOVE(&me->phdrList, mp2, elem);
CIRCLEQ_INSERT_TAIL(&mp->childPhdrList, mp2, elemChildPhdr);
}
}
diff --git a/src/libelfu/modelops/toFile.c b/src/libelfu/modelops/toFile.c
index ff01390..b42bc08 100644
--- a/src/libelfu/modelops/toFile.c
+++ b/src/libelfu/modelops/toFile.c
@@ -4,34 +4,22 @@
#include <libelfu/libelfu.h>
-static void modelToPhdrs(ElfuElf *me, Elf *e)
+static void* modelToPhdr(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
{
- ElfuPhdr *mp;
- size_t i;
+ size_t *i = (size_t*)aux1;
+ Elf *e = (Elf*)aux2;
- /* Count PHDRs */
- i = 0;
- CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
- i++;
+ if (!gelf_update_phdr (e, *i, &mp->phdr)) {
+ ELFU_WARNELF("gelf_update_phdr");
}
- if (!gelf_newphdr(e, i)) {
- ELFU_WARNELF("gelf_newphdr");
- }
-
- /* Copy PHDRs */
- i = 0;
- CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
- if (!gelf_update_phdr (e, i, &mp->phdr)) {
- ELFU_WARNELF("gelf_update_phdr");
- }
+ *i += 1;
- i++;
- }
+ /* Continue */
+ return NULL;
}
-
static void* modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
{
Elf_Scn *scnOut;
@@ -82,6 +70,8 @@ static void* modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
void elfu_mToElf(ElfuElf *me, Elf *e)
{
+ size_t i = 0;
+
if (me->symtab) {
elfu_mSymtabFlatten(me);
}
@@ -114,8 +104,13 @@ void elfu_mToElf(ElfuElf *me, Elf *e)
/* PHDRs */
- modelToPhdrs(me, e);
+ if (!gelf_newphdr(e, elfu_mPhdrCount(me))) {
+ ELFU_WARNELF("gelf_newphdr");
+ }
+
+ elfu_mPhdrForall(me, modelToPhdr, &i, e);
+ /* Done */
elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
}