debuggers.hg

view tools/libxc/xc_dom_elfloader.c @ 16715:c5deb251b9dc

Update version to 3.2.0-rc4
author Keir Fraser <keir.fraser@citrix.com>
date Sat Dec 29 17:57:37 2007 +0000 (2007-12-29)
parents c051ed67258a
children db943e8d1051
line source
1 /*
2 * Xen domain builder -- ELF bits.
3 *
4 * Parse and load ELF kernel images.
5 *
6 * This code is licenced under the GPL.
7 * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
8 *
9 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <inttypes.h>
14 #include "xg_private.h"
15 #include "xc_dom.h"
17 #define XEN_VER "xen-3.0"
19 /* ------------------------------------------------------------------------ */
21 static char *xc_dom_guest_type(struct xc_dom_image *dom,
22 struct elf_binary *elf)
23 {
24 uint64_t machine = elf_uval(elf, elf->ehdr, e_machine);
26 switch ( machine )
27 {
28 case EM_386:
29 switch ( dom->parms.pae )
30 {
31 case 3 /* PAEKERN_bimodal */:
32 if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") )
33 return "xen-3.0-x86_32p";
34 return "xen-3.0-x86_32";
35 case PAEKERN_extended_cr3:
36 case PAEKERN_yes:
37 return "xen-3.0-x86_32p";
38 case PAEKERN_no:
39 default:
40 return "xen-3.0-x86_32";
41 }
42 case EM_X86_64:
43 return "xen-3.0-x86_64";
44 case EM_IA_64:
45 return elf_msb(elf) ? "xen-3.0-ia64be" : "xen-3.0-ia64";
46 case EM_PPC64:
47 return "xen-3.0-powerpc64";
48 default:
49 return "xen-3.0-unknown";
50 }
51 }
53 /* ------------------------------------------------------------------------ */
54 /* parse elf binary */
56 static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
57 {
58 if ( dom->kernel_blob == NULL )
59 {
60 if ( verbose )
61 xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n",
62 __FUNCTION__);
63 return -EINVAL;
64 }
66 if ( !elf_is_elfbinary(dom->kernel_blob) )
67 {
68 if ( verbose )
69 xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not an ELF image\n",
70 __FUNCTION__);
71 return -EINVAL;
72 }
73 return 0;
74 }
76 static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
77 {
78 return check_elf_kernel(dom, 0);
79 }
81 static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
82 struct elf_binary *elf, int load)
83 {
84 struct elf_binary syms;
85 const elf_shdr *shdr, *shdr2;
86 xen_vaddr_t symtab, maxaddr;
87 char *hdr;
88 size_t size;
89 int h, count, type, i, tables = 0;
91 if ( elf_swap(elf) )
92 {
93 xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n",
94 __FUNCTION__);
95 return 0;
96 }
98 if ( load )
99 {
100 if ( !dom->bsd_symtab_start )
101 return 0;
102 size = dom->kernel_seg.vend - dom->bsd_symtab_start;
103 hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
104 *(int *)hdr = size - sizeof(int);
105 }
106 else
107 {
108 size = sizeof(int) + elf_size(elf, elf->ehdr) +
109 elf_shdr_count(elf) * elf_size(elf, shdr);
110 hdr = xc_dom_malloc(dom, size);
111 if ( hdr == NULL )
112 return 0;
113 dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
114 }
116 memcpy(hdr + sizeof(int),
117 elf->image,
118 elf_size(elf, elf->ehdr));
119 memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
120 elf->image + elf_uval(elf, elf->ehdr, e_shoff),
121 elf_shdr_count(elf) * elf_size(elf, shdr));
122 if ( elf_64bit(elf) )
123 {
124 Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
125 ehdr->e_phoff = 0;
126 ehdr->e_phentsize = 0;
127 ehdr->e_phnum = 0;
128 ehdr->e_shoff = elf_size(elf, elf->ehdr);
129 ehdr->e_shstrndx = SHN_UNDEF;
130 }
131 else
132 {
133 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
134 ehdr->e_phoff = 0;
135 ehdr->e_phentsize = 0;
136 ehdr->e_phnum = 0;
137 ehdr->e_shoff = elf_size(elf, elf->ehdr);
138 ehdr->e_shstrndx = SHN_UNDEF;
139 }
140 if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
141 return -1;
142 if ( xc_dom_logfile )
143 elf_set_logfile(&syms, xc_dom_logfile, 1);
145 symtab = dom->bsd_symtab_start + sizeof(int);
146 maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
147 elf_shdr_count(&syms) * elf_size(&syms, shdr));
149 xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64
150 " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n",
151 __FUNCTION__, load ? "load" : "parse",
152 dom->bsd_symtab_start, dom->kernel_seg.vend,
153 symtab, maxaddr);
155 count = elf_shdr_count(&syms);
156 for ( h = 0; h < count; h++ )
157 {
158 shdr = elf_shdr_by_index(&syms, h);
159 type = elf_uval(&syms, shdr, sh_type);
160 if ( type == SHT_STRTAB )
161 {
162 /* Look for a strtab @i linked to symtab @h. */
163 for ( i = 0; i < count; i++ )
164 {
165 shdr2 = elf_shdr_by_index(&syms, i);
166 if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
167 (elf_uval(&syms, shdr2, sh_link) == h) )
168 break;
169 }
170 /* Skip symtab @h if we found no corresponding strtab @i. */
171 if ( i == count )
172 {
173 if ( elf_64bit(&syms) )
174 *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
175 else
176 *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
177 continue;
178 }
179 }
181 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
182 {
183 /* Mangled to be based on ELF header location. */
184 if ( elf_64bit(&syms) )
185 *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
186 else
187 *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
188 size = elf_uval(&syms, shdr, sh_size);
189 maxaddr = elf_round_up(&syms, maxaddr + size);
190 tables++;
191 xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n",
192 __FUNCTION__, h,
193 type == SHT_SYMTAB ? "symtab" : "strtab",
194 size, maxaddr);
196 if ( load )
197 {
198 shdr2 = elf_shdr_by_index(elf, h);
199 memcpy((void*)elf_section_start(&syms, shdr),
200 elf_section_start(elf, shdr2),
201 size);
202 }
203 }
205 /* Name is NULL. */
206 if ( elf_64bit(&syms) )
207 *(Elf64_Half*)(&shdr->e64.sh_name) = 0;
208 else
209 *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
210 }
212 if ( tables == 0 )
213 {
214 xc_dom_printf("%s: no symbol table present\n", __FUNCTION__);
215 dom->bsd_symtab_start = 0;
216 return 0;
217 }
218 if ( !load )
219 dom->kernel_seg.vend = maxaddr;
220 return 0;
221 }
223 static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
224 {
225 struct elf_binary *elf;
226 int rc;
228 rc = check_elf_kernel(dom, 1);
229 if ( rc != 0 )
230 return rc;
232 elf = xc_dom_malloc(dom, sizeof(*elf));
233 dom->private_loader = elf;
234 rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
235 if ( xc_dom_logfile )
236 elf_set_logfile(elf, xc_dom_logfile, 1);
237 if ( rc != 0 )
238 {
239 xc_dom_panic(XC_INVALID_KERNEL, "%s: corrupted ELF image\n",
240 __FUNCTION__);
241 return rc;
242 }
244 /* Find the section-header strings table. */
245 if ( elf->sec_strtab == NULL )
246 {
247 xc_dom_panic(XC_INVALID_KERNEL, "%s: ELF image has no shstrtab\n",
248 __FUNCTION__);
249 return -EINVAL;
250 }
252 /* parse binary and get xen meta info */
253 elf_parse_binary(elf);
254 if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
255 return rc;
257 /* find kernel segment */
258 dom->kernel_seg.vstart = dom->parms.virt_kstart;
259 dom->kernel_seg.vend = dom->parms.virt_kend;
261 if ( dom->parms.bsd_symtab )
262 xc_dom_load_elf_symtab(dom, elf, 0);
264 dom->guest_type = xc_dom_guest_type(dom, elf);
265 xc_dom_printf("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
266 __FUNCTION__, dom->guest_type,
267 dom->kernel_seg.vstart, dom->kernel_seg.vend);
268 return 0;
269 }
271 static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
272 {
273 struct elf_binary *elf = dom->private_loader;
275 elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
276 elf_load_binary(elf);
277 if ( dom->parms.bsd_symtab )
278 xc_dom_load_elf_symtab(dom, elf, 1);
279 return 0;
280 }
282 /* ------------------------------------------------------------------------ */
284 static struct xc_dom_loader elf_loader = {
285 .name = "ELF-generic",
286 .probe = xc_dom_probe_elf_kernel,
287 .parser = xc_dom_parse_elf_kernel,
288 .loader = xc_dom_load_elf_kernel,
289 };
291 static void __init register_loader(void)
292 {
293 xc_dom_register_loader(&elf_loader);
294 }
296 /*
297 * Local variables:
298 * mode: C
299 * c-set-style: "BSD"
300 * c-basic-offset: 4
301 * tab-width: 4
302 * indent-tabs-mode: nil
303 * End:
304 */