ia64/xen-unstable

view xen/common/elf.c @ 10570:8dc4af3f192c

[IA64] Implement and use DOM0_DOMAIN_STEUP.

DOM0_GETMEMLIST now reads ptes and use gpfn.
Domain builder reworked: calls DOMAIN_SETUP, setup start_info page.
SAL data are now in domain memory.
is_vti field added in domain.arch.
Many cleanups (indentation, static, warnings).

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Wed Jul 05 09:28:32 2006 -0600 (2006-07-05)
parents 14717dedba02
children d49e5cc672eb
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, vaddr, virt_base, elf_pa_off;
27 char *shstrtab, *guestinfo=NULL, *p;
28 char *elfbase = (char *)dsi->image_addr;
29 int h, virt_base_defined, elf_pa_off_defined;
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;
65 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
66 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
67 {
68 printk("ERROR: Xen will only load images built for the generic "
69 "loader or Linux images\n");
70 return -EINVAL;
71 }
73 if ( (strstr(guestinfo, "XEN_VER=xen-3.0") == NULL) )
74 {
75 printk("ERROR: Xen will only load images built for Xen v3.0\n");
76 return -EINVAL;
77 }
79 break;
80 }
82 dsi->xen_section_string = guestinfo;
84 if ( guestinfo == NULL )
85 guestinfo = "";
87 /* Initial guess for virt_base is 0 if it is not explicitly defined. */
88 p = strstr(guestinfo, "VIRT_BASE=");
89 virt_base_defined = (p != NULL);
90 virt_base = virt_base_defined ? simple_strtoul(p+10, &p, 0) : 0;
92 /* Initial guess for elf_pa_off is virt_base if not explicitly defined. */
93 p = strstr(guestinfo, "ELF_PADDR_OFFSET=");
94 elf_pa_off_defined = (p != NULL);
95 elf_pa_off = elf_pa_off_defined ? simple_strtoul(p+17, &p, 0) : virt_base;
97 if ( elf_pa_off_defined && !virt_base_defined )
98 goto bad_image;
100 for ( h = 0; h < ehdr->e_phnum; h++ )
101 {
102 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
103 if ( !is_loadable_phdr(phdr) )
104 continue;
105 vaddr = phdr->p_paddr - elf_pa_off + virt_base;
106 if ( (vaddr + phdr->p_memsz) < vaddr )
107 goto bad_image;
108 if ( vaddr < kernstart )
109 kernstart = vaddr;
110 if ( (vaddr + phdr->p_memsz) > kernend )
111 kernend = vaddr + phdr->p_memsz;
112 }
114 /*
115 * Legacy compatibility and images with no __xen_guest section: assume
116 * header addresses are virtual addresses, and that guest memory should be
117 * mapped starting at kernel load address.
118 */
119 dsi->v_start = virt_base_defined ? virt_base : kernstart;
120 dsi->elf_paddr_offset = elf_pa_off_defined ? elf_pa_off : dsi->v_start;
122 dsi->v_kernentry = ehdr->e_entry;
123 if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL )
124 dsi->v_kernentry = simple_strtoul(p+11, &p, 0);
126 if ( (kernstart > kernend) ||
127 (dsi->v_kernentry < kernstart) ||
128 (dsi->v_kernentry > kernend) ||
129 (dsi->v_start > kernstart) )
130 goto bad_image;
132 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
133 dsi->load_symtab = 1;
135 dsi->v_kernstart = kernstart;
136 dsi->v_kernend = kernend;
137 dsi->v_end = dsi->v_kernend;
139 loadelfsymtab(dsi, 0);
141 return 0;
143 bad_image:
144 printk("Malformed ELF image.\n");
145 return -EINVAL;
146 }
148 int loadelfimage(struct domain_setup_info *dsi)
149 {
150 char *elfbase = (char *)dsi->image_addr;
151 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
152 Elf_Phdr *phdr;
153 unsigned long vaddr;
154 int h;
156 for ( h = 0; h < ehdr->e_phnum; h++ )
157 {
158 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
159 if ( !is_loadable_phdr(phdr) )
160 continue;
161 vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start;
162 if ( phdr->p_filesz != 0 )
163 memcpy((char *)vaddr, elfbase + phdr->p_offset, phdr->p_filesz);
164 if ( phdr->p_memsz > phdr->p_filesz )
165 memset((char *)vaddr + phdr->p_filesz, 0,
166 phdr->p_memsz - phdr->p_filesz);
167 }
169 loadelfsymtab(dsi, 1);
171 return 0;
172 }
174 #define ELFROUND (ELFSIZE / 8)
176 static void loadelfsymtab(struct domain_setup_info *dsi, int doload)
177 {
178 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr;
179 Elf_Shdr *shdr;
180 unsigned long maxva, symva;
181 char *p, *elfbase = (char *)dsi->image_addr;
182 int h, i;
184 if ( !dsi->load_symtab )
185 return;
187 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
188 symva = maxva;
189 maxva += sizeof(int);
190 dsi->symtab_addr = maxva;
191 dsi->symtab_len = 0;
192 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
193 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
194 if ( doload )
195 {
196 p = (void *)symva;
197 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
198 memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr));
199 }
200 else
201 {
202 p = NULL;
203 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
204 }
206 for ( h = 0; h < ehdr->e_shnum; h++ )
207 {
208 if ( shdr[h].sh_type == SHT_STRTAB )
209 {
210 /* Look for a strtab @i linked to symtab @h. */
211 for ( i = 0; i < ehdr->e_shnum; i++ )
212 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
213 (shdr[i].sh_link == h) )
214 break;
215 /* Skip symtab @h if we found no corresponding strtab @i. */
216 if ( i == ehdr->e_shnum )
217 {
218 if (doload) {
219 shdr[h].sh_offset = 0;
220 }
221 continue;
222 }
223 }
225 if ( (shdr[h].sh_type == SHT_STRTAB) ||
226 (shdr[h].sh_type == SHT_SYMTAB) )
227 {
228 if (doload) {
229 memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
230 shdr[h].sh_size);
232 /* Mangled to be based on ELF header location. */
233 shdr[h].sh_offset = maxva - dsi->symtab_addr;
235 }
236 dsi->symtab_len += shdr[h].sh_size;
237 maxva += shdr[h].sh_size;
238 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
239 }
241 if ( doload )
242 shdr[h].sh_name = 0; /* Name is NULL. */
243 }
245 if ( dsi->symtab_len == 0 )
246 {
247 dsi->symtab_addr = 0;
248 return;
249 }
251 if ( doload )
252 {
253 *(int *)p = maxva - dsi->symtab_addr;
254 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
255 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
256 sym_ehdr->e_phoff = 0;
257 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
258 sym_ehdr->e_phentsize = 0;
259 sym_ehdr->e_phnum = 0;
260 sym_ehdr->e_shstrndx = SHN_UNDEF;
261 }
263 dsi->symtab_len = maxva - dsi->symtab_addr;
264 dsi->v_end = maxva;
265 }
267 /*
268 * Local variables:
269 * mode: C
270 * c-set-style: "BSD"
271 * c-basic-offset: 4
272 * tab-width: 4
273 * indent-tabs-mode: nil
274 * End:
275 */