direct-io.hg

view xen/common/elf.c @ 3578:9bf594bc4824

bitkeeper revision 1.1159.223.49 (41fa5538VkhzExY3oLvE43gn3nUTRQ)

trivial elf-parsing fix.
author kaf24@scramble.cl.cam.ac.uk
date Fri Jan 28 15:07:36 2005 +0000 (2005-01-28)
parents d331c6994d28
children 2266301ae541 da63c1ee596f
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>
13 #ifdef CONFIG_X86
14 #define FORCE_XENELF_IMAGE 1
15 #define ELF_ADDR p_vaddr
16 #elif defined(__ia64__)
17 #define FORCE_XENELF_IMAGE 0
18 #define ELF_ADDR p_paddr
19 #endif
21 static inline int is_loadable_phdr(Elf_Phdr *phdr)
22 {
23 return ((phdr->p_type == PT_LOAD) &&
24 ((phdr->p_flags & (PF_W|PF_X)) != 0));
25 }
27 int parseelfimage(char *elfbase,
28 unsigned long elfsize,
29 struct domain_setup_info *dsi)
30 {
31 Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
32 Elf_Phdr *phdr;
33 Elf_Shdr *shdr;
34 unsigned long kernstart = ~0UL, kernend=0UL;
35 char *shstrtab, *guestinfo=NULL, *p;
36 int h;
38 if ( !IS_ELF(*ehdr) )
39 {
40 printk("Kernel image does not have an ELF header.\n");
41 return -EINVAL;
42 }
44 if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
45 {
46 printk("ELF program headers extend beyond end of image.\n");
47 return -EINVAL;
48 }
50 if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
51 {
52 printk("ELF section headers extend beyond end of image.\n");
53 return -EINVAL;
54 }
56 /* Find the section-header strings table. */
57 if ( ehdr->e_shstrndx == SHN_UNDEF )
58 {
59 printk("ELF image has no section-header strings table (shstrtab).\n");
60 return -EINVAL;
61 }
62 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff +
63 (ehdr->e_shstrndx*ehdr->e_shentsize));
64 shstrtab = elfbase + shdr->sh_offset;
66 /* Find the special '__xen_guest' section and check its contents. */
67 for ( h = 0; h < ehdr->e_shnum; h++ )
68 {
69 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
70 if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
71 continue;
73 guestinfo = elfbase + shdr->sh_offset;
74 printk("Xen-ELF header found: '%s'\n", guestinfo);
76 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
77 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
78 {
79 printk("ERROR: Xen will only load images built for the generic "
80 "loader or Linux images\n");
81 return -EINVAL;
82 }
84 if ( (strstr(guestinfo, "XEN_VER=2.0") == NULL) )
85 {
86 printk("ERROR: Xen will only load images built for Xen v2.0\n");
87 return -EINVAL;
88 }
90 break;
91 }
92 if ( guestinfo == NULL )
93 {
94 printk("Not a Xen-ELF image: '__xen_guest' section not found.\n");
95 #if FORCE_XENELF_IMAGE
96 return -EINVAL;
97 #endif
98 }
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 if ( phdr->ELF_ADDR < kernstart )
106 kernstart = phdr->ELF_ADDR;
107 if ( (phdr->ELF_ADDR + phdr->p_memsz) > kernend )
108 kernend = phdr->ELF_ADDR + phdr->p_memsz;
109 }
111 if ( (kernstart > kernend) ||
112 (ehdr->e_entry < kernstart) ||
113 (ehdr->e_entry > kernend) )
114 {
115 printk("Malformed ELF image.\n");
116 return -EINVAL;
117 }
119 dsi->v_start = kernstart;
121 if ( guestinfo != NULL )
122 {
123 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
124 dsi->v_start = simple_strtoul(p+10, &p, 0);
126 if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
127 dsi->use_writable_pagetables = 1;
128 }
130 dsi->v_kernstart = kernstart;
131 dsi->v_kernend = kernend;
132 dsi->v_kernentry = ehdr->e_entry;
134 return 0;
135 }
137 int loadelfimage(char *elfbase)
138 {
139 Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
140 Elf_Phdr *phdr;
141 int h;
143 for ( h = 0; h < ehdr->e_phnum; h++ )
144 {
145 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
146 if ( !is_loadable_phdr(phdr) )
147 continue;
148 if ( phdr->p_filesz != 0 )
149 memcpy((char *)phdr->ELF_ADDR, elfbase + phdr->p_offset,
150 phdr->p_filesz);
151 if ( phdr->p_memsz > phdr->p_filesz )
152 memset((char *)phdr->ELF_ADDR + phdr->p_filesz, 0,
153 phdr->p_memsz - phdr->p_filesz);
154 }
156 return 0;
157 }