/[gxemul]/trunk/src/file/file_elf.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/file/file_elf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (show annotations)
Wed Oct 10 21:07:01 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 21049 byte(s)
first cut at emulating DSM G600 -- serial port work and not much else...
1 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: file_elf.c,v 1.7 2007/07/20 09:03:33 debug Exp $
29 *
30 * COMMENT: ELF file support
31 */
32
33 /* Note: Included from file.c. */
34
35
36 #include "exec_elf.h"
37
38 /* ELF machine types as strings: (same as exec_elf.h) */
39 #define N_ELF_MACHINE_TYPES 89
40 static char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
41 "NONE", "M32", "SPARC", "386", /* 0..3 */
42 "68K", "88K", "486", "860", /* 4..7 */
43 "MIPS", "S370", "MIPS_RS3_LE", "RS6000", /* 8..11 */
44 "unknown12", "unknown13", "unknown14", "PARISC", /* 12..15 */
45 "NCUBE", "VPP500", "SPARC32PLUS", "960", /* 16..19 */
46 "PPC", "PPC64", "unknown22", "unknown23", /* 20..23 */
47 "unknown24", "unknown25", "unknown26", "unknown27", /* 24..27 */
48 "unknown28", "unknown29", "unknown30", "unknown31", /* 28..31 */
49 "unknown32", "unknown33", "unknown34", "unknown35", /* 32..35 */
50 "V800", "FR20", "RH32", "RCE", /* 36..39 */
51 "ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */
52 "TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */
53 "H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */
54 "COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */
55 "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */
56 "unknown60", "unknown61", "AMD64", "unknown63", /* 60..63 */
57 "unknown64", "unknown65", "unknown66", "unknown67", /* 64..67 */
58 "unknown68", "unknown69", "unknown70", "unknown71", /* 68..71 */
59 "unknown72", "unknown73", "unknown74", "unknown75", /* 72..75 */
60 "unknown76", "unknown77", "unknown78", "unknown79", /* 76..79 */
61 "unknown80", "unknown81", "unknown82", "AVR", /* 80..83 */
62 "unknown84", "unknown85", "unknown86", "unknown87", /* 84..87 */
63 "M32R" /* 88 */
64 };
65
66
67 /*
68 * file_load_elf():
69 *
70 * Loads an ELF image into the emulated memory. The entry point (read from
71 * the ELF header) and the initial value of the gp register (read from the
72 * ELF symbol table) are stored in the specified CPU's registers.
73 *
74 * This is pretty heavy stuff, but is needed because of the heaviness of
75 * ELF files. :-/ Hopefully it will be able to recognize most valid ELFs.
76 */
77 static void file_load_elf(struct machine *m, struct memory *mem,
78 char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp,
79 int *byte_order, uint64_t *tocp)
80 {
81 Elf32_Ehdr hdr32;
82 Elf64_Ehdr hdr64;
83 FILE *f;
84 uint64_t eentry;
85 int len, i, ok;
86 int elf64, encoding, eflags;
87 int etype, emachine;
88 int ephnum, ephentsize, eshnum, eshentsize;
89 off_t ephoff, eshoff;
90 Elf32_Phdr phdr32;
91 Elf64_Phdr phdr64;
92 Elf32_Shdr shdr32;
93 Elf64_Shdr shdr64;
94 Elf32_Sym sym32;
95 Elf64_Sym sym64;
96 int ofs;
97 int chunk_len = 1024, align_len;
98 char *symbol_strings = NULL; size_t symbol_length = 0;
99 char *s;
100 Elf32_Sym *symbols_sym32 = NULL; int n_symbols = 0;
101 Elf64_Sym *symbols_sym64 = NULL;
102
103 f = fopen(filename, "r");
104 if (f == NULL) {
105 perror(filename);
106 exit(1);
107 }
108
109 len = fread(&hdr32, 1, sizeof(Elf32_Ehdr), f);
110 if (len < (signed int)sizeof(Elf32_Ehdr)) {
111 fprintf(stderr, "%s: not an ELF file image\n", filename);
112 exit(1);
113 }
114
115 if (memcmp(&hdr32.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0) {
116 fprintf(stderr, "%s: not an ELF file image\n", filename);
117 exit(1);
118 }
119
120 switch (hdr32.e_ident[EI_CLASS]) {
121 case ELFCLASS32:
122 elf64 = 0;
123 break;
124 case ELFCLASS64:
125 elf64 = 1;
126 fseek(f, 0, SEEK_SET);
127 len = fread(&hdr64, 1, sizeof(Elf64_Ehdr), f);
128 if (len < (signed int)sizeof(Elf64_Ehdr)) {
129 fprintf(stderr, "%s: not an ELF64 file image\n",
130 filename);
131 exit(1);
132 }
133 break;
134 default:
135 fprintf(stderr, "%s: unknown ELF class '%i'\n",
136 filename, hdr32.e_ident[EI_CLASS]);
137 exit(1);
138 }
139
140 encoding = hdr32.e_ident[EI_DATA];
141 if (encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) {
142 fprintf(stderr, "%s: unknown data encoding '%i'\n",
143 filename, hdr32.e_ident[EI_DATA]);
144 exit(1);
145 }
146
147 if (elf64) {
148 unencode(etype, &hdr64.e_type, Elf64_Quarter);
149 unencode(eflags, &hdr64.e_flags, Elf64_Half);
150 unencode(emachine, &hdr64.e_machine, Elf64_Quarter);
151 unencode(eentry, &hdr64.e_entry, Elf64_Addr);
152 unencode(ephnum, &hdr64.e_phnum, Elf64_Quarter);
153 unencode(ephentsize, &hdr64.e_phentsize, Elf64_Quarter);
154 unencode(ephoff, &hdr64.e_phoff, Elf64_Off);
155 unencode(eshnum, &hdr64.e_shnum, Elf64_Quarter);
156 unencode(eshentsize, &hdr64.e_shentsize, Elf64_Quarter);
157 unencode(eshoff, &hdr64.e_shoff, Elf64_Off);
158 if (ephentsize != sizeof(Elf64_Phdr)) {
159 fprintf(stderr, "%s: incorrect phentsize? %i, should "
160 "be %i\nPerhaps this is a dynamically linked "
161 "binary (which isn't supported yet).\n", filename,
162 (int)ephentsize, (int)sizeof(Elf64_Phdr));
163 exit(1);
164 }
165 if (eshentsize != sizeof(Elf64_Shdr)) {
166 fprintf(stderr, "%s: incorrect shentsize? %i, should "
167 "be %i\nPerhaps this is a dynamically linked "
168 "binary (which isn't supported yet).\n", filename,
169 (int)eshentsize, (int)sizeof(Elf64_Shdr));
170 exit(1);
171 }
172 } else {
173 unencode(etype, &hdr32.e_type, Elf32_Half);
174 unencode(eflags, &hdr32.e_flags, Elf32_Word);
175 unencode(emachine, &hdr32.e_machine, Elf32_Half);
176 unencode(eentry, &hdr32.e_entry, Elf32_Addr);
177 unencode(ephnum, &hdr32.e_phnum, Elf32_Half);
178 unencode(ephentsize, &hdr32.e_phentsize, Elf32_Half);
179 unencode(ephoff, &hdr32.e_phoff, Elf32_Off);
180 unencode(eshnum, &hdr32.e_shnum, Elf32_Half);
181 unencode(eshentsize, &hdr32.e_shentsize, Elf32_Half);
182 unencode(eshoff, &hdr32.e_shoff, Elf32_Off);
183 if (ephentsize != sizeof(Elf32_Phdr)) {
184 fprintf(stderr, "%s: incorrect phentsize? %i, should "
185 "be %i\nPerhaps this is a dynamically linked "
186 "binary (which isn't supported yet).\n", filename,
187 (int)ephentsize, (int)sizeof(Elf32_Phdr));
188 exit(1);
189 }
190 if (eshentsize != sizeof(Elf32_Shdr)) {
191 fprintf(stderr, "%s: incorrect shentsize? %i, should "
192 "be %i\nPerhaps this is a dynamically linked "
193 "binary (which isn't supported yet).\n", filename,
194 (int)eshentsize, (int)sizeof(Elf32_Shdr));
195 exit(1);
196 }
197 }
198
199 if ( etype != ET_EXEC ) {
200 fprintf(stderr, "%s is not an ELF Executable file, type = %i\n",
201 filename, etype);
202 exit(1);
203 }
204
205 ok = 0;
206 switch (arch) {
207 case ARCH_ALPHA:
208 switch (emachine) {
209 case EM_ALPHA:
210 case -28634:
211 ok = 1;
212 }
213 break;
214 case ARCH_ARM:
215 switch (emachine) {
216 case EM_ARM:
217 ok = 1;
218 }
219 break;
220 /* case ARCH_AVR:
221 switch (emachine) {
222 case EM_AVR:
223 ok = 1;
224 }
225 break;
226 case ARCH_AVR32:
227 switch (emachine) {
228 case 6317:
229 ok = 1;
230 }
231 break;
232 case ARCH_HPPA:
233 switch (emachine) {
234 case EM_PARISC:
235 ok = 1;
236 }
237 break;
238 case ARCH_I960:
239 switch (emachine) {
240 case EM_960:
241 ok = 1;
242 }
243 break;
244 case ARCH_IA64:
245 switch (emachine) {
246 case EM_IA_64:
247 ok = 1;
248 }
249 break;
250 case ARCH_M68K:
251 switch (emachine) {
252 case EM_68K:
253 ok = 1;
254 }
255 break; */
256 case ARCH_M32R:
257 switch (emachine) {
258 case EM_M32R:
259 ok = 1;
260 }
261 break;
262 case ARCH_MIPS:
263 switch (emachine) {
264 case EM_MIPS:
265 case EM_MIPS_RS3_LE:
266 ok = 1;
267 }
268 break;
269 case ARCH_PPC:
270 switch (emachine) {
271 case EM_PPC:
272 case EM_PPC64:
273 ok = 1;
274 }
275 break;
276 case ARCH_SH:
277 switch (emachine) {
278 case EM_SH:
279 ok = 1;
280 }
281 break;
282 case ARCH_SPARC:
283 switch (emachine) {
284 case EM_SPARC:
285 case EM_SPARCV9:
286 ok = 1;
287 }
288 break;
289 /* case ARCH_X86:
290 switch (emachine) {
291 case EM_386:
292 case EM_486:
293 *tocp = 1;
294 ok = 1;
295 break;
296 case EM_AMD64:
297 *tocp = 2;
298 ok = 1;
299 break;
300 }
301 break; */
302 default:
303 fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n");
304 }
305 if (!ok) {
306 fprintf(stderr, "%s: this is a ", filename);
307 if (emachine >= 0 && emachine < N_ELF_MACHINE_TYPES)
308 fprintf(stderr, elf_machine_type[emachine]);
309 else
310 fprintf(stderr, "machine type '%i'", emachine);
311 fprintf(stderr, " ELF binary!\n");
312 exit(1);
313 }
314
315 s = "entry point";
316 if (elf64 && arch == ARCH_PPC)
317 s = "function descriptor at";
318
319 debug("ELF%i %s, %s 0x", elf64? 64 : 32,
320 encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s);
321
322 // XXX force load address to 0
323 eentry -= 0xc0000000;
324
325 if (elf64)
326 debug("%016"PRIx64"\n", (uint64_t) eentry);
327 else
328 debug("%08"PRIx32"\n", (uint32_t) eentry);
329
330 /*
331 * SH64: 32-bit instruction encoding?
332 */
333 if (arch == ARCH_SH && (eentry & 1)) {
334 fatal("SH64: 32-bit instruction encoding: TODO\n");
335 /* m->cpus[0]->cd.sh.compact = 0; */
336 m->cpus[0]->cd.sh.cpu_type.bits = 64;
337 exit(1);
338 }
339
340 /* Read the program headers: */
341
342 for (i=0; i<ephnum; i++) {
343 int p_type;
344 uint64_t p_offset;
345 uint64_t p_vaddr;
346 uint64_t p_paddr;
347 uint64_t p_filesz;
348 uint64_t p_memsz;
349 int p_flags;
350 int p_align;
351
352 fseek(f, ephoff + i * ephentsize, SEEK_SET);
353
354 if (elf64) {
355 fread(&phdr64, 1, sizeof(Elf64_Phdr), f);
356 unencode(p_type, &phdr64.p_type, Elf64_Half);
357 unencode(p_flags, &phdr64.p_flags, Elf64_Half);
358 unencode(p_offset, &phdr64.p_offset, Elf64_Off);
359 unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr);
360 unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr);
361 unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword);
362 unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword);
363 unencode(p_align, &phdr64.p_align, Elf64_Xword);
364 } else {
365 fread(&phdr32, 1, sizeof(Elf32_Phdr), f);
366 unencode(p_type, &phdr32.p_type, Elf32_Word);
367 unencode(p_offset, &phdr32.p_offset, Elf32_Off);
368 unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr);
369 unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr);
370 unencode(p_filesz, &phdr32.p_filesz, Elf32_Word);
371 unencode(p_memsz, &phdr32.p_memsz, Elf32_Word);
372 unencode(p_flags, &phdr32.p_flags, Elf32_Word);
373 unencode(p_align, &phdr32.p_align, Elf32_Word);
374 }
375
376 /*
377 * Hack for loading PPC kernels that are linked to high
378 * addresses. (This requires enabling of instruction and
379 * data virtual address translation.)
380 */
381 if (arch == ARCH_PPC) {
382 if ( (elf64 && (p_vaddr >> 60) != 0) ||
383 (!elf64 && (p_vaddr >> 28) != 0) )
384 m->cpus[m->bootstrap_cpu]->
385 cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR;
386 }
387
388 if (p_memsz != 0 && (p_type == PT_LOAD ||
389 (p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) {
390 debug("chunk %i (", i);
391 if (p_type == PT_LOAD)
392 debug("load");
393 else
394 debug("0x%08"PRIx32, (uint32_t) p_type);
395
396 debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset);
397
398 if (elf64)
399 debug("%016"PRIx64, (uint64_t) p_vaddr);
400 else
401 debug("%08"PRIx32, (uint32_t) p_vaddr);
402
403 debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz);
404
405 if (p_vaddr != p_paddr) {
406 if (elf64)
407 debug("NOTE: vaddr (0x%"PRIx64") and "
408 "paddr (0x%"PRIx64") differ; using "
409 "vaddr\n", (uint64_t) p_vaddr,
410 (uint64_t) p_paddr);
411 else
412 debug("NOTE: vaddr (0x%08"PRIx32") and "
413 "paddr (0x%08"PRIx32") differ; usin"
414 "g vaddr\n", (uint32_t) p_vaddr,
415 (uint32_t)p_paddr);
416 }
417
418 if (p_memsz < p_filesz) {
419 fprintf(stderr, "%s: memsz < filesz. TODO: how"
420 " to handle this? memsz=%016"PRIx64
421 " filesz=%016"PRIx64"\n", filename,
422 (uint64_t) p_memsz, (uint64_t) p_filesz);
423 exit(1);
424 }
425
426 fseek(f, p_offset, SEEK_SET);
427 align_len = 1;
428 if ((p_vaddr & 0xf)==0) align_len = 0x10;
429 if ((p_vaddr & 0x3f)==0) align_len = 0x40;
430 if ((p_vaddr & 0xff)==0) align_len = 0x100;
431 if ((p_vaddr & 0xfff)==0) align_len = 0x1000;
432 if ((p_vaddr & 0x3fff)==0) align_len = 0x4000;
433 if ((p_vaddr & 0xffff)==0) align_len = 0x10000;
434 ofs = 0; len = chunk_len = align_len;
435 while (ofs < (int64_t)p_filesz && len==chunk_len) {
436 unsigned char *ch;
437 int i = 0;
438
439 CHECK_ALLOCATION(ch = malloc(chunk_len));
440
441 /* Switch to larger size, if possible: */
442 if (align_len < 0x10000 &&
443 ((p_vaddr + ofs) & 0xffff)==0) {
444 align_len = 0x10000;
445 len = chunk_len = align_len;
446 free(ch);
447 CHECK_ALLOCATION(ch=malloc(chunk_len));
448 } else if (align_len < 0x1000 &&
449 ((p_vaddr + ofs) & 0xfff)==0) {
450 align_len = 0x1000;
451 len = chunk_len = align_len;
452 free(ch);
453 CHECK_ALLOCATION(ch=malloc(chunk_len));
454 }
455
456 len = fread(&ch[0], 1, chunk_len, f);
457 if (ofs + len > (int64_t)p_filesz)
458 len = p_filesz - ofs;
459
460 while (i < len) {
461 size_t len_to_copy;
462 len_to_copy = (i + align_len) <= len?
463 align_len : len - i;
464 m->cpus[0]->memory_rw(m->cpus[0], mem,
465 p_vaddr + ofs, &ch[i], len_to_copy,
466 MEM_WRITE, NO_EXCEPTIONS);
467 ofs += align_len;
468 i += align_len;
469 }
470
471 free(ch);
472 }
473 }
474 }
475
476 /*
477 * Read the section headers to find the address of the _gp
478 * symbol (for MIPS):
479 */
480
481 for (i=0; i<eshnum; i++) {
482 int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize;
483 uint64_t sh_addr, sh_size, sh_addralign;
484 off_t sh_offset;
485 int n_entries; /* for reading the symbol / string tables */
486
487 /* debug("section header %i at %016"PRIx64"\n", i,
488 (uint64_t) eshoff+i*eshentsize); */
489
490 fseek(f, eshoff + i * eshentsize, SEEK_SET);
491
492 if (elf64) {
493 len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f);
494 if (len != sizeof(Elf64_Shdr)) {
495 fprintf(stderr, "couldn't read header\n");
496 exit(1);
497 }
498 unencode(sh_name, &shdr64.sh_name, Elf64_Half);
499 unencode(sh_type, &shdr64.sh_type, Elf64_Half);
500 unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword);
501 unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr);
502 unencode(sh_offset, &shdr64.sh_offset, Elf64_Off);
503 unencode(sh_size, &shdr64.sh_size, Elf64_Xword);
504 unencode(sh_link, &shdr64.sh_link, Elf64_Half);
505 unencode(sh_info, &shdr64.sh_info, Elf64_Half);
506 unencode(sh_addralign, &shdr64.sh_addralign,
507 Elf64_Xword);
508 unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword);
509 } else {
510 len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f);
511 if (len != sizeof(Elf32_Shdr)) {
512 fprintf(stderr, "couldn't read header\n");
513 exit(1);
514 }
515 unencode(sh_name, &shdr32.sh_name, Elf32_Word);
516 unencode(sh_type, &shdr32.sh_type, Elf32_Word);
517 unencode(sh_flags, &shdr32.sh_flags, Elf32_Word);
518 unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr);
519 unencode(sh_offset, &shdr32.sh_offset, Elf32_Off);
520 unencode(sh_size, &shdr32.sh_size, Elf32_Word);
521 unencode(sh_link, &shdr32.sh_link, Elf32_Word);
522 unencode(sh_info, &shdr32.sh_info, Elf32_Word);
523 unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word);
524 unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word);
525 }
526
527 /* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx"
528 " sh_size=%06lx sh_entsize=%03lx\n",
529 (long)sh_name, (long)sh_type, (long)sh_flags,
530 (long)sh_size, (long)sh_entsize); */
531
532 /* Perhaps it is bad to reuse sh_entsize like this? TODO */
533 if (elf64)
534 sh_entsize = sizeof(Elf64_Sym);
535 else
536 sh_entsize = sizeof(Elf32_Sym);
537
538 if (sh_type == SHT_SYMTAB) {
539 size_t len;
540 n_entries = sh_size / sh_entsize;
541
542 fseek(f, sh_offset, SEEK_SET);
543
544 if (elf64) {
545 if (symbols_sym64 != NULL)
546 free(symbols_sym64);
547
548 CHECK_ALLOCATION(symbols_sym64 =
549 malloc(sh_size));
550
551 len = fread(symbols_sym64, 1, sh_entsize *
552 n_entries, f);
553 } else {
554 if (symbols_sym32 != NULL)
555 free(symbols_sym32);
556
557 CHECK_ALLOCATION(symbols_sym32 =
558 malloc(sh_size));
559
560 len = fread(symbols_sym32, 1,
561 sh_entsize * n_entries, f);
562 }
563
564 if (len != sh_size) {
565 fprintf(stderr, "could not read symbols from "
566 "%s\n", filename);
567 exit(1);
568 }
569
570 debug("%i symbol entries at 0x%"PRIx64"\n",
571 (int) n_entries, (uint64_t) sh_offset);
572
573 n_symbols = n_entries;
574 }
575
576 /*
577 * TODO: This is incorrect, there may be several strtab
578 * sections.
579 *
580 * For now, the simple/stupid guess that the largest string
581 * table is the one to use seems to be good enough.
582 */
583
584 if (sh_type == SHT_STRTAB && sh_size > symbol_length) {
585 size_t len;
586
587 if (symbol_strings != NULL)
588 free(symbol_strings);
589
590 CHECK_ALLOCATION(symbol_strings = malloc(sh_size + 1));
591
592 fseek(f, sh_offset, SEEK_SET);
593 len = fread(symbol_strings, 1, sh_size, f);
594 if (len != sh_size) {
595 fprintf(stderr, "could not read symbols from "
596 "%s\n", filename);
597 exit(1);
598 }
599
600 debug("%i bytes of symbol strings at 0x%"PRIx64"\n",
601 (int) sh_size, (uint64_t) sh_offset);
602
603 symbol_strings[sh_size] = '\0';
604 symbol_length = sh_size;
605 }
606 }
607
608 fclose(f);
609
610 /* Decode symbols: */
611 if (symbol_strings != NULL) {
612 for (i=0; i<n_symbols; i++) {
613 uint64_t st_name, addr, size;
614 int st_info;
615
616 if (elf64) {
617 sym64 = symbols_sym64[i];
618 unencode(st_name, &sym64.st_name, Elf64_Half);
619 unencode(st_info, &sym64.st_info, Elf_Byte);
620 unencode(addr, &sym64.st_value, Elf64_Addr);
621 unencode(size, &sym64.st_size, Elf64_Xword);
622 } else {
623 sym32 = symbols_sym32[i];
624 unencode(st_name, &sym32.st_name, Elf32_Word);
625 unencode(st_info, &sym32.st_info, Elf_Byte);
626 unencode(addr, &sym32.st_value, Elf32_Word);
627 unencode(size, &sym32.st_size, Elf32_Word);
628 }
629
630 /* debug("symbol info=0x%02x addr=0x%016"PRIx64
631 " (%i) '%s'\n", st_info, (uint64_t) addr,
632 st_name, symbol_strings + st_name); */
633
634 if (size == 0)
635 size ++;
636
637 if (addr != 0) /* && ((st_info >> 4) & 0xf)
638 >= STB_GLOBAL) */ {
639 /* debug("symbol info=0x%02x addr=0x%016"PRIx64
640 " '%s'\n", st_info, (uint64_t) addr,
641 symbol_strings + st_name); */
642 add_symbol_name(&m->symbol_context,
643 addr, size, symbol_strings + st_name,
644 0, -1);
645 }
646
647 if (strcmp(symbol_strings + st_name, "_gp") == 0) {
648 debug("found _gp address: 0x");
649 if (elf64)
650 debug("%016"PRIx64"\n", (uint64_t)addr);
651 else
652 debug("%08"PRIx32"\n", (uint32_t)addr);
653 *gpp = addr;
654 }
655 }
656 }
657
658 *entrypointp = eentry;
659
660 if (encoding == ELFDATA2LSB)
661 *byte_order = EMUL_LITTLE_ENDIAN;
662 else
663 *byte_order = EMUL_BIG_ENDIAN;
664
665 if (elf64 && arch == ARCH_PPC) {
666 /*
667 * Special case for 64-bit PPC ELFs:
668 *
669 * The ELF starting symbol points to a ".opd" section
670 * which contains a function descriptor:
671 *
672 * uint64_t start;
673 * uint64_t toc_base;
674 * uint64_t something_else; (?)
675 */
676 int res;
677 unsigned char b[sizeof(uint64_t)];
678 uint64_t toc_base;
679
680 debug("PPC64: ");
681
682 res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
683 sizeof(b), MEM_READ, NO_EXCEPTIONS);
684 if (!res)
685 debug(" [WARNING: could not read memory?] ");
686
687 /* PPC are always big-endian: */
688 *entrypointp = ((uint64_t)b[0] << 56) +
689 ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
690 ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
691 ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
692 (uint64_t)b[7];
693
694 res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
695 b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
696 if (!res)
697 fatal(" [WARNING: could not read memory?] ");
698
699 toc_base = ((uint64_t)b[0] << 56) +
700 ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
701 ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
702 ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
703 (uint64_t)b[7];
704
705 debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n",
706 (uint64_t) *entrypointp, (uint64_t) toc_base);
707 if (tocp != NULL)
708 *tocp = toc_base;
709 }
710
711 n_executables_loaded ++;
712 }
713

  ViewVC Help
Powered by ViewVC 1.1.26