summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libelfu/model.h2
-rw-r--r--src/main.c6
-rw-r--r--src/model/toFile.c115
3 files changed, 123 insertions, 0 deletions
diff --git a/include/libelfu/model.h b/include/libelfu/model.h
index 05f31ca..aaf754f 100644
--- a/include/libelfu/model.h
+++ b/include/libelfu/model.h
@@ -47,4 +47,6 @@ ElfuPhdr* elfu_modelFromPhdr(GElf_Phdr *phdr);
ElfuScn* elfu_modelFromSection(Elf_Scn *scn);
ElfuElf* elfu_modelFromElf(Elf *e);
+void elfu_modelToElf(ElfuElf *me, Elf *e);
+
#endif
diff --git a/src/main.c b/src/main.c
index e664829..4d41ee4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,6 +77,12 @@ int main(int argc, char **argv)
if (me) {
printf("Model successfully loaded.\n");
+
+ elfu_modelToElf(me, hOut.e);
+
+ printf("Model converted to ELF, ready to be written.\n");
+ } else {
+ printf("Failed to load model.\n");
}
}
diff --git a/src/model/toFile.c b/src/model/toFile.c
new file mode 100644
index 0000000..294cfe4
--- /dev/null
+++ b/src/model/toFile.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libelf.h>
+#include <gelf.h>
+
+#include <libelfu/libelfu.h>
+
+
+
+static void elfu_modelToPhdrs(ElfuElf *me, Elf *e)
+{
+ ElfuPhdr *mp;
+ size_t i;
+
+ /* Count PHDRs */
+ i = 0;
+ for (mp = me->phdrList.cqh_first;
+ mp != (void *)&me->phdrList;
+ mp = mp->elem.cqe_next) {
+ i++;
+ }
+
+ if (!gelf_newphdr(e, i)) {
+ fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1));
+ }
+
+ /* Copy PHDRs */
+ i = 0;
+ for (mp = me->phdrList.cqh_first;
+ mp != (void *)&me->phdrList;
+ mp = mp->elem.cqe_next) {
+ if (!gelf_update_phdr (e, i, &mp->phdr)) {
+ fprintf(stderr, "gelf_update_phdr() failed: %s\n", elf_errmsg(-1));
+ }
+
+ i++;
+ }
+}
+
+
+
+static void elfu_modelToSection(ElfuScn *ms, Elf *e)
+{
+ Elf_Scn *scnOut;
+
+ scnOut = elf_newscn(e);
+ if (!scnOut) {
+ fprintf(stderr, "elf_newscn() failed: %s\n", elf_errmsg(-1));
+ return;
+ }
+
+
+ /* SHDR */
+ if (!gelf_update_shdr(scnOut, &ms->shdr)) {
+ fprintf(stderr, "gelf_update_shdr() failed: %s\n", elf_errmsg(-1));
+ }
+
+
+ /* Data */
+ ElfuData *md;
+ for (md = ms->dataList.cqh_first;
+ md != (void *)&ms->dataList;
+ md = md->elem.cqe_next) {
+ Elf_Data *dataOut = elf_newdata(scnOut);
+ if (!dataOut) {
+ fprintf(stderr, "elf_newdata() failed: %s\n", elf_errmsg(-1));
+ }
+
+ dataOut->d_align = md->data.d_align;
+ dataOut->d_buf = md->data.d_buf;
+ dataOut->d_off = md->data.d_off;
+ dataOut->d_type = md->data.d_type;
+ dataOut->d_size = md->data.d_size;
+ dataOut->d_version = md->data.d_version;
+ }
+}
+
+
+
+
+
+void elfu_modelToElf(ElfuElf *me, Elf *e)
+{
+ ElfuScn *ms;
+
+ /* We control the ELF file's layout now. */
+ /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections. */
+ elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
+
+
+ /* EHDR */
+ if (!gelf_newehdr(e, me->elfclass)) {
+ fprintf(stderr, "gelf_newehdr() failed: %s\n", elf_errmsg(-1));
+ }
+
+ if (!gelf_update_ehdr(e, &me->ehdr)) {
+ fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1));
+ }
+
+
+ /* Sections */
+ for (ms = me->scnList.cqh_first;
+ ms != (void *)&me->scnList;
+ ms = ms->elem.cqe_next) {
+ elfu_modelToSection(ms, e);
+ }
+
+
+ /* PHDRs */
+ elfu_modelToPhdrs(me, e);
+
+
+ elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
+}