ia64/xen-unstable

view xen/common/elf.c @ 6832:5959fae4722a

Set NE bit for VMX guest CR0. VMCS guest CR0.NE bit must
be set, else it will cause "vm-entry failed".

Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Sep 14 13:37:50 2005 +0000 (2005-09-14)
parents 5cc07785693b
children 75637383278c
line source
1 /******************************************************************************
2 * elf.c
3 *
4 * Generic Elf-loading routines.
5 */
7 #include <xen/config.h>
8 #include <xen/init.h>
9 #include <xen/lib.h>
10 #include <xen/mm.h>
11 #include <xen/elf.h>
12 #include <xen/sched.h>
14 static void loadelfsymtab(struct domain_setup_info *dsi, int doload);
15 static inline int is_loadable_phdr(Elf_Phdr *phdr)
16 {
17 return ((phdr->p_type == PT_LOAD) &&
18 ((phdr->p_flags & (PF_W|PF_X)) != 0));
19 }
21 int parseelfimage(struct domain_setup_info *dsi)
22 {
23 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
24 Elf_Phdr *phdr;
25 Elf_Shdr *shdr;
26 unsigned long kernstart = ~0UL, kernend=0UL;
27 char *shstrtab, *guestinfo=NULL, *p;
28 char *elfbase = (char *)dsi->image_addr;
29 int h;
31 if ( !elf_sanity_check(ehdr) )
32 return -EINVAL;
34 if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > dsi->image_len )
35 {
36 printk("ELF program headers extend beyond end of image.\n");
37 return -EINVAL;
38 }
40 if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > dsi->image_len )
41 {
42 printk("ELF section headers extend beyond end of image.\n");
43 return -EINVAL;
44 }
46 /* Find the section-header strings table. */
47 if ( ehdr->e_shstrndx == SHN_UNDEF )
48 {
49 printk("ELF image has no section-header strings table (shstrtab).\n");
50 return -EINVAL;
51 }
52 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff +
53 (ehdr->e_shstrndx*ehdr->e_shentsize));
54 shstrtab = elfbase + shdr->sh_offset;
56 /* Find the special '__xen_guest' section and check its contents. */
57 for ( h = 0; h < ehdr->e_shnum; h++ )
58 {
59 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
60 if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
61 continue;
63 guestinfo = elfbase + shdr->sh_offset;
64 printk("Xen-ELF header found: '%s'\n", guestinfo);
66 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
67 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
68 {
69 printk("ERROR: Xen will only load images built for the generic "
70 "loader or Linux images\n");
71 return -EINVAL;
72 }
74 if ( (strstr(guestinfo, "XEN_VER=3.0") == NULL) )
75 {
76 printk("ERROR: Xen will only load images built for Xen v3.0\n");
77 return -EINVAL;
78 }
80 break;
81 }
83 dsi->xen_section_string = guestinfo;
85 for ( h = 0; h < ehdr->e_phnum; h++ )
86 {
87 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
88 if ( !is_loadable_phdr(phdr) )
89 continue;
90 if ( phdr->p_paddr < kernstart )
91 kernstart = phdr->p_paddr;
92 if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
93 kernend = phdr->p_paddr + phdr->p_memsz;
94 }
96 if ( (kernstart > kernend) ||
97 (ehdr->e_entry < kernstart) ||
98 (ehdr->e_entry > kernend) )
99 {
100 printk("Malformed ELF image.\n");
101 return -EINVAL;
102 }
104 dsi->v_start = kernstart;
106 if ( guestinfo != NULL )
107 {
108 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
109 dsi->v_start = simple_strtoul(p+10, &p, 0);
111 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
112 dsi->load_symtab = 1;
113 }
115 dsi->v_kernstart = kernstart;
116 dsi->v_kernend = kernend;
117 dsi->v_kernentry = ehdr->e_entry;
118 dsi->v_end = dsi->v_kernend;
120 loadelfsymtab(dsi, 0);
122 return 0;
123 }
125 int loadelfimage(struct domain_setup_info *dsi)
126 {
127 char *elfbase = (char *)dsi->image_addr;
128 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
129 Elf_Phdr *phdr;
130 int h;
132 for ( h = 0; h < ehdr->e_phnum; h++ )
133 {
134 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
135 if ( !is_loadable_phdr(phdr) )
136 continue;
137 if ( phdr->p_filesz != 0 )
138 memcpy((char *)phdr->p_paddr, elfbase + phdr->p_offset,
139 phdr->p_filesz);
140 if ( phdr->p_memsz > phdr->p_filesz )
141 memset((char *)phdr->p_paddr + phdr->p_filesz, 0,
142 phdr->p_memsz - phdr->p_filesz);
143 }
145 loadelfsymtab(dsi, 1);
147 return 0;
148 }
150 #define ELFROUND (ELFSIZE / 8)
152 static void loadelfsymtab(struct domain_setup_info *dsi, int doload)
153 {
154 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr;
155 Elf_Shdr *shdr;
156 unsigned long maxva, symva;
157 char *p, *elfbase = (char *)dsi->image_addr;
158 int h, i;
160 if ( !dsi->load_symtab )
161 return;
163 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
164 symva = maxva;
165 maxva += sizeof(int);
166 dsi->symtab_addr = maxva;
167 dsi->symtab_len = 0;
168 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
169 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
170 if ( doload )
171 {
172 p = (void *)symva;
173 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
174 memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr));
175 }
176 else
177 {
178 p = NULL;
179 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
180 }
182 for ( h = 0; h < ehdr->e_shnum; h++ )
183 {
184 if ( shdr[h].sh_type == SHT_STRTAB )
185 {
186 /* Look for a strtab @i linked to symtab @h. */
187 for ( i = 0; i < ehdr->e_shnum; i++ )
188 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
189 (shdr[i].sh_link == h) )
190 break;
191 /* Skip symtab @h if we found no corresponding strtab @i. */
192 if ( i == ehdr->e_shnum )
193 {
194 if (doload) {
195 shdr[h].sh_offset = 0;
196 }
197 continue;
198 }
199 }
201 if ( (shdr[h].sh_type == SHT_STRTAB) ||
202 (shdr[h].sh_type == SHT_SYMTAB) )
203 {
204 if (doload) {
205 memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
206 shdr[h].sh_size);
208 /* Mangled to be based on ELF header location. */
209 shdr[h].sh_offset = maxva - dsi->symtab_addr;
211 }
212 dsi->symtab_len += shdr[h].sh_size;
213 maxva += shdr[h].sh_size;
214 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
215 }
217 if ( doload )
218 shdr[h].sh_name = 0; /* Name is NULL. */
219 }
221 if ( dsi->symtab_len == 0 )
222 {
223 dsi->symtab_addr = 0;
224 return;
225 }
227 if ( doload )
228 {
229 *(int *)p = maxva - dsi->symtab_addr;
230 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
231 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
232 sym_ehdr->e_phoff = 0;
233 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
234 sym_ehdr->e_phentsize = 0;
235 sym_ehdr->e_phnum = 0;
236 sym_ehdr->e_shstrndx = SHN_UNDEF;
237 }
239 dsi->symtab_len = maxva - dsi->symtab_addr;
240 dsi->v_end = maxva;
241 }
243 /*
244 * Local variables:
245 * mode: C
246 * c-set-style: "BSD"
247 * c-basic-offset: 4
248 * tab-width: 4
249 * indent-tabs-mode: nil
250 * End:
251 */