Redesign data structures, make basic reladd work.
[centaur.git] / src / model / toFile.c
index 294cfe458ce82a18c3dd8e79bc1415f569a44a05..9410f134c117ad1fa6b472c7564e93860848b2b4 100644 (file)
@@ -1,37 +1,30 @@
-#include <stdio.h>
 #include <stdlib.h>
-
-#include <libelf.h>
-#include <gelf.h>
-
+#include <libelf/libelf.h>
+#include <libelf/gelf.h>
 #include <libelfu/libelfu.h>
 
 
 
-static void elfu_modelToPhdrs(ElfuElf *me, Elf *e)
+static void 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) {
+  CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
     i++;
   }
 
   if (!gelf_newphdr(e, i)) {
-    fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1));
+    ELFU_WARNELF("gelf_newphdr");
   }
 
   /* Copy PHDRs */
   i = 0;
-  for (mp = me->phdrList.cqh_first;
-        mp != (void *)&me->phdrList;
-        mp = mp->elem.cqe_next) {
+  CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
     if (!gelf_update_phdr (e, i, &mp->phdr)) {
-      fprintf(stderr, "gelf_update_phdr() failed: %s\n", elf_errmsg(-1));
+      ELFU_WARNELF("gelf_update_phdr");
     }
 
     i++;
@@ -40,75 +33,84 @@ static void elfu_modelToPhdrs(ElfuElf *me, Elf *e)
 
 
 
-static void elfu_modelToSection(ElfuScn *ms, Elf *e)
+static int modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
 {
+  (void) me;
+  (void) aux2;
+  Elf *e = (Elf*)aux1;
   Elf_Scn *scnOut;
 
   scnOut = elf_newscn(e);
   if (!scnOut) {
-    fprintf(stderr, "elf_newscn() failed: %s\n", elf_errmsg(-1));
-    return;
+    ELFU_WARNELF("elf_newscn");
+    return 1;
   }
 
 
   /* SHDR */
+  if (ms->linkptr) {
+    ms->shdr.sh_link = elfu_mScnIndex(me, ms->linkptr);
+  }
+  if (ms->infoptr) {
+    ms->shdr.sh_info = elfu_mScnIndex(me, ms->infoptr);
+  }
   if (!gelf_update_shdr(scnOut, &ms->shdr)) {
-    fprintf(stderr, "gelf_update_shdr() failed: %s\n", elf_errmsg(-1));
+    ELFU_WARNELF("gelf_update_shdr");
   }
 
 
   /* Data */
-  ElfuData *md;
-  for (md = ms->dataList.cqh_first;
-        md != (void *)&ms->dataList;
-        md = md->elem.cqe_next) {
+  if (ms->data.d_buf) {
     Elf_Data *dataOut = elf_newdata(scnOut);
     if (!dataOut) {
-      fprintf(stderr, "elf_newdata() failed: %s\n", elf_errmsg(-1));
+      ELFU_WARNELF("elf_newdata");
     }
 
-    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;
+    dataOut->d_align = ms->data.d_align;
+    dataOut->d_buf  = ms->data.d_buf;
+    dataOut->d_off  = ms->data.d_off;
+    dataOut->d_type = ms->data.d_type;
+    dataOut->d_size = ms->data.d_size;
+    dataOut->d_version = ms->data.d_version;
   }
+
+  return 0;
 }
 
 
 
 
 
-void elfu_modelToElf(ElfuElf *me, Elf *e)
+void elfu_mToElf(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. */
+  /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections,
+   * but we don't want that since we filtered it out in the reading stage
+   * already. It would be too mind-blowing to handle the dependencies between
+   * the PHDRs and sections then... */
   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));
+    ELFU_WARNELF("gelf_newehdr");
+  }
+
+  if (me->shstrtab) {
+    me->ehdr.e_shstrndx = elfu_mScnIndex(me, me->shstrtab);
   }
 
   if (!gelf_update_ehdr(e, &me->ehdr)) {
-    fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1));
+    ELFU_WARNELF("gelf_update_ehdr");
   }
 
 
   /* Sections */
-  for (ms = me->scnList.cqh_first;
-        ms != (void *)&me->scnList;
-        ms = ms->elem.cqe_next) {
-    elfu_modelToSection(ms, e);
-  }
+  elfu_mScnForall(me, modelToSection, e, NULL);
 
 
   /* PHDRs */
-  elfu_modelToPhdrs(me, e);
+  modelToPhdrs(me, e);
 
 
   elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);