Reorder PHDRs according to ELF spec
[centaur.git] / src / libelfu / modelops / toFile.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <libelfu/libelfu.h>
5
6
7 static void* modelToPhdr(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
8 {
9   size_t *i = (size_t*)aux1;
10   Elf *e = (Elf*)aux2;
11
12   if (!gelf_update_phdr (e, *i, &mp->phdr)) {
13     ELFU_WARNELF("gelf_update_phdr");
14   }
15
16   *i += 1;
17
18   /* Continue */
19   return NULL;
20 }
21
22
23 static void* modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
24 {
25   Elf_Scn *scnOut;
26   Elf *e = (Elf*)aux1;
27   (void) me;
28   (void) aux2;
29
30   scnOut = elf_newscn(e);
31   if (!scnOut) {
32     ELFU_WARNELF("elf_newscn");
33     return (void*)-1;
34   }
35
36
37   /* SHDR */
38   if (ms->linkptr) {
39     ms->shdr.sh_link = elfu_mScnIndex(me, ms->linkptr);
40   }
41   if (ms->infoptr) {
42     ms->shdr.sh_info = elfu_mScnIndex(me, ms->infoptr);
43   }
44   if (!gelf_update_shdr(scnOut, &ms->shdr)) {
45     ELFU_WARNELF("gelf_update_shdr");
46   }
47
48
49   /* Data */
50   if (ms->databuf) {
51     Elf_Data *dataOut = elf_newdata(scnOut);
52     if (!dataOut) {
53       ELFU_WARNELF("elf_newdata");
54     }
55
56     dataOut->d_align = 1;
57     dataOut->d_buf  = ms->databuf;
58     dataOut->d_off  = 0;
59     dataOut->d_type = ELF_T_BYTE;
60     dataOut->d_size = ms->shdr.sh_size;
61     dataOut->d_version = elf_version(EV_NONE);
62   }
63
64   return NULL;
65 }
66
67
68
69
70
71 void elfu_mToElf(ElfuElf *me, Elf *e)
72 {
73   size_t i = 0;
74
75   if (me->symtab) {
76     elfu_mSymtabFlatten(me);
77   }
78
79
80   /* We control the ELF file's layout now. */
81   /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections,
82    * but we don't want that since we filtered it out in the reading stage
83    * already. It would be too mind-blowing to handle the dependencies between
84    * the PHDRs and sections then... */
85   elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
86
87
88   /* EHDR */
89   if (!gelf_newehdr(e, me->elfclass)) {
90     ELFU_WARNELF("gelf_newehdr");
91   }
92
93   if (me->shstrtab) {
94     me->ehdr.e_shstrndx = elfu_mScnIndex(me, me->shstrtab);
95   }
96
97   if (!gelf_update_ehdr(e, &me->ehdr)) {
98     ELFU_WARNELF("gelf_update_ehdr");
99   }
100
101
102   /* Sections */
103   elfu_mScnForall(me, modelToSection, e, NULL);
104
105
106   /* PHDRs */
107   if (!gelf_newphdr(e, elfu_mPhdrCount(me))) {
108     ELFU_WARNELF("gelf_newphdr");
109   }
110
111   elfu_mPhdrForall(me, modelToPhdr, &i, e);
112
113   elfu_eReorderPhdrs(e);
114
115
116   /* Done */
117   elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
118 }