ia64/xen-unstable

view tools/libxc/xc_load_elf.c @ 9730:74ee53209cca

Fix whitespace in libxc. Tabs are manually fixed.
Trailing whitespace removed with:
perl -p -i -e 's/\s+$/\n/g' tools/libxc/*.[ch]

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Apr 15 10:07:31 2006 +0100 (2006-04-15)
parents 86db4688d514
children d0c7cc0afd15
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 const char *image, unsigned long image_size,
23 struct domain_setup_info *dsi);
24 static int
25 loadelfimage(
26 const char *image, unsigned long image_size, int xch, uint32_t dom,
27 unsigned long *parray, struct domain_setup_info *dsi);
28 static int
29 loadelfsymtab(
30 const char *image, int xch, uint32_t dom, unsigned long *parray,
31 struct domain_setup_info *dsi);
33 int probe_elf(const char *image,
34 unsigned long image_size,
35 struct load_funcs *load_funcs)
36 {
37 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
39 if ( !IS_ELF(*ehdr) )
40 return -EINVAL;
42 load_funcs->parseimage = parseelfimage;
43 load_funcs->loadimage = loadelfimage;
45 return 0;
46 }
48 static inline int is_loadable_phdr(Elf_Phdr *phdr)
49 {
50 return ((phdr->p_type == PT_LOAD) &&
51 ((phdr->p_flags & (PF_W|PF_X)) != 0));
52 }
54 static int parseelfimage(const char *image,
55 unsigned long elfsize,
56 struct domain_setup_info *dsi)
57 {
58 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
59 Elf_Phdr *phdr;
60 Elf_Shdr *shdr;
61 unsigned long kernstart = ~0UL, kernend=0UL;
62 const char *shstrtab;
63 char *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 (
73 #if defined(__i386__)
74 (ehdr->e_ident[EI_CLASS] != ELFCLASS32) ||
75 (ehdr->e_machine != EM_386) ||
76 #elif defined(__x86_64__)
77 (ehdr->e_ident[EI_CLASS] != ELFCLASS64) ||
78 (ehdr->e_machine != EM_X86_64) ||
79 #endif
80 (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) ||
81 (ehdr->e_type != ET_EXEC) )
82 {
83 ERROR("Kernel not a Xen-compatible Elf image.");
84 return -EINVAL;
85 }
87 if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
88 {
89 ERROR("ELF program headers extend beyond end of image.");
90 return -EINVAL;
91 }
93 if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
94 {
95 ERROR("ELF section headers extend beyond end of image.");
96 return -EINVAL;
97 }
99 /* Find the section-header strings table. */
100 if ( ehdr->e_shstrndx == SHN_UNDEF )
101 {
102 ERROR("ELF image has no section-header strings table (shstrtab).");
103 return -EINVAL;
104 }
105 shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
106 (ehdr->e_shstrndx*ehdr->e_shentsize));
107 shstrtab = image + shdr->sh_offset;
109 /* Find the special '__xen_guest' section and check its contents. */
110 for ( h = 0; h < ehdr->e_shnum; h++ )
111 {
112 shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
113 if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
114 continue;
116 guestinfo = (char *)image + shdr->sh_offset;
118 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
119 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
120 {
121 ERROR("Will only load images built for the generic loader "
122 "or Linux images");
123 ERROR("Actually saw: '%s'", guestinfo);
124 return -EINVAL;
125 }
127 if ( (strstr(guestinfo, "XEN_VER=xen-3.0") == NULL) )
128 {
129 ERROR("Will only load images built for Xen v3.0");
130 ERROR("Actually saw: '%s'", guestinfo);
131 return -EINVAL;
132 }
133 if ( (strstr(guestinfo, "PAE=yes") != NULL) )
134 dsi->pae_kernel = 1;
136 break;
137 }
139 if ( guestinfo == NULL )
140 {
141 #ifdef __ia64__
142 guestinfo = "";
143 #else
144 ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
145 return -EINVAL;
146 #endif
147 }
149 dsi->xen_guest_string = guestinfo;
151 for ( h = 0; h < ehdr->e_phnum; h++ )
152 {
153 phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
154 if ( !is_loadable_phdr(phdr) )
155 continue;
156 if ( phdr->p_paddr < kernstart )
157 kernstart = phdr->p_paddr;
158 if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
159 kernend = phdr->p_paddr + phdr->p_memsz;
160 }
162 if ( (kernstart > kernend) ||
163 (ehdr->e_entry < kernstart) ||
164 (ehdr->e_entry > kernend) )
165 {
166 ERROR("Malformed ELF image.");
167 return -EINVAL;
168 }
170 dsi->v_start = kernstart;
171 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
172 dsi->v_start = strtoul(p+10, &p, 0);
174 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
175 dsi->load_symtab = 1;
177 dsi->v_kernstart = kernstart;
178 dsi->v_kernend = kernend;
179 dsi->v_kernentry = ehdr->e_entry;
180 dsi->v_end = dsi->v_kernend;
182 loadelfsymtab(image, 0, 0, NULL, dsi);
184 return 0;
185 }
187 static int
188 loadelfimage(
189 const char *image, unsigned long elfsize, int xch, uint32_t dom,
190 unsigned long *parray, struct domain_setup_info *dsi)
191 {
192 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
193 Elf_Phdr *phdr;
194 int h;
196 char *va;
197 unsigned long pa, done, chunksz;
199 for ( h = 0; h < ehdr->e_phnum; h++ )
200 {
201 phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
202 if ( !is_loadable_phdr(phdr) )
203 continue;
205 for ( done = 0; done < phdr->p_filesz; done += chunksz )
206 {
207 pa = (phdr->p_paddr + done) - dsi->v_start;
208 va = xc_map_foreign_range(
209 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
210 chunksz = phdr->p_filesz - done;
211 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
212 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
213 memcpy(va + (pa & (PAGE_SIZE-1)),
214 image + phdr->p_offset + done, chunksz);
215 munmap(va, PAGE_SIZE);
216 }
218 for ( ; done < phdr->p_memsz; done += chunksz )
219 {
220 pa = (phdr->p_paddr + done) - dsi->v_start;
221 va = xc_map_foreign_range(
222 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
223 chunksz = phdr->p_memsz - done;
224 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
225 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
226 memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
227 munmap(va, PAGE_SIZE);
228 }
229 }
231 loadelfsymtab(image, xch, dom, parray, dsi);
233 return 0;
234 }
236 #define ELFROUND (ELFSIZE / 8)
238 static int
239 loadelfsymtab(
240 const char *image, int xch, uint32_t dom, unsigned long *parray,
241 struct domain_setup_info *dsi)
242 {
243 Elf_Ehdr *ehdr = (Elf_Ehdr *)image, *sym_ehdr;
244 Elf_Shdr *shdr;
245 unsigned long maxva, symva;
246 char *p;
247 int h, i;
249 if ( !dsi->load_symtab )
250 return 0;
252 p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
253 ehdr->e_shnum * sizeof(Elf_Shdr));
254 if (p == NULL)
255 return 0;
257 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
258 symva = maxva;
259 maxva += sizeof(int);
260 dsi->symtab_addr = maxva;
261 dsi->symtab_len = 0;
262 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
263 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
265 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
266 memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
268 for ( h = 0; h < ehdr->e_shnum; h++ )
269 {
270 if ( shdr[h].sh_type == SHT_STRTAB )
271 {
272 /* Look for a strtab @i linked to symtab @h. */
273 for ( i = 0; i < ehdr->e_shnum; i++ )
274 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
275 (shdr[i].sh_link == h) )
276 break;
277 /* Skip symtab @h if we found no corresponding strtab @i. */
278 if ( i == ehdr->e_shnum )
279 {
280 shdr[h].sh_offset = 0;
281 continue;
282 }
283 }
285 if ( (shdr[h].sh_type == SHT_STRTAB) ||
286 (shdr[h].sh_type == SHT_SYMTAB) )
287 {
288 if ( parray != NULL )
289 xc_map_memcpy(maxva, image + shdr[h].sh_offset,
290 shdr[h].sh_size,
291 xch, dom, parray, dsi->v_start);
293 /* Mangled to be based on ELF header location. */
294 shdr[h].sh_offset = maxva - dsi->symtab_addr;
296 dsi->symtab_len += shdr[h].sh_size;
297 maxva += shdr[h].sh_size;
298 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
299 }
301 shdr[h].sh_name = 0; /* Name is NULL. */
302 }
304 if ( dsi->symtab_len == 0 )
305 {
306 dsi->symtab_addr = 0;
307 goto out;
308 }
310 if ( parray != NULL )
311 {
312 *(int *)p = maxva - dsi->symtab_addr;
313 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
314 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
315 sym_ehdr->e_phoff = 0;
316 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
317 sym_ehdr->e_phentsize = 0;
318 sym_ehdr->e_phnum = 0;
319 sym_ehdr->e_shstrndx = SHN_UNDEF;
321 /* Copy total length, crafted ELF header and section header table */
322 xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
323 ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
324 dsi->v_start);
325 }
327 dsi->symtab_len = maxva - dsi->symtab_addr;
328 dsi->v_end = round_pgup(maxva);
330 out:
331 free(p);
333 return 0;
334 }
336 /*
337 * Local variables:
338 * mode: C
339 * c-set-style: "BSD"
340 * c-basic-offset: 4
341 * tab-width: 4
342 * indent-tabs-mode: nil
343 * End:
344 */