ia64/xen-unstable

view xen/common/elf.c @ 9706:3c05406f5e0a

In some cases, say for instance for some bizzare reason
the tree was checked out of CVS, which doens't neccessarily
store file permissions, mkbuildtree may not be executable.
So run them explicitly via bash.

Signed-Off-By: Horms <horms@verge.net.au>
author kaf24@firebug.cl.cam.ac.uk
date Thu Apr 13 11:24:00 2006 +0100 (2006-04-13)
parents f84d5cdd9895
children d0c7cc0afd15
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;
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 for ( h = 0; h < ehdr->e_phnum; h++ )
85 {
86 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
87 if ( !is_loadable_phdr(phdr) )
88 continue;
89 if ( phdr->p_paddr < kernstart )
90 kernstart = phdr->p_paddr;
91 if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
92 kernend = phdr->p_paddr + phdr->p_memsz;
93 }
95 if ( (kernstart > kernend) ||
96 (ehdr->e_entry < kernstart) ||
97 (ehdr->e_entry > kernend) )
98 {
99 printk("Malformed ELF image.\n");
100 return -EINVAL;
101 }
103 dsi->v_start = kernstart;
105 if ( guestinfo != NULL )
106 {
107 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
108 dsi->v_start = simple_strtoul(p+10, &p, 0);
110 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
111 dsi->load_symtab = 1;
112 }
114 dsi->v_kernstart = kernstart;
115 dsi->v_kernend = kernend;
116 dsi->v_kernentry = ehdr->e_entry;
117 dsi->v_end = dsi->v_kernend;
119 loadelfsymtab(dsi, 0);
121 return 0;
122 }
124 int loadelfimage(struct domain_setup_info *dsi)
125 {
126 char *elfbase = (char *)dsi->image_addr;
127 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
128 Elf_Phdr *phdr;
129 int h;
131 for ( h = 0; h < ehdr->e_phnum; h++ )
132 {
133 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
134 if ( !is_loadable_phdr(phdr) )
135 continue;
136 if ( phdr->p_filesz != 0 )
137 memcpy((char *)phdr->p_paddr, elfbase + phdr->p_offset,
138 phdr->p_filesz);
139 if ( phdr->p_memsz > phdr->p_filesz )
140 memset((char *)phdr->p_paddr + phdr->p_filesz, 0,
141 phdr->p_memsz - phdr->p_filesz);
142 }
144 loadelfsymtab(dsi, 1);
146 return 0;
147 }
149 #define ELFROUND (ELFSIZE / 8)
151 static void loadelfsymtab(struct domain_setup_info *dsi, int doload)
152 {
153 Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr;
154 Elf_Shdr *shdr;
155 unsigned long maxva, symva;
156 char *p, *elfbase = (char *)dsi->image_addr;
157 int h, i;
159 if ( !dsi->load_symtab )
160 return;
162 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
163 symva = maxva;
164 maxva += sizeof(int);
165 dsi->symtab_addr = maxva;
166 dsi->symtab_len = 0;
167 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
168 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
169 if ( doload )
170 {
171 p = (void *)symva;
172 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
173 memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr));
174 }
175 else
176 {
177 p = NULL;
178 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
179 }
181 for ( h = 0; h < ehdr->e_shnum; h++ )
182 {
183 if ( shdr[h].sh_type == SHT_STRTAB )
184 {
185 /* Look for a strtab @i linked to symtab @h. */
186 for ( i = 0; i < ehdr->e_shnum; i++ )
187 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
188 (shdr[i].sh_link == h) )
189 break;
190 /* Skip symtab @h if we found no corresponding strtab @i. */
191 if ( i == ehdr->e_shnum )
192 {
193 if (doload) {
194 shdr[h].sh_offset = 0;
195 }
196 continue;
197 }
198 }
200 if ( (shdr[h].sh_type == SHT_STRTAB) ||
201 (shdr[h].sh_type == SHT_SYMTAB) )
202 {
203 if (doload) {
204 memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
205 shdr[h].sh_size);
207 /* Mangled to be based on ELF header location. */
208 shdr[h].sh_offset = maxva - dsi->symtab_addr;
210 }
211 dsi->symtab_len += shdr[h].sh_size;
212 maxva += shdr[h].sh_size;
213 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
214 }
216 if ( doload )
217 shdr[h].sh_name = 0; /* Name is NULL. */
218 }
220 if ( dsi->symtab_len == 0 )
221 {
222 dsi->symtab_addr = 0;
223 return;
224 }
226 if ( doload )
227 {
228 *(int *)p = maxva - dsi->symtab_addr;
229 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
230 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
231 sym_ehdr->e_phoff = 0;
232 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
233 sym_ehdr->e_phentsize = 0;
234 sym_ehdr->e_phnum = 0;
235 sym_ehdr->e_shstrndx = SHN_UNDEF;
236 }
238 dsi->symtab_len = maxva - dsi->symtab_addr;
239 dsi->v_end = maxva;
240 }
242 /*
243 * Local variables:
244 * mode: C
245 * c-set-style: "BSD"
246 * c-basic-offset: 4
247 * tab-width: 4
248 * indent-tabs-mode: nil
249 * End:
250 */