ia64/xen-unstable

view xen/common/elf.c @ 9776:72f9c751d3ea

Replace &foo[0] with foo where the latter seems cleaner
(which is usually, and particularly when its an argument
to one of the bitops functions).

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Apr 19 18:32:20 2006 +0100 (2006-04-19)
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 */