ia64/xen-unstable

view tools/libxc/xc_load_elf.c @ 8964:8946b6dcd49e

Fix x86_64 Xen build.

event_callback_cs and failsafe_callback_cs are x86_32 only.

Signed-off-by: Ian Campbell <Ian.Campbell@XenSource.com>
author Ian.Campbell@xensource.com
date Wed Feb 22 17:26:39 2006 +0000 (2006-02-22)
parents 71914b64b577
children a1fcee3b2abe
line source
1 /******************************************************************************
2 * xc_elf_load.c
3 */
5 #include "xg_private.h"
7 #if defined(__i386__)
8 #define ELFSIZE 32
9 #endif
10 #if defined(__x86_64__) || defined(__ia64__)
11 #define ELFSIZE 64
12 #endif
14 #include "xc_elf.h"
15 #include <stdlib.h>
17 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
18 #define round_pgdown(_p) ((_p)&PAGE_MASK)
20 static int
21 parseelfimage(
22 char *image, unsigned long image_size, struct domain_setup_info *dsi);
23 static int
24 loadelfimage(
25 char *image, unsigned long image_size, int xch, uint32_t dom,
26 unsigned long *parray, struct domain_setup_info *dsi);
27 static int
28 loadelfsymtab(
29 char *image, int xch, uint32_t dom, unsigned long *parray,
30 struct domain_setup_info *dsi);
32 int probe_elf(char *image,
33 unsigned long image_size,
34 struct load_funcs *load_funcs)
35 {
36 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
38 if ( !IS_ELF(*ehdr) )
39 {
40 return -EINVAL;
41 }
43 load_funcs->parseimage = parseelfimage;
44 load_funcs->loadimage = loadelfimage;
46 return 0;
47 }
49 static inline int is_loadable_phdr(Elf_Phdr *phdr)
50 {
51 return ((phdr->p_type == PT_LOAD) &&
52 ((phdr->p_flags & (PF_W|PF_X)) != 0));
53 }
55 static int parseelfimage(char *image,
56 unsigned long elfsize,
57 struct domain_setup_info *dsi)
58 {
59 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
60 Elf_Phdr *phdr;
61 Elf_Shdr *shdr;
62 unsigned long kernstart = ~0UL, kernend=0UL;
63 char *shstrtab, *guestinfo=NULL, *p;
64 int h;
66 if ( !IS_ELF(*ehdr) )
67 {
68 ERROR("Kernel image does not have an ELF header.");
69 return -EINVAL;
70 }
72 if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
73 {
74 ERROR("ELF program headers extend beyond end of image.");
75 return -EINVAL;
76 }
78 if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
79 {
80 ERROR("ELF section headers extend beyond end of image.");
81 return -EINVAL;
82 }
84 /* Find the section-header strings table. */
85 if ( ehdr->e_shstrndx == SHN_UNDEF )
86 {
87 ERROR("ELF image has no section-header strings table (shstrtab).");
88 return -EINVAL;
89 }
90 shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
91 (ehdr->e_shstrndx*ehdr->e_shentsize));
92 shstrtab = image + shdr->sh_offset;
94 /* Find the special '__xen_guest' section and check its contents. */
95 for ( h = 0; h < ehdr->e_shnum; h++ )
96 {
97 shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
98 if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
99 continue;
101 guestinfo = image + shdr->sh_offset;
103 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
104 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
105 {
106 ERROR("Will only load images built for the generic loader "
107 "or Linux images");
108 ERROR("Actually saw: '%s'", guestinfo);
109 return -EINVAL;
110 }
112 if ( (strstr(guestinfo, "XEN_VER=xen-3.0") == NULL) )
113 {
114 ERROR("Will only load images built for Xen v3.0");
115 ERROR("Actually saw: '%s'", guestinfo);
116 return -EINVAL;
117 }
118 if ( (strstr(guestinfo, "PAE=yes") != NULL) )
119 dsi->pae_kernel = 1;
121 break;
122 }
124 if ( guestinfo == NULL )
125 {
126 #ifdef __ia64__
127 guestinfo = "";
128 #else
129 ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
130 return -EINVAL;
131 #endif
132 }
134 dsi->xen_guest_string = guestinfo;
136 for ( h = 0; h < ehdr->e_phnum; h++ )
137 {
138 phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
139 if ( !is_loadable_phdr(phdr) )
140 continue;
141 if ( phdr->p_paddr < kernstart )
142 kernstart = phdr->p_paddr;
143 if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
144 kernend = phdr->p_paddr + phdr->p_memsz;
145 }
147 if ( (kernstart > kernend) ||
148 (ehdr->e_entry < kernstart) ||
149 (ehdr->e_entry > kernend) )
150 {
151 ERROR("Malformed ELF image.");
152 return -EINVAL;
153 }
155 dsi->v_start = kernstart;
156 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
157 dsi->v_start = strtoul(p+10, &p, 0);
159 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
160 dsi->load_symtab = 1;
162 dsi->v_kernstart = kernstart;
163 dsi->v_kernend = kernend;
164 dsi->v_kernentry = ehdr->e_entry;
165 dsi->v_end = dsi->v_kernend;
167 loadelfsymtab(image, 0, 0, NULL, dsi);
169 return 0;
170 }
172 static int
173 loadelfimage(
174 char *image, unsigned long elfsize, int xch, uint32_t dom,
175 unsigned long *parray, struct domain_setup_info *dsi)
176 {
177 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
178 Elf_Phdr *phdr;
179 int h;
181 char *va;
182 unsigned long pa, done, chunksz;
184 for ( h = 0; h < ehdr->e_phnum; h++ )
185 {
186 phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
187 if ( !is_loadable_phdr(phdr) )
188 continue;
190 for ( done = 0; done < phdr->p_filesz; done += chunksz )
191 {
192 pa = (phdr->p_paddr + done) - dsi->v_start;
193 va = xc_map_foreign_range(
194 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
195 chunksz = phdr->p_filesz - done;
196 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
197 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
198 memcpy(va + (pa & (PAGE_SIZE-1)),
199 image + phdr->p_offset + done, chunksz);
200 munmap(va, PAGE_SIZE);
201 }
203 for ( ; done < phdr->p_memsz; done += chunksz )
204 {
205 pa = (phdr->p_paddr + done) - dsi->v_start;
206 va = xc_map_foreign_range(
207 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
208 chunksz = phdr->p_memsz - done;
209 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
210 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
211 memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
212 munmap(va, PAGE_SIZE);
213 }
214 }
216 loadelfsymtab(image, xch, dom, parray, dsi);
218 return 0;
219 }
221 #define ELFROUND (ELFSIZE / 8)
223 static int
224 loadelfsymtab(
225 char *image, int xch, uint32_t dom, unsigned long *parray,
226 struct domain_setup_info *dsi)
227 {
228 Elf_Ehdr *ehdr = (Elf_Ehdr *)image, *sym_ehdr;
229 Elf_Shdr *shdr;
230 unsigned long maxva, symva;
231 char *p;
232 int h, i;
234 if ( !dsi->load_symtab )
235 return 0;
237 p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
238 ehdr->e_shnum * sizeof(Elf_Shdr));
239 if (p == NULL)
240 return 0;
242 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
243 symva = maxva;
244 maxva += sizeof(int);
245 dsi->symtab_addr = maxva;
246 dsi->symtab_len = 0;
247 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
248 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
250 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
251 memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
253 for ( h = 0; h < ehdr->e_shnum; h++ )
254 {
255 if ( shdr[h].sh_type == SHT_STRTAB )
256 {
257 /* Look for a strtab @i linked to symtab @h. */
258 for ( i = 0; i < ehdr->e_shnum; i++ )
259 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
260 (shdr[i].sh_link == h) )
261 break;
262 /* Skip symtab @h if we found no corresponding strtab @i. */
263 if ( i == ehdr->e_shnum )
264 {
265 shdr[h].sh_offset = 0;
266 continue;
267 }
268 }
270 if ( (shdr[h].sh_type == SHT_STRTAB) ||
271 (shdr[h].sh_type == SHT_SYMTAB) )
272 {
273 if ( parray != NULL )
274 xc_map_memcpy(maxva, image + shdr[h].sh_offset, shdr[h].sh_size,
275 xch, dom, parray, dsi->v_start);
277 /* Mangled to be based on ELF header location. */
278 shdr[h].sh_offset = maxva - dsi->symtab_addr;
280 dsi->symtab_len += shdr[h].sh_size;
281 maxva += shdr[h].sh_size;
282 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
283 }
285 shdr[h].sh_name = 0; /* Name is NULL. */
286 }
288 if ( dsi->symtab_len == 0 )
289 {
290 dsi->symtab_addr = 0;
291 goto out;
292 }
294 if ( parray != NULL )
295 {
296 *(int *)p = maxva - dsi->symtab_addr;
297 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
298 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
299 sym_ehdr->e_phoff = 0;
300 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
301 sym_ehdr->e_phentsize = 0;
302 sym_ehdr->e_phnum = 0;
303 sym_ehdr->e_shstrndx = SHN_UNDEF;
305 /* Copy total length, crafted ELF header and section header table */
306 xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
307 ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
308 dsi->v_start);
309 }
311 dsi->symtab_len = maxva - dsi->symtab_addr;
312 dsi->v_end = round_pgup(maxva);
314 out:
315 free(p);
317 return 0;
318 }
320 /*
321 * Local variables:
322 * mode: C
323 * c-set-style: "BSD"
324 * c-basic-offset: 4
325 * tab-width: 4
326 * indent-tabs-mode: nil
327 * End:
328 */