summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornorly <ny-git@enpas.org>2013-06-20 23:47:01 +0100
committernorly <ny-git@enpas.org>2013-06-21 00:42:22 +0100
commite68a6c6cc16279c72e270daae0548ea7c0f11c6e (patch)
tree1bb268b01d557bf64744c1a0794acea2fad9286b
parentfb56823e86ceff5e340a691ef2a6d5df81e02fac (diff)
LOAD PHDRs at top level, others as children. mPhdrForall().
The reference binaries had to be updated as PHDRs are now reordered.
-rw-r--r--include/libelfu/modelops.h2
-rw-r--r--src/libelfu/model/phdr.c51
-rw-r--r--src/libelfu/modelops/fromFile.c2
-rw-r--r--src/libelfu/modelops/toFile.c37
-rwxr-xr-xtests/reference/putsmain32-clonedbin6104 -> 6104 bytes
-rwxr-xr-xtests/reference/putsmain32-with-puts-alternative32bin18696 -> 18696 bytes
6 files changed, 66 insertions, 26 deletions
diff --git a/include/libelfu/modelops.h b/include/libelfu/modelops.h
index afe6b96..e5702f7 100644
--- a/include/libelfu/modelops.h
+++ b/include/libelfu/modelops.h
@@ -18,6 +18,8 @@ void elfu_mSymtabFlatten(ElfuElf *me);
void elfu_mRelocate(ElfuElf *metarget, ElfuScn *mstarget, ElfuScn *msrt);
+typedef void* (PhdrHandlerFunc)(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2);
+ void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2);
size_t elfu_mPhdrCount(ElfuElf *me);
void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp);
ElfuPhdr* elfu_mPhdrAlloc();
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);
}
diff --git a/tests/reference/putsmain32-cloned b/tests/reference/putsmain32-cloned
index 58328b4..973ea9c 100755
--- a/tests/reference/putsmain32-cloned
+++ b/tests/reference/putsmain32-cloned
Binary files differ
diff --git a/tests/reference/putsmain32-with-puts-alternative32 b/tests/reference/putsmain32-with-puts-alternative32
index 953ddad..c820ef5 100755
--- a/tests/reference/putsmain32-with-puts-alternative32
+++ b/tests/reference/putsmain32-with-puts-alternative32
Binary files differ