ia64/xen-unstable

view xen/arch/x86/boot/mkelf32.c @ 9026:a5830f7fd7e0

Cross-compilation fixes (x86/64 on i386).

Use strtoull to parse the final_exec_addr value from the command
line. Whe cross compiling on i386 for x86-64 unsigned long is 32 bit,
which leads to final_exec_addr being truncated to 32 bits by strtoul,
which leads to grub refusing to load the resulting image. Please
apply.

Use the target nm(1) when cross compiling to pick the _end address
from the Xen binary.

Signed-Off-By: Muli Ben-Yehuda <mulix@mulix.org>
author kaf24@firebug.cl.cam.ac.uk
date Sun Feb 26 10:42:07 2006 +0100 (2006-02-26)
parents b21be984945a
children d75cab09ef57
line source
1 /******************************************************************************
2 * mkelf32.c
3 *
4 * Usage: elf-prefix <in-image> <out-image> <load-base>
5 *
6 * Converts an Elf32 or Elf64 executable binary <in-image> into a simple Elf32
7 * image <out-image> comprising a single chunk to be loaded at <load-base>.
8 */
10 #include <errno.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <inttypes.h>
20 #define u8 uint8_t
21 #define u16 uint16_t
22 #define u32 uint32_t
23 #define u64 uint64_t
24 #define s8 int8_t
25 #define s16 int16_t
26 #define s32 int32_t
27 #define s64 int64_t
28 #include "../../../include/xen/elf.h"
30 #define DYNAMICALLY_FILLED 0
31 #define RAW_OFFSET 128
33 static Elf32_Ehdr out_ehdr = {
34 { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, /* EI_MAG{0-3} */
35 ELFCLASS32, /* EI_CLASS */
36 ELFDATA2LSB, /* EI_DATA */
37 EV_CURRENT, /* EI_VERSION */
38 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* e_ident */
39 ET_EXEC, /* e_type */
40 EM_386, /* e_machine */
41 EV_CURRENT, /* e_version */
42 DYNAMICALLY_FILLED, /* e_entry */
43 sizeof(Elf32_Ehdr), /* e_phoff */
44 DYNAMICALLY_FILLED, /* e_shoff */
45 0, /* e_flags */
46 sizeof(Elf32_Ehdr), /* e_ehsize */
47 sizeof(Elf32_Phdr), /* e_phentsize */
48 1, /* e_phnum */
49 sizeof(Elf32_Shdr), /* e_shentsize */
50 3, /* e_shnum */
51 2 /* e_shstrndx */
52 };
54 static Elf32_Phdr out_phdr = {
55 PT_LOAD, /* p_type */
56 RAW_OFFSET, /* p_offset */
57 DYNAMICALLY_FILLED, /* p_vaddr */
58 DYNAMICALLY_FILLED, /* p_paddr */
59 DYNAMICALLY_FILLED, /* p_filesz */
60 DYNAMICALLY_FILLED, /* p_memsz */
61 PF_R|PF_W|PF_X, /* p_flags */
62 64 /* p_align */
63 };
65 static u8 out_shstrtab[] = "\0.text\0.shstrtab";
67 static Elf32_Shdr out_shdr[] = {
68 { 0 },
69 { 1, /* sh_name */
70 SHT_PROGBITS, /* sh_type */
71 SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR, /* sh_flags */
72 DYNAMICALLY_FILLED, /* sh_addr */
73 RAW_OFFSET, /* sh_offset */
74 DYNAMICALLY_FILLED, /* sh_size */
75 0, /* sh_link */
76 0, /* sh_info */
77 64, /* sh_addralign */
78 0 /* sh_entsize */
79 },
80 { 7, /* sh_name */
81 SHT_STRTAB, /* sh_type */
82 0, /* sh_flags */
83 0, /* sh_addr */
84 DYNAMICALLY_FILLED, /* sh_offset */
85 sizeof(out_shstrtab), /* sh_size */
86 0, /* sh_link */
87 0, /* sh_info */
88 1, /* sh_addralign */
89 0 /* sh_entsize */
90 }
91 };
93 #define swap16(_v) ((((u16)(_v)>>8)&0xff)|(((u16)(_v)&0xff)<<8))
94 #define swap32(_v) (((u32)swap16((u16)(_v))<<16)|(u32)swap16((u32)((_v)>>16)))
95 #define swap64(_v) (((u64)swap32((u32)(_v))<<32)|(u64)swap32((u32)((_v)>>32)))
97 static int big_endian;
99 static void endianadjust_ehdr32(Elf32_Ehdr *eh)
100 {
101 if ( !big_endian )
102 return;
103 eh->e_type = swap16(eh->e_type);
104 eh->e_machine = swap16(eh->e_machine);
105 eh->e_version = swap32(eh->e_version);
106 eh->e_entry = swap32(eh->e_entry);
107 eh->e_phoff = swap32(eh->e_phoff);
108 eh->e_shoff = swap32(eh->e_shoff);
109 eh->e_flags = swap32(eh->e_flags);
110 eh->e_ehsize = swap16(eh->e_ehsize);
111 eh->e_phentsize = swap16(eh->e_phentsize);
112 eh->e_phnum = swap16(eh->e_phnum);
113 eh->e_shentsize = swap16(eh->e_shentsize);
114 eh->e_shnum = swap16(eh->e_shnum);
115 eh->e_shstrndx = swap16(eh->e_shstrndx);
116 }
118 static void endianadjust_ehdr64(Elf64_Ehdr *eh)
119 {
120 if ( !big_endian )
121 return;
122 eh->e_type = swap16(eh->e_type);
123 eh->e_machine = swap16(eh->e_machine);
124 eh->e_version = swap32(eh->e_version);
125 eh->e_entry = swap64(eh->e_entry);
126 eh->e_phoff = swap64(eh->e_phoff);
127 eh->e_shoff = swap64(eh->e_shoff);
128 eh->e_flags = swap32(eh->e_flags);
129 eh->e_ehsize = swap16(eh->e_ehsize);
130 eh->e_phentsize = swap16(eh->e_phentsize);
131 eh->e_phnum = swap16(eh->e_phnum);
132 eh->e_shentsize = swap16(eh->e_shentsize);
133 eh->e_shnum = swap16(eh->e_shnum);
134 eh->e_shstrndx = swap16(eh->e_shstrndx);
135 }
137 static void endianadjust_phdr32(Elf32_Phdr *ph)
138 {
139 if ( !big_endian )
140 return;
141 ph->p_type = swap32(ph->p_type);
142 ph->p_offset = swap32(ph->p_offset);
143 ph->p_vaddr = swap32(ph->p_vaddr);
144 ph->p_paddr = swap32(ph->p_paddr);
145 ph->p_filesz = swap32(ph->p_filesz);
146 ph->p_memsz = swap32(ph->p_memsz);
147 ph->p_flags = swap32(ph->p_flags);
148 ph->p_align = swap32(ph->p_align);
149 }
151 static void endianadjust_phdr64(Elf64_Phdr *ph)
152 {
153 if ( !big_endian )
154 return;
155 ph->p_type = swap32(ph->p_type);
156 ph->p_flags = swap32(ph->p_flags);
157 ph->p_offset = swap64(ph->p_offset);
158 ph->p_vaddr = swap64(ph->p_vaddr);
159 ph->p_paddr = swap64(ph->p_paddr);
160 ph->p_filesz = swap64(ph->p_filesz);
161 ph->p_memsz = swap64(ph->p_memsz);
162 ph->p_align = swap64(ph->p_align);
163 }
165 static void endianadjust_shdr32(Elf32_Shdr *sh)
166 {
167 if ( !big_endian )
168 return;
169 sh->sh_name = swap32(sh->sh_name);
170 sh->sh_type = swap32(sh->sh_type);
171 sh->sh_flags = swap32(sh->sh_flags);
172 sh->sh_addr = swap32(sh->sh_addr);
173 sh->sh_offset = swap32(sh->sh_offset);
174 sh->sh_size = swap32(sh->sh_size);
175 sh->sh_link = swap32(sh->sh_link);
176 sh->sh_info = swap32(sh->sh_info);
177 sh->sh_addralign = swap32(sh->sh_addralign);
178 sh->sh_entsize = swap32(sh->sh_entsize);
179 }
181 static void do_write(int fd, void *data, int len)
182 {
183 int done, left = len;
184 char *p = data;
186 while ( left != 0 )
187 {
188 if ( (done = write(fd, p, left)) == -1 )
189 {
190 if ( errno == EINTR )
191 continue;
192 fprintf(stderr, "Error writing output image: %d (%s).\n",
193 errno, strerror(errno));
194 exit(1);
195 }
197 left -= done;
198 p += done;
199 }
200 }
202 static void do_read(int fd, void *data, int len)
203 {
204 int done, left = len;
205 char *p = data;
207 while ( left != 0 )
208 {
209 if ( (done = read(fd, p, left)) == -1 )
210 {
211 if ( errno == EINTR )
212 continue;
213 fprintf(stderr, "Error reading input image: %d (%s).\n",
214 errno, strerror(errno));
215 exit(1);
216 }
218 left -= done;
219 p += done;
220 }
221 }
223 int main(int argc, char **argv)
224 {
225 u64 final_exec_addr;
226 u32 loadbase, dat_siz, mem_siz;
227 char *inimage, *outimage;
228 int infd, outfd;
229 char buffer[1024];
230 int bytes, todo, i;
232 Elf32_Ehdr in32_ehdr;
233 Elf32_Phdr in32_phdr;
235 Elf64_Ehdr in64_ehdr;
236 Elf64_Phdr in64_phdr;
238 if ( argc != 5 )
239 {
240 fprintf(stderr, "Usage: mkelf32 <in-image> <out-image> "
241 "<load-base> <final-exec-addr>\n");
242 return 1;
243 }
245 inimage = argv[1];
246 outimage = argv[2];
247 loadbase = strtoull(argv[3], NULL, 16);
248 final_exec_addr = strtoul(argv[4], NULL, 16);
250 infd = open(inimage, O_RDONLY);
251 if ( infd == -1 )
252 {
253 fprintf(stderr, "Failed to open input image '%s': %d (%s).\n",
254 inimage, errno, strerror(errno));
255 return 1;
256 }
258 do_read(infd, &in32_ehdr, sizeof(in32_ehdr));
259 if ( !IS_ELF(in32_ehdr) ||
260 (in32_ehdr.e_ident[EI_DATA] != ELFDATA2LSB) )
261 {
262 fprintf(stderr, "Input image must be a little-endian Elf image.\n");
263 return 1;
264 }
266 big_endian = (*(u16 *)in32_ehdr.e_ident == ((ELFMAG0 << 8) | ELFMAG1));
268 endianadjust_ehdr32(&in32_ehdr);
269 switch ( in32_ehdr.e_ident[EI_CLASS] )
270 {
271 case ELFCLASS32:
272 if ( in32_ehdr.e_phentsize != sizeof(in32_phdr) )
273 {
274 fprintf(stderr, "Bad program header size (%d != %d).\n",
275 (int)in32_ehdr.e_phentsize, (int)sizeof(in32_phdr));
276 return 1;
277 }
279 if ( in32_ehdr.e_phnum != 1 )
280 {
281 fprintf(stderr, "Expect precisely 1 program header; found %d.\n",
282 (int)in32_ehdr.e_phnum);
283 return 1;
284 }
286 (void)lseek(infd, in32_ehdr.e_phoff, SEEK_SET);
287 do_read(infd, &in32_phdr, sizeof(in32_phdr));
288 endianadjust_phdr32(&in32_phdr);
290 (void)lseek(infd, in32_phdr.p_offset, SEEK_SET);
291 dat_siz = (u32)in32_phdr.p_filesz;
293 /* Do not use p_memsz: it does not include BSS alignment padding. */
294 /*mem_siz = (u32)in32_phdr.p_memsz;*/
295 mem_siz = (u32)(final_exec_addr - in32_phdr.p_vaddr);
296 break;
298 case ELFCLASS64:
299 (void)lseek(infd, 0, SEEK_SET);
300 do_read(infd, &in64_ehdr, sizeof(in64_ehdr));
301 endianadjust_ehdr64(&in64_ehdr);
303 if ( in64_ehdr.e_phentsize != sizeof(in64_phdr) )
304 {
305 fprintf(stderr, "Bad program header size (%d != %d).\n",
306 (int)in64_ehdr.e_phentsize, (int)sizeof(in64_phdr));
307 return 1;
308 }
310 if ( in64_ehdr.e_phnum != 1 )
311 {
312 fprintf(stderr, "Expect precisly 1 program header; found %d.\n",
313 (int)in64_ehdr.e_phnum);
314 return 1;
315 }
317 (void)lseek(infd, in64_ehdr.e_phoff, SEEK_SET);
318 do_read(infd, &in64_phdr, sizeof(in64_phdr));
319 endianadjust_phdr64(&in64_phdr);
321 (void)lseek(infd, in64_phdr.p_offset, SEEK_SET);
322 dat_siz = (u32)in64_phdr.p_filesz;
324 /* Do not use p_memsz: it does not include BSS alignment padding. */
325 /*mem_siz = (u32)in64_phdr.p_memsz;*/
326 mem_siz = (u32)(final_exec_addr - in64_phdr.p_vaddr);
327 break;
329 default:
330 fprintf(stderr, "Input image must be a 32- or 64-bit Elf image.\n");
331 return 1;
332 }
334 /*
335 * End the image on a page boundary. This gets round alignment bugs
336 * in the boot- or chain-loader (e.g., kexec on the XenoBoot CD).
337 */
338 mem_siz += -(loadbase + mem_siz) & 0xfff;
340 out_ehdr.e_entry = loadbase;
341 out_ehdr.e_shoff = RAW_OFFSET + dat_siz;
343 out_phdr.p_vaddr = loadbase;
344 out_phdr.p_paddr = loadbase;
345 out_phdr.p_filesz = dat_siz;
346 out_phdr.p_memsz = mem_siz;
348 out_shdr[1].sh_addr = loadbase;
349 out_shdr[1].sh_size = dat_siz;
350 out_shdr[2].sh_offset = RAW_OFFSET + dat_siz + sizeof(out_shdr);
352 outfd = open(outimage, O_WRONLY|O_CREAT|O_TRUNC, 0775);
353 if ( outfd == -1 )
354 {
355 fprintf(stderr, "Failed to open output image '%s': %d (%s).\n",
356 outimage, errno, strerror(errno));
357 return 1;
358 }
360 endianadjust_ehdr32(&out_ehdr);
361 do_write(outfd, &out_ehdr, sizeof(out_ehdr));
363 endianadjust_phdr32(&out_phdr);
364 do_write(outfd, &out_phdr, sizeof(out_phdr));
366 if ( (bytes = RAW_OFFSET - sizeof(out_ehdr) - sizeof(out_phdr)) < 0 )
367 {
368 fprintf(stderr, "Header overflow.\n");
369 return 1;
370 }
371 do_write(outfd, buffer, bytes);
373 for ( bytes = 0; bytes < dat_siz; bytes += todo )
374 {
375 todo = ((dat_siz - bytes) > sizeof(buffer)) ?
376 sizeof(buffer) : (dat_siz - bytes);
377 do_read(infd, buffer, todo);
378 do_write(outfd, buffer, todo);
379 }
381 for ( i = 0; i < (sizeof(out_shdr) / sizeof(out_shdr[0])); i++ )
382 endianadjust_shdr32(&out_shdr[i]);
383 do_write(outfd, &out_shdr[0], sizeof(out_shdr));
385 do_write(outfd, out_shstrtab, sizeof(out_shstrtab));
386 do_write(outfd, buffer, 4-((sizeof(out_shstrtab)+dat_siz)&3));
388 close(infd);
389 close(outfd);
391 return 0;
392 }
394 /*
395 * Local variables:
396 * mode: C
397 * c-set-style: "BSD"
398 * c-basic-offset: 4
399 * tab-width: 4
400 * indent-tabs-mode: nil
401 * End:
402 */