GPLv2 release
[centaur.git] / src / libelfu / modelops / toFile.c
1 /* This file is part of centaur.
2  *
3  * centaur is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License 2 as
5  * published by the Free Software Foundation.
6
7  * centaur is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11
12  * You should have received a copy of the GNU General Public License
13  * along with centaur.  If not, see <http://www.gnu.org/licenses/>.
14  */
15
16 #include <assert.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <libelfu/libelfu.h>
20
21
22 static void* modelToPhdr(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2)
23 {
24   size_t *i = (size_t*)aux1;
25   Elf *e = (Elf*)aux2;
26
27   if (!gelf_update_phdr (e, *i, &mp->phdr)) {
28     ELFU_WARNELF("gelf_update_phdr");
29   }
30
31   *i += 1;
32
33   /* Continue */
34   return NULL;
35 }
36
37
38 static void* modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
39 {
40   Elf_Scn *scnOut;
41   Elf *e = (Elf*)aux1;
42   (void) me;
43   (void) aux2;
44
45   scnOut = elf_newscn(e);
46   if (!scnOut) {
47     ELFU_WARNELF("elf_newscn");
48     return (void*)-1;
49   }
50
51
52   /* SHDR */
53   if (ms->linkptr) {
54     ms->shdr.sh_link = elfu_mScnIndex(me, ms->linkptr);
55   }
56   if (ms->infoptr) {
57     ms->shdr.sh_info = elfu_mScnIndex(me, ms->infoptr);
58   }
59   if (!gelf_update_shdr(scnOut, &ms->shdr)) {
60     ELFU_WARNELF("gelf_update_shdr");
61   }
62
63
64   /* Data */
65   if (ms->databuf) {
66     Elf_Data *dataOut = elf_newdata(scnOut);
67     if (!dataOut) {
68       ELFU_WARNELF("elf_newdata");
69     }
70
71     dataOut->d_align = 1;
72     dataOut->d_buf  = ms->databuf;
73     dataOut->d_off  = 0;
74     dataOut->d_type = ELF_T_BYTE;
75     dataOut->d_size = ms->shdr.sh_size;
76     dataOut->d_version = elf_version(EV_NONE);
77   }
78
79   return NULL;
80 }
81
82
83
84
85
86 void elfu_mToElf(ElfuElf *me, Elf *e)
87 {
88   size_t i = 0;
89
90   if (me->symtab) {
91     elfu_mSymtabFlatten(me);
92   }
93
94
95   /* We control the ELF file's layout now. */
96   /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections,
97    * but we don't want that since we filtered it out in the reading stage
98    * already. It would be too mind-blowing to handle the dependencies between
99    * the PHDRs and sections then... */
100   elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
101
102
103   /* EHDR */
104   if (!gelf_newehdr(e, me->elfclass)) {
105     ELFU_WARNELF("gelf_newehdr");
106   }
107
108   if (me->shstrtab) {
109     me->ehdr.e_shstrndx = elfu_mScnIndex(me, me->shstrtab);
110   }
111
112   if (!gelf_update_ehdr(e, &me->ehdr)) {
113     ELFU_WARNELF("gelf_update_ehdr");
114   }
115
116
117   /* Sections */
118   elfu_mScnForall(me, modelToSection, e, NULL);
119
120
121   /* PHDRs */
122   if (!gelf_newphdr(e, elfu_mPhdrCount(me))) {
123     ELFU_WARNELF("gelf_newphdr");
124   }
125
126   elfu_mPhdrForall(me, modelToPhdr, &i, e);
127
128   elfu_eReorderPhdrs(e);
129
130
131   /* Done */
132   elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
133 }