Fix stupid copy
[centaur.git] / src / copy / segments.c
1 #include <stdio.h>
2
3 #include <libelf.h>
4 #include <gelf.h>
5
6 #include <libelfu/libelfu.h>
7
8
9
10 void elfu_copySegments1(Elf *eo, Elf *ei)
11 {
12   size_t i, n;
13
14   if (elf_getphdrnum(ei, &n)) {
15     fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
16   }
17
18   if (!gelf_newphdr(eo, n)) {
19     fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1));
20   }
21
22   for (i = 0; i < n; i++) {
23     GElf_Phdr phdr, phdrOut;
24
25     if (gelf_getphdr(ei, i, &phdr) != &phdr) {
26       fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
27       break;
28     }
29
30     if (gelf_getphdr(eo, i, &phdrOut) != &phdrOut) {
31       fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
32       break;
33     }
34
35     phdrOut.p_type = phdr.p_type;
36     /* p_offset */
37     phdrOut.p_vaddr = phdr.p_vaddr;
38     phdrOut.p_paddr = phdr.p_paddr;
39     /* p_filesz */
40     /* p_memsz */
41     phdrOut.p_flags = phdr.p_flags;
42     phdrOut.p_align = phdr.p_align;
43
44     if (!gelf_update_phdr (eo, i, &phdrOut)) {
45       fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1));
46     }
47   }
48
49   /* Tell libelf that phdrs have changed */
50   elf_flagphdr(eo, ELF_C_SET, ELF_F_DIRTY);
51 }
52
53
54 void elfu_copySegments2(Elf *eo, Elf *ei)
55 {
56   size_t i, n;
57
58   if (elf_getphdrnum(ei, &n)) {
59     fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
60   }
61
62   for (i = 0; i < n; i++) {
63     GElf_Phdr phdr, phdrOut;
64
65     if (gelf_getphdr(ei, i, &phdr) != &phdr) {
66       fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
67       break;
68     }
69
70     if (gelf_getphdr(eo, i, &phdrOut) != &phdrOut) {
71       fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
72       break;
73     }
74
75     /* Start of segment */
76     if (phdr.p_type == PT_PHDR) {
77       /* Skip PHDR entries and fix them up later */
78     }
79     else if (phdr.p_offset == 0) {
80       /* The text segment usually loads the whole ELF header */
81       phdrOut.p_offset = 0;
82     } else {
83       /* Try to guess the start of the segment */
84       Elf_Scn *scn, *scnOut;
85       GElf_Shdr shdr, shdrOut;
86
87       scn = elfu_firstSectionInSegment(ei, &phdr);
88       if (!scn) {
89         fprintf(stderr, "elfu_firstSectionInSegment() failed for segment #%d\n", i);
90         continue;
91       }
92
93       if (gelf_getshdr(scn, &shdr) != &shdr) {
94         fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1));
95       }
96
97       if (phdr.p_offset < shdr.sh_offset) {
98         fprintf(stderr, "elfu_copySegments2: Segment #%d starts before first contained section.\n", i);
99       }
100
101       scnOut = elf_getscn(eo, elf_ndxscn(scn));
102       if (!scnOut) {
103         fprintf(stderr, "elf_getscn() failed: %s\n", elf_errmsg(-1));
104       }
105
106       if (gelf_getshdr(scnOut, &shdrOut) != &shdrOut) {
107         fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1));
108       }
109
110       phdrOut.p_offset = shdrOut.sh_offset;
111     }
112
113     /* File length of segment */
114     if (phdr.p_type == PT_PHDR) {
115       /* Skip PHDR entries and fix them up later */
116     }
117     else if (phdr.p_memsz == 0) {
118       phdrOut.p_filesz = 0;
119       phdrOut.p_memsz = 0;
120     } else {
121       /* Try to guess the end of the segment */
122       Elf_Scn *scn, *scnOut;
123       GElf_Shdr shdr, shdrOut;
124
125       scn = elfu_lastSectionInSegment(ei, &phdr);
126       if (!scn) {
127         fprintf(stderr, "elfu_lastSectionInSegment() failed for segment #%d\n", i);
128         continue;
129       }
130
131       if (gelf_getshdr(scn, &shdr) != &shdr) {
132         fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1));
133       }
134
135       if (phdr.p_offset + phdr.p_filesz > shdr.sh_offset + shdr.sh_size) {
136         fprintf(stderr, "elfu_copySegments2: Segment #%d ends after last contained section.\n", i);
137       }
138
139       scnOut = elf_getscn(eo, elf_ndxscn(scn));
140       if (!scnOut) {
141         fprintf(stderr, "elf_getscn() failed: %s\n", elf_errmsg(-1));
142       }
143
144       if (gelf_getshdr(scnOut, &shdrOut) != &shdrOut) {
145         fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1));
146       }
147
148       phdrOut.p_filesz = shdrOut.sh_offset - phdrOut.p_offset;
149       if (shdrOut.sh_type != SHT_NOBITS) {
150         phdrOut.p_filesz += shdrOut.sh_size;
151       }
152
153       phdrOut.p_memsz = shdrOut.sh_offset - phdrOut.p_offset + shdrOut.sh_size;
154     }
155
156     if (!gelf_update_phdr (eo, i, &phdrOut)) {
157       fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1));
158     }
159   }
160
161   /* Tell libelf that phdrs have changed */
162   elf_flagphdr(eo, ELF_C_SET, ELF_F_DIRTY);
163 }