/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (hide annotations)
Wed Oct 10 21:07:01 2007 UTC (16 years, 7 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 dpavlin 38 /*
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 dpavlin 44 * $Id: file_elf.c,v 1.7 2007/07/20 09:03:33 debug Exp $
29 dpavlin 38 *
30 dpavlin 44 * COMMENT: ELF file support
31 dpavlin 38 */
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 dpavlin 44 #define N_ELF_MACHINE_TYPES 89
40 dpavlin 38 static char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
41 dpavlin 44 "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 dpavlin 38 };
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 dpavlin 42 /* case ARCH_AVR:
221 dpavlin 38 switch (emachine) {
222     case EM_AVR:
223     ok = 1;
224     }
225     break;
226 dpavlin 42 case ARCH_AVR32:
227 dpavlin 38 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 dpavlin 44 break;
250     case ARCH_M68K:
251 dpavlin 38 switch (emachine) {
252     case EM_68K:
253     ok = 1;
254     }
255 dpavlin 40 break; */
256 dpavlin 44 case ARCH_M32R:
257     switch (emachine) {
258     case EM_M32R:
259     ok = 1;
260     }
261     break;
262 dpavlin 38 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 dpavlin 46 // XXX force load address to 0
323     eentry -= 0xc0000000;
324    
325 dpavlin 38 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 dpavlin 42 fatal("SH64: 32-bit instruction encoding: TODO\n");
335     /* m->cpus[0]->cd.sh.compact = 0; */
336 dpavlin 38 m->cpus[0]->cd.sh.cpu_type.bits = 64;
337 dpavlin 42 exit(1);
338 dpavlin 38 }
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 dpavlin 42 unsigned char *ch;
437 dpavlin 38 int i = 0;
438    
439 dpavlin 42 CHECK_ALLOCATION(ch = malloc(chunk_len));
440    
441 dpavlin 38 /* 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 dpavlin 42 CHECK_ALLOCATION(ch=malloc(chunk_len));
448 dpavlin 38 } 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 dpavlin 42 CHECK_ALLOCATION(ch=malloc(chunk_len));
454 dpavlin 38 }
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 dpavlin 42 CHECK_ALLOCATION(symbols_sym64 =
549     malloc(sh_size));
550    
551 dpavlin 38 len = fread(symbols_sym64, 1, sh_entsize *
552     n_entries, f);
553     } else {
554     if (symbols_sym32 != NULL)
555     free(symbols_sym32);
556    
557 dpavlin 42 CHECK_ALLOCATION(symbols_sym32 =
558     malloc(sh_size));
559    
560 dpavlin 38 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 dpavlin 42 CHECK_ALLOCATION(symbol_strings = malloc(sh_size + 1));
591 dpavlin 38
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