ia64/xen-unstable

view xen/common/libelf/libelf-loader.c @ 18594:5e4e234d58be

x86: Define __per_cpu_shift label to help kdump/crashdump.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Oct 08 13:11:06 2008 +0100 (2008-10-08)
parents 7ee30cf72fd3
children
line source
1 /*
2 * parse and load elf binaries
3 */
5 #include "libelf-private.h"
7 /* ------------------------------------------------------------------------ */
9 int elf_init(struct elf_binary *elf, const char *image, size_t size)
10 {
11 const elf_shdr *shdr;
12 uint64_t i, count, section, offset;
14 if ( !elf_is_elfbinary(image) )
15 {
16 elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
17 return -1;
18 }
20 memset(elf, 0, sizeof(*elf));
21 elf->image = image;
22 elf->size = size;
23 elf->ehdr = (elf_ehdr *)image;
24 elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
25 elf->data = elf->ehdr->e32.e_ident[EI_DATA];
27 /* Sanity check phdr. */
28 offset = elf_uval(elf, elf->ehdr, e_phoff) +
29 elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
30 if ( offset > elf->size )
31 {
32 elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n",
33 __FUNCTION__, offset, (unsigned long)elf->size);
34 return -1;
35 }
37 /* Sanity check shdr. */
38 offset = elf_uval(elf, elf->ehdr, e_shoff) +
39 elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf);
40 if ( offset > elf->size )
41 {
42 elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n",
43 __FUNCTION__, offset, (unsigned long)elf->size);
44 return -1;
45 }
47 /* Find section string table. */
48 section = elf_uval(elf, elf->ehdr, e_shstrndx);
49 shdr = elf_shdr_by_index(elf, section);
50 if ( shdr != NULL )
51 elf->sec_strtab = elf_section_start(elf, shdr);
53 /* Find symbol table and symbol string table. */
54 count = elf_shdr_count(elf);
55 for ( i = 0; i < count; i++ )
56 {
57 shdr = elf_shdr_by_index(elf, i);
58 if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
59 continue;
60 elf->sym_tab = shdr;
61 shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link));
62 if ( shdr == NULL )
63 {
64 elf->sym_tab = NULL;
65 continue;
66 }
67 elf->sym_strtab = elf_section_start(elf, shdr);
68 break;
69 }
71 return 0;
72 }
74 #ifndef __XEN__
75 void elf_set_logfile(struct elf_binary *elf, FILE * log, int verbose)
76 {
77 elf->log = log;
78 elf->verbose = verbose;
79 }
80 #else
81 void elf_set_verbose(struct elf_binary *elf)
82 {
83 elf->verbose = 1;
84 }
85 #endif
87 /* Calculate the required additional kernel space for the elf image */
88 void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
89 {
90 uint64_t sz;
91 const elf_shdr *shdr;
92 int i, type;
94 if ( !elf->sym_tab )
95 return;
97 pstart = elf_round_up(elf, pstart);
99 /* Space to store the size of the elf image */
100 sz = sizeof(uint32_t);
102 /* Space for the elf and elf section headers */
103 sz += (elf_uval(elf, elf->ehdr, e_ehsize) +
104 elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize));
105 sz = elf_round_up(elf, sz);
107 /* Space for the symbol and string tables. */
108 for ( i = 0; i < elf_shdr_count(elf); i++ )
109 {
110 shdr = elf_shdr_by_index(elf, i);
111 type = elf_uval(elf, (elf_shdr *)shdr, sh_type);
112 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
113 sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
114 }
116 elf->bsd_symtab_pstart = pstart;
117 elf->bsd_symtab_pend = pstart + sz;
118 }
120 static void elf_load_bsdsyms(struct elf_binary *elf)
121 {
122 elf_ehdr *sym_ehdr;
123 unsigned long sz;
124 char *maxva, *symbase, *symtab_addr;
125 elf_shdr *shdr;
126 int i, type;
128 if ( !elf->bsd_symtab_pstart )
129 return;
131 #define elf_hdr_elm(_elf, _hdr, _elm, _val) \
132 do { \
133 if ( elf_64bit(_elf) ) \
134 (_hdr)->e64._elm = _val; \
135 else \
136 (_hdr)->e32._elm = _val; \
137 } while ( 0 )
139 symbase = elf_get_ptr(elf, elf->bsd_symtab_pstart);
140 symtab_addr = maxva = symbase + sizeof(uint32_t);
142 /* Set up Elf header. */
143 sym_ehdr = (elf_ehdr *)symtab_addr;
144 sz = elf_uval(elf, elf->ehdr, e_ehsize);
145 memcpy(sym_ehdr, elf->ehdr, sz);
146 maxva += sz; /* no round up */
148 elf_hdr_elm(elf, sym_ehdr, e_phoff, 0);
149 elf_hdr_elm(elf, sym_ehdr, e_shoff, elf_uval(elf, elf->ehdr, e_ehsize));
150 elf_hdr_elm(elf, sym_ehdr, e_phentsize, 0);
151 elf_hdr_elm(elf, sym_ehdr, e_phnum, 0);
153 /* Copy Elf section headers. */
154 shdr = (elf_shdr *)maxva;
155 sz = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize);
156 memcpy(shdr, elf->image + elf_uval(elf, elf->ehdr, e_shoff), sz);
157 maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
159 for ( i = 0; i < elf_shdr_count(elf); i++ )
160 {
161 type = elf_uval(elf, shdr, sh_type);
162 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
163 {
164 elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i,
165 elf_section_start(elf, shdr), maxva);
166 sz = elf_uval(elf, shdr, sh_size);
167 memcpy(maxva, elf_section_start(elf, shdr), sz);
168 /* Mangled to be based on ELF header location. */
169 elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
170 maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
171 }
172 shdr = (elf_shdr *)((long)shdr +
173 (long)elf_uval(elf, elf->ehdr, e_shentsize));
174 }
176 /* Write down the actual sym size. */
177 *(uint32_t *)symbase = maxva - symtab_addr;
179 #undef elf_ehdr_elm
180 }
182 void elf_parse_binary(struct elf_binary *elf)
183 {
184 const elf_phdr *phdr;
185 uint64_t low = -1;
186 uint64_t high = 0;
187 uint64_t i, count, paddr, memsz;
189 count = elf_uval(elf, elf->ehdr, e_phnum);
190 for ( i = 0; i < count; i++ )
191 {
192 phdr = elf_phdr_by_index(elf, i);
193 if ( !elf_phdr_is_loadable(elf, phdr) )
194 continue;
195 paddr = elf_uval(elf, phdr, p_paddr);
196 memsz = elf_uval(elf, phdr, p_memsz);
197 elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64
198 " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz);
199 if ( low > paddr )
200 low = paddr;
201 if ( high < paddr + memsz )
202 high = paddr + memsz;
203 }
204 elf->pstart = low;
205 elf->pend = high;
206 elf_msg(elf, "%s: memory: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
207 __FUNCTION__, elf->pstart, elf->pend);
208 }
210 void elf_load_binary(struct elf_binary *elf)
211 {
212 const elf_phdr *phdr;
213 uint64_t i, count, paddr, offset, filesz, memsz;
214 char *dest;
216 count = elf_uval(elf, elf->ehdr, e_phnum);
217 for ( i = 0; i < count; i++ )
218 {
219 phdr = elf_phdr_by_index(elf, i);
220 if ( !elf_phdr_is_loadable(elf, phdr) )
221 continue;
222 paddr = elf_uval(elf, phdr, p_paddr);
223 offset = elf_uval(elf, phdr, p_offset);
224 filesz = elf_uval(elf, phdr, p_filesz);
225 memsz = elf_uval(elf, phdr, p_memsz);
226 dest = elf_get_ptr(elf, paddr);
227 elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
228 __func__, i, dest, dest + filesz);
229 memcpy(dest, elf->image + offset, filesz);
230 memset(dest + filesz, 0, memsz - filesz);
231 }
233 elf_load_bsdsyms(elf);
234 }
236 void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
237 {
238 return elf->dest + addr - elf->pstart;
239 }
241 uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
242 {
243 const elf_sym *sym;
244 uint64_t value;
246 sym = elf_sym_by_name(elf, symbol);
247 if ( sym == NULL )
248 {
249 elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol);
250 return -1;
251 }
253 value = elf_uval(elf, sym, st_value);
254 elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __FUNCTION__,
255 symbol, value);
256 return value;
257 }
259 /*
260 * Local variables:
261 * mode: C
262 * c-set-style: "BSD"
263 * c-basic-offset: 4
264 * tab-width: 4
265 * indent-tabs-mode: nil
266 * End:
267 */