debuggers.hg

view tools/libxc/xc_dom_elfloader.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents b0d7780794eb
children 3ffdb094c2c0 2a9bb324e645
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 default:
47 return "xen-3.0-unknown";
48 }
49 }
51 /* ------------------------------------------------------------------------ */
52 /* parse elf binary */
54 static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
55 {
56 if ( dom->kernel_blob == NULL )
57 {
58 if ( verbose )
59 xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n",
60 __FUNCTION__);
61 return -EINVAL;
62 }
64 if ( !elf_is_elfbinary(dom->kernel_blob) )
65 {
66 if ( verbose )
67 xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not an ELF image\n",
68 __FUNCTION__);
69 return -EINVAL;
70 }
71 return 0;
72 }
74 static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
75 {
76 return check_elf_kernel(dom, 0);
77 }
79 static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
80 struct elf_binary *elf, int load)
81 {
82 struct elf_binary syms;
83 const elf_shdr *shdr, *shdr2;
84 xen_vaddr_t symtab, maxaddr;
85 char *hdr;
86 size_t size;
87 int h, count, type, i, tables = 0;
89 if ( elf_swap(elf) )
90 {
91 xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n",
92 __FUNCTION__);
93 return 0;
94 }
96 if ( load )
97 {
98 if ( !dom->bsd_symtab_start )
99 return 0;
100 size = dom->kernel_seg.vend - dom->bsd_symtab_start;
101 hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
102 *(int *)hdr = size - sizeof(int);
103 }
104 else
105 {
106 size = sizeof(int) + elf_size(elf, elf->ehdr) +
107 elf_shdr_count(elf) * elf_size(elf, shdr);
108 hdr = xc_dom_malloc(dom, size);
109 if ( hdr == NULL )
110 return 0;
111 dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
112 }
114 memcpy(hdr + sizeof(int),
115 elf->image,
116 elf_size(elf, elf->ehdr));
117 memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
118 elf->image + elf_uval(elf, elf->ehdr, e_shoff),
119 elf_shdr_count(elf) * elf_size(elf, shdr));
120 if ( elf_64bit(elf) )
121 {
122 Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
123 ehdr->e_phoff = 0;
124 ehdr->e_phentsize = 0;
125 ehdr->e_phnum = 0;
126 ehdr->e_shoff = elf_size(elf, elf->ehdr);
127 ehdr->e_shstrndx = SHN_UNDEF;
128 }
129 else
130 {
131 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
132 ehdr->e_phoff = 0;
133 ehdr->e_phentsize = 0;
134 ehdr->e_phnum = 0;
135 ehdr->e_shoff = elf_size(elf, elf->ehdr);
136 ehdr->e_shstrndx = SHN_UNDEF;
137 }
138 if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
139 return -1;
140 if ( xc_dom_logfile )
141 elf_set_logfile(&syms, xc_dom_logfile, 1);
143 symtab = dom->bsd_symtab_start + sizeof(int);
144 maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
145 elf_shdr_count(&syms) * elf_size(&syms, shdr));
147 xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64
148 " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n",
149 __FUNCTION__, load ? "load" : "parse",
150 dom->bsd_symtab_start, dom->kernel_seg.vend,
151 symtab, maxaddr);
153 count = elf_shdr_count(&syms);
154 for ( h = 0; h < count; h++ )
155 {
156 shdr = elf_shdr_by_index(&syms, h);
157 type = elf_uval(&syms, shdr, sh_type);
158 if ( type == SHT_STRTAB )
159 {
160 /* Look for a strtab @i linked to symtab @h. */
161 for ( i = 0; i < count; i++ )
162 {
163 shdr2 = elf_shdr_by_index(&syms, i);
164 if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
165 (elf_uval(&syms, shdr2, sh_link) == h) )
166 break;
167 }
168 /* Skip symtab @h if we found no corresponding strtab @i. */
169 if ( i == count )
170 {
171 if ( elf_64bit(&syms) )
172 *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
173 else
174 *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
175 continue;
176 }
177 }
179 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
180 {
181 /* Mangled to be based on ELF header location. */
182 if ( elf_64bit(&syms) )
183 *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
184 else
185 *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
186 size = elf_uval(&syms, shdr, sh_size);
187 maxaddr = elf_round_up(&syms, maxaddr + size);
188 tables++;
189 xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n",
190 __FUNCTION__, h,
191 type == SHT_SYMTAB ? "symtab" : "strtab",
192 size, maxaddr);
194 if ( load )
195 {
196 shdr2 = elf_shdr_by_index(elf, h);
197 memcpy((void*)elf_section_start(&syms, shdr),
198 elf_section_start(elf, shdr2),
199 size);
200 }
201 }
203 /* Name is NULL. */
204 if ( elf_64bit(&syms) )
205 *(Elf64_Half*)(&shdr->e64.sh_name) = 0;
206 else
207 *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
208 }
210 if ( tables == 0 )
211 {
212 xc_dom_printf("%s: no symbol table present\n", __FUNCTION__);
213 dom->bsd_symtab_start = 0;
214 return 0;
215 }
216 if ( !load )
217 dom->kernel_seg.vend = maxaddr;
218 return 0;
219 }
221 static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
222 {
223 struct elf_binary *elf;
224 int rc;
226 rc = check_elf_kernel(dom, 1);
227 if ( rc != 0 )
228 return rc;
230 elf = xc_dom_malloc(dom, sizeof(*elf));
231 dom->private_loader = elf;
232 rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
233 if ( xc_dom_logfile )
234 elf_set_logfile(elf, xc_dom_logfile, 1);
235 if ( rc != 0 )
236 {
237 xc_dom_panic(XC_INVALID_KERNEL, "%s: corrupted ELF image\n",
238 __FUNCTION__);
239 return rc;
240 }
242 /* Find the section-header strings table. */
243 if ( elf->sec_strtab == NULL )
244 {
245 xc_dom_panic(XC_INVALID_KERNEL, "%s: ELF image has no shstrtab\n",
246 __FUNCTION__);
247 return -EINVAL;
248 }
250 /* parse binary and get xen meta info */
251 elf_parse_binary(elf);
252 if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
253 return rc;
255 /* find kernel segment */
256 dom->kernel_seg.vstart = dom->parms.virt_kstart;
257 dom->kernel_seg.vend = dom->parms.virt_kend;
259 if ( dom->parms.bsd_symtab )
260 xc_dom_load_elf_symtab(dom, elf, 0);
262 dom->guest_type = xc_dom_guest_type(dom, elf);
263 xc_dom_printf("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
264 __FUNCTION__, dom->guest_type,
265 dom->kernel_seg.vstart, dom->kernel_seg.vend);
266 return 0;
267 }
269 static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
270 {
271 struct elf_binary *elf = dom->private_loader;
273 elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
274 elf_load_binary(elf);
275 if ( dom->parms.bsd_symtab )
276 xc_dom_load_elf_symtab(dom, elf, 1);
277 return 0;
278 }
280 /* ------------------------------------------------------------------------ */
282 struct xc_dom_loader elf_loader = {
283 .name = "ELF-generic",
284 .probe = xc_dom_probe_elf_kernel,
285 .parser = xc_dom_parse_elf_kernel,
286 .loader = xc_dom_load_elf_kernel,
287 };
289 static void __init register_loader(void)
290 {
291 xc_dom_register_loader(&elf_loader);
292 }
294 /*
295 * Local variables:
296 * mode: C
297 * c-set-style: "BSD"
298 * c-basic-offset: 4
299 * tab-width: 4
300 * indent-tabs-mode: nil
301 * End:
302 */