399c25b6131fad0d7a285272fa1b68e0f5a7f208
[centaur.git] / src / model / toFile.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <libelf.h>
5 #include <gelf.h>
6
7 #include <libelfu/libelfu.h>
8
9
10
11 static void elfu_modelToPhdrs(ElfuElf *me, Elf *e)
12 {
13   ElfuPhdr *mp;
14   size_t i;
15
16   /* Count PHDRs */
17   i = 0;
18   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
19     i++;
20   }
21
22   if (!gelf_newphdr(e, i)) {
23     fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1));
24   }
25
26   /* Copy PHDRs */
27   i = 0;
28   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
29     if (!gelf_update_phdr (e, i, &mp->phdr)) {
30       fprintf(stderr, "gelf_update_phdr() failed: %s\n", elf_errmsg(-1));
31     }
32
33     i++;
34   }
35 }
36
37
38
39 static void elfu_modelToSection(ElfuScn *ms, Elf *e)
40 {
41   Elf_Scn *scnOut;
42
43   scnOut = elf_newscn(e);
44   if (!scnOut) {
45     fprintf(stderr, "elf_newscn() failed: %s\n", elf_errmsg(-1));
46     return;
47   }
48
49
50   /* SHDR */
51   if (!gelf_update_shdr(scnOut, &ms->shdr)) {
52     fprintf(stderr, "gelf_update_shdr() failed: %s\n", elf_errmsg(-1));
53   }
54
55
56   /* Data */
57   ElfuData *md;
58   CIRCLEQ_FOREACH(md, &ms->dataList, elem) {
59     Elf_Data *dataOut = elf_newdata(scnOut);
60     if (!dataOut) {
61       fprintf(stderr, "elf_newdata() failed: %s\n", elf_errmsg(-1));
62     }
63
64     dataOut->d_align = md->data.d_align;
65     dataOut->d_buf  = md->data.d_buf;
66     dataOut->d_off  = md->data.d_off;
67     dataOut->d_type = md->data.d_type;
68     dataOut->d_size = md->data.d_size;
69     dataOut->d_version = md->data.d_version;
70   }
71 }
72
73
74
75
76
77 void elfu_modelToElf(ElfuElf *me, Elf *e)
78 {
79   ElfuScn *ms;
80
81   /* We control the ELF file's layout now. */
82   /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections. */
83   elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
84
85
86   /* EHDR */
87   if (!gelf_newehdr(e, me->elfclass)) {
88     fprintf(stderr, "gelf_newehdr() failed: %s\n", elf_errmsg(-1));
89   }
90
91   if (!gelf_update_ehdr(e, &me->ehdr)) {
92     fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1));
93   }
94
95
96   /* Sections */
97   CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
98     elfu_modelToSection(ms, e);
99   }
100
101
102   /* PHDRs */
103   elfu_modelToPhdrs(me, e);
104
105
106   elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
107 }