/[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 40 - (hide annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 21236 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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 40 * $Id: file_elf.c,v 1.2 2007/04/18 14:08:35 debug Exp $
29 dpavlin 38 *
30     * 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 84
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     };
63    
64    
65     /*
66     * file_load_elf():
67     *
68     * Loads an ELF image into the emulated memory. The entry point (read from
69     * the ELF header) and the initial value of the gp register (read from the
70     * ELF symbol table) are stored in the specified CPU's registers.
71     *
72     * This is pretty heavy stuff, but is needed because of the heaviness of
73     * ELF files. :-/ Hopefully it will be able to recognize most valid ELFs.
74     */
75     static void file_load_elf(struct machine *m, struct memory *mem,
76     char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp,
77     int *byte_order, uint64_t *tocp)
78     {
79     Elf32_Ehdr hdr32;
80     Elf64_Ehdr hdr64;
81     FILE *f;
82     uint64_t eentry;
83     int len, i, ok;
84     int elf64, encoding, eflags;
85     int etype, emachine;
86     int ephnum, ephentsize, eshnum, eshentsize;
87     off_t ephoff, eshoff;
88     Elf32_Phdr phdr32;
89     Elf64_Phdr phdr64;
90     Elf32_Shdr shdr32;
91     Elf64_Shdr shdr64;
92     Elf32_Sym sym32;
93     Elf64_Sym sym64;
94     int ofs;
95     int chunk_len = 1024, align_len;
96     char *symbol_strings = NULL; size_t symbol_length = 0;
97     char *s;
98     Elf32_Sym *symbols_sym32 = NULL; int n_symbols = 0;
99     Elf64_Sym *symbols_sym64 = NULL;
100    
101     f = fopen(filename, "r");
102     if (f == NULL) {
103     perror(filename);
104     exit(1);
105     }
106    
107     len = fread(&hdr32, 1, sizeof(Elf32_Ehdr), f);
108     if (len < (signed int)sizeof(Elf32_Ehdr)) {
109     fprintf(stderr, "%s: not an ELF file image\n", filename);
110     exit(1);
111     }
112    
113     if (memcmp(&hdr32.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0) {
114     fprintf(stderr, "%s: not an ELF file image\n", filename);
115     exit(1);
116     }
117    
118     switch (hdr32.e_ident[EI_CLASS]) {
119     case ELFCLASS32:
120     elf64 = 0;
121     break;
122     case ELFCLASS64:
123     elf64 = 1;
124     fseek(f, 0, SEEK_SET);
125     len = fread(&hdr64, 1, sizeof(Elf64_Ehdr), f);
126     if (len < (signed int)sizeof(Elf64_Ehdr)) {
127     fprintf(stderr, "%s: not an ELF64 file image\n",
128     filename);
129     exit(1);
130     }
131     break;
132     default:
133     fprintf(stderr, "%s: unknown ELF class '%i'\n",
134     filename, hdr32.e_ident[EI_CLASS]);
135     exit(1);
136     }
137    
138     encoding = hdr32.e_ident[EI_DATA];
139     if (encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) {
140     fprintf(stderr, "%s: unknown data encoding '%i'\n",
141     filename, hdr32.e_ident[EI_DATA]);
142     exit(1);
143     }
144    
145     if (elf64) {
146     unencode(etype, &hdr64.e_type, Elf64_Quarter);
147     unencode(eflags, &hdr64.e_flags, Elf64_Half);
148     unencode(emachine, &hdr64.e_machine, Elf64_Quarter);
149     unencode(eentry, &hdr64.e_entry, Elf64_Addr);
150     unencode(ephnum, &hdr64.e_phnum, Elf64_Quarter);
151     unencode(ephentsize, &hdr64.e_phentsize, Elf64_Quarter);
152     unencode(ephoff, &hdr64.e_phoff, Elf64_Off);
153     unencode(eshnum, &hdr64.e_shnum, Elf64_Quarter);
154     unencode(eshentsize, &hdr64.e_shentsize, Elf64_Quarter);
155     unencode(eshoff, &hdr64.e_shoff, Elf64_Off);
156     if (ephentsize != sizeof(Elf64_Phdr)) {
157     fprintf(stderr, "%s: incorrect phentsize? %i, should "
158     "be %i\nPerhaps this is a dynamically linked "
159     "binary (which isn't supported yet).\n", filename,
160     (int)ephentsize, (int)sizeof(Elf64_Phdr));
161     exit(1);
162     }
163     if (eshentsize != sizeof(Elf64_Shdr)) {
164     fprintf(stderr, "%s: incorrect shentsize? %i, should "
165     "be %i\nPerhaps this is a dynamically linked "
166     "binary (which isn't supported yet).\n", filename,
167     (int)eshentsize, (int)sizeof(Elf64_Shdr));
168     exit(1);
169     }
170     } else {
171     unencode(etype, &hdr32.e_type, Elf32_Half);
172     unencode(eflags, &hdr32.e_flags, Elf32_Word);
173     unencode(emachine, &hdr32.e_machine, Elf32_Half);
174     unencode(eentry, &hdr32.e_entry, Elf32_Addr);
175     unencode(ephnum, &hdr32.e_phnum, Elf32_Half);
176     unencode(ephentsize, &hdr32.e_phentsize, Elf32_Half);
177     unencode(ephoff, &hdr32.e_phoff, Elf32_Off);
178     unencode(eshnum, &hdr32.e_shnum, Elf32_Half);
179     unencode(eshentsize, &hdr32.e_shentsize, Elf32_Half);
180     unencode(eshoff, &hdr32.e_shoff, Elf32_Off);
181     if (ephentsize != sizeof(Elf32_Phdr)) {
182     fprintf(stderr, "%s: incorrect phentsize? %i, should "
183     "be %i\nPerhaps this is a dynamically linked "
184     "binary (which isn't supported yet).\n", filename,
185     (int)ephentsize, (int)sizeof(Elf32_Phdr));
186     exit(1);
187     }
188     if (eshentsize != sizeof(Elf32_Shdr)) {
189     fprintf(stderr, "%s: incorrect shentsize? %i, should "
190     "be %i\nPerhaps this is a dynamically linked "
191     "binary (which isn't supported yet).\n", filename,
192     (int)eshentsize, (int)sizeof(Elf32_Shdr));
193     exit(1);
194     }
195     }
196    
197     if ( etype != ET_EXEC ) {
198     fprintf(stderr, "%s is not an ELF Executable file, type = %i\n",
199     filename, etype);
200     exit(1);
201     }
202    
203     ok = 0;
204     switch (arch) {
205     case ARCH_ALPHA:
206     switch (emachine) {
207     case EM_ALPHA:
208     case -28634:
209     ok = 1;
210     }
211     break;
212     case ARCH_ARM:
213     switch (emachine) {
214     case EM_ARM:
215     ok = 1;
216     }
217     break;
218     case ARCH_AVR:
219     switch (emachine) {
220     case EM_AVR:
221     ok = 1;
222     }
223     break;
224     /* case ARCH_AVR32:
225     switch (emachine) {
226     case 6317:
227     ok = 1;
228     }
229     break;
230     case ARCH_HPPA:
231     switch (emachine) {
232     case EM_PARISC:
233     ok = 1;
234     }
235     break;
236     case ARCH_I960:
237     switch (emachine) {
238     case EM_960:
239     ok = 1;
240     }
241     break;
242     case ARCH_IA64:
243     switch (emachine) {
244     case EM_IA_64:
245     ok = 1;
246     }
247     break; */
248 dpavlin 40 /* case ARCH_M68K:
249 dpavlin 38 switch (emachine) {
250     case EM_68K:
251     ok = 1;
252     }
253 dpavlin 40 break; */
254 dpavlin 38 case ARCH_MIPS:
255     switch (emachine) {
256     case EM_MIPS:
257     case EM_MIPS_RS3_LE:
258     ok = 1;
259     }
260     break;
261     case ARCH_PPC:
262     switch (emachine) {
263     case EM_PPC:
264     case EM_PPC64:
265     ok = 1;
266     }
267     break;
268     case ARCH_SH:
269     switch (emachine) {
270     case EM_SH:
271     ok = 1;
272     }
273     break;
274     case ARCH_SPARC:
275     switch (emachine) {
276     case EM_SPARC:
277     case EM_SPARCV9:
278     ok = 1;
279     }
280     break;
281     /* case ARCH_X86:
282     switch (emachine) {
283     case EM_386:
284     case EM_486:
285     *tocp = 1;
286     ok = 1;
287     break;
288     case EM_AMD64:
289     *tocp = 2;
290     ok = 1;
291     break;
292     }
293     break; */
294     default:
295     fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n");
296     }
297     if (!ok) {
298     fprintf(stderr, "%s: this is a ", filename);
299     if (emachine >= 0 && emachine < N_ELF_MACHINE_TYPES)
300     fprintf(stderr, elf_machine_type[emachine]);
301     else
302     fprintf(stderr, "machine type '%i'", emachine);
303     fprintf(stderr, " ELF binary!\n");
304     exit(1);
305     }
306    
307     s = "entry point";
308     if (elf64 && arch == ARCH_PPC)
309     s = "function descriptor at";
310    
311     debug("ELF%i %s, %s 0x", elf64? 64 : 32,
312     encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s);
313    
314     if (elf64)
315     debug("%016"PRIx64"\n", (uint64_t) eentry);
316     else
317     debug("%08"PRIx32"\n", (uint32_t) eentry);
318    
319     /*
320     * SH64: 32-bit instruction encoding?
321     */
322     if (arch == ARCH_SH && (eentry & 1)) {
323     debug("SH64: 32-bit instruction encoding\n");
324     m->cpus[0]->cd.sh.compact = 0;
325     m->cpus[0]->cd.sh.cpu_type.bits = 64;
326     }
327    
328     /* Read the program headers: */
329    
330     for (i=0; i<ephnum; i++) {
331     int p_type;
332     uint64_t p_offset;
333     uint64_t p_vaddr;
334     uint64_t p_paddr;
335     uint64_t p_filesz;
336     uint64_t p_memsz;
337     int p_flags;
338     int p_align;
339    
340     fseek(f, ephoff + i * ephentsize, SEEK_SET);
341    
342     if (elf64) {
343     fread(&phdr64, 1, sizeof(Elf64_Phdr), f);
344     unencode(p_type, &phdr64.p_type, Elf64_Half);
345     unencode(p_flags, &phdr64.p_flags, Elf64_Half);
346     unencode(p_offset, &phdr64.p_offset, Elf64_Off);
347     unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr);
348     unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr);
349     unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword);
350     unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword);
351     unencode(p_align, &phdr64.p_align, Elf64_Xword);
352     } else {
353     fread(&phdr32, 1, sizeof(Elf32_Phdr), f);
354     unencode(p_type, &phdr32.p_type, Elf32_Word);
355     unencode(p_offset, &phdr32.p_offset, Elf32_Off);
356     unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr);
357     unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr);
358     unencode(p_filesz, &phdr32.p_filesz, Elf32_Word);
359     unencode(p_memsz, &phdr32.p_memsz, Elf32_Word);
360     unencode(p_flags, &phdr32.p_flags, Elf32_Word);
361     unencode(p_align, &phdr32.p_align, Elf32_Word);
362     }
363    
364     /*
365     * Hack for loading PPC kernels that are linked to high
366     * addresses. (This requires enabling of instruction and
367     * data virtual address translation.)
368     */
369     if (arch == ARCH_PPC) {
370     if ( (elf64 && (p_vaddr >> 60) != 0) ||
371     (!elf64 && (p_vaddr >> 28) != 0) )
372     m->cpus[m->bootstrap_cpu]->
373     cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR;
374     }
375    
376     if (p_memsz != 0 && (p_type == PT_LOAD ||
377     (p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) {
378     debug("chunk %i (", i);
379     if (p_type == PT_LOAD)
380     debug("load");
381     else
382     debug("0x%08"PRIx32, (uint32_t) p_type);
383    
384     debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset);
385    
386     if (elf64)
387     debug("%016"PRIx64, (uint64_t) p_vaddr);
388     else
389     debug("%08"PRIx32, (uint32_t) p_vaddr);
390    
391     debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz);
392    
393     if (p_vaddr != p_paddr) {
394     if (elf64)
395     debug("NOTE: vaddr (0x%"PRIx64") and "
396     "paddr (0x%"PRIx64") differ; using "
397     "vaddr\n", (uint64_t) p_vaddr,
398     (uint64_t) p_paddr);
399     else
400     debug("NOTE: vaddr (0x%08"PRIx32") and "
401     "paddr (0x%08"PRIx32") differ; usin"
402     "g vaddr\n", (uint32_t) p_vaddr,
403     (uint32_t)p_paddr);
404     }
405    
406     if (p_memsz < p_filesz) {
407     fprintf(stderr, "%s: memsz < filesz. TODO: how"
408     " to handle this? memsz=%016"PRIx64
409     " filesz=%016"PRIx64"\n", filename,
410     (uint64_t) p_memsz, (uint64_t) p_filesz);
411     exit(1);
412     }
413    
414     fseek(f, p_offset, SEEK_SET);
415     align_len = 1;
416     if ((p_vaddr & 0xf)==0) align_len = 0x10;
417     if ((p_vaddr & 0x3f)==0) align_len = 0x40;
418     if ((p_vaddr & 0xff)==0) align_len = 0x100;
419     if ((p_vaddr & 0xfff)==0) align_len = 0x1000;
420     if ((p_vaddr & 0x3fff)==0) align_len = 0x4000;
421     if ((p_vaddr & 0xffff)==0) align_len = 0x10000;
422     ofs = 0; len = chunk_len = align_len;
423     while (ofs < (int64_t)p_filesz && len==chunk_len) {
424     unsigned char *ch = malloc(chunk_len);
425     int i = 0;
426    
427     /* Switch to larger size, if possible: */
428     if (align_len < 0x10000 &&
429     ((p_vaddr + ofs) & 0xffff)==0) {
430     align_len = 0x10000;
431     len = chunk_len = align_len;
432     free(ch);
433     ch = malloc(chunk_len);
434     } else if (align_len < 0x1000 &&
435     ((p_vaddr + ofs) & 0xfff)==0) {
436     align_len = 0x1000;
437     len = chunk_len = align_len;
438     free(ch);
439     ch = malloc(chunk_len);
440     }
441    
442     if (ch == NULL) {
443     fprintf(stderr, "out of memory\n");
444     exit(1);
445     }
446    
447     len = fread(&ch[0], 1, chunk_len, f);
448     if (ofs + len > (int64_t)p_filesz)
449     len = p_filesz - ofs;
450    
451     while (i < len) {
452     size_t len_to_copy;
453     len_to_copy = (i + align_len) <= len?
454     align_len : len - i;
455     m->cpus[0]->memory_rw(m->cpus[0], mem,
456     p_vaddr + ofs, &ch[i], len_to_copy,
457     MEM_WRITE, NO_EXCEPTIONS);
458     ofs += align_len;
459     i += align_len;
460     }
461    
462     free(ch);
463     }
464     }
465     }
466    
467     /*
468     * Read the section headers to find the address of the _gp
469     * symbol (for MIPS):
470     */
471    
472     for (i=0; i<eshnum; i++) {
473     int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize;
474     uint64_t sh_addr, sh_size, sh_addralign;
475     off_t sh_offset;
476     int n_entries; /* for reading the symbol / string tables */
477    
478     /* debug("section header %i at %016"PRIx64"\n", i,
479     (uint64_t) eshoff+i*eshentsize); */
480    
481     fseek(f, eshoff + i * eshentsize, SEEK_SET);
482    
483     if (elf64) {
484     len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f);
485     if (len != sizeof(Elf64_Shdr)) {
486     fprintf(stderr, "couldn't read header\n");
487     exit(1);
488     }
489     unencode(sh_name, &shdr64.sh_name, Elf64_Half);
490     unencode(sh_type, &shdr64.sh_type, Elf64_Half);
491     unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword);
492     unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr);
493     unencode(sh_offset, &shdr64.sh_offset, Elf64_Off);
494     unencode(sh_size, &shdr64.sh_size, Elf64_Xword);
495     unencode(sh_link, &shdr64.sh_link, Elf64_Half);
496     unencode(sh_info, &shdr64.sh_info, Elf64_Half);
497     unencode(sh_addralign, &shdr64.sh_addralign,
498     Elf64_Xword);
499     unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword);
500     } else {
501     len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f);
502     if (len != sizeof(Elf32_Shdr)) {
503     fprintf(stderr, "couldn't read header\n");
504     exit(1);
505     }
506     unencode(sh_name, &shdr32.sh_name, Elf32_Word);
507     unencode(sh_type, &shdr32.sh_type, Elf32_Word);
508     unencode(sh_flags, &shdr32.sh_flags, Elf32_Word);
509     unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr);
510     unencode(sh_offset, &shdr32.sh_offset, Elf32_Off);
511     unencode(sh_size, &shdr32.sh_size, Elf32_Word);
512     unencode(sh_link, &shdr32.sh_link, Elf32_Word);
513     unencode(sh_info, &shdr32.sh_info, Elf32_Word);
514     unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word);
515     unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word);
516     }
517    
518     /* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx"
519     " sh_size=%06lx sh_entsize=%03lx\n",
520     (long)sh_name, (long)sh_type, (long)sh_flags,
521     (long)sh_size, (long)sh_entsize); */
522    
523     /* Perhaps it is bad to reuse sh_entsize like this? TODO */
524     if (elf64)
525     sh_entsize = sizeof(Elf64_Sym);
526     else
527     sh_entsize = sizeof(Elf32_Sym);
528    
529     if (sh_type == SHT_SYMTAB) {
530     size_t len;
531     n_entries = sh_size / sh_entsize;
532    
533     fseek(f, sh_offset, SEEK_SET);
534    
535     if (elf64) {
536     if (symbols_sym64 != NULL)
537     free(symbols_sym64);
538     symbols_sym64 = malloc(sh_size);
539     if (symbols_sym64 == NULL) {
540     fprintf(stderr, "out of memory\n");
541     exit(1);
542     }
543    
544     len = fread(symbols_sym64, 1, sh_entsize *
545     n_entries, f);
546     } else {
547     if (symbols_sym32 != NULL)
548     free(symbols_sym32);
549     symbols_sym32 = malloc(sh_size);
550     if (symbols_sym32 == NULL) {
551     fprintf(stderr, "out of memory\n");
552     exit(1);
553     }
554    
555     len = fread(symbols_sym32, 1,
556     sh_entsize * n_entries, f);
557     }
558    
559     if (len != sh_size) {
560     fprintf(stderr, "could not read symbols from "
561     "%s\n", filename);
562     exit(1);
563     }
564    
565     debug("%i symbol entries at 0x%"PRIx64"\n",
566     (int) n_entries, (uint64_t) sh_offset);
567    
568     n_symbols = n_entries;
569     }
570    
571     /*
572     * TODO: This is incorrect, there may be several strtab
573     * sections.
574     *
575     * For now, the simple/stupid guess that the largest string
576     * table is the one to use seems to be good enough.
577     */
578    
579     if (sh_type == SHT_STRTAB && sh_size > symbol_length) {
580     size_t len;
581    
582     if (symbol_strings != NULL)
583     free(symbol_strings);
584    
585     symbol_strings = malloc(sh_size + 1);
586     if (symbol_strings == NULL) {
587     fprintf(stderr, "out of memory\n");
588     exit(1);
589     }
590    
591     fseek(f, sh_offset, SEEK_SET);
592     len = fread(symbol_strings, 1, sh_size, f);
593     if (len != sh_size) {
594     fprintf(stderr, "could not read symbols from "
595     "%s\n", filename);
596     exit(1);
597     }
598    
599     debug("%i bytes of symbol strings at 0x%"PRIx64"\n",
600     (int) sh_size, (uint64_t) sh_offset);
601    
602     symbol_strings[sh_size] = '\0';
603     symbol_length = sh_size;
604     }
605     }
606    
607     fclose(f);
608    
609     /* Decode symbols: */
610     if (symbol_strings != NULL) {
611     for (i=0; i<n_symbols; i++) {
612     uint64_t st_name, addr, size;
613     int st_info;
614    
615     if (elf64) {
616     sym64 = symbols_sym64[i];
617     unencode(st_name, &sym64.st_name, Elf64_Half);
618     unencode(st_info, &sym64.st_info, Elf_Byte);
619     unencode(addr, &sym64.st_value, Elf64_Addr);
620     unencode(size, &sym64.st_size, Elf64_Xword);
621     } else {
622     sym32 = symbols_sym32[i];
623     unencode(st_name, &sym32.st_name, Elf32_Word);
624     unencode(st_info, &sym32.st_info, Elf_Byte);
625     unencode(addr, &sym32.st_value, Elf32_Word);
626     unencode(size, &sym32.st_size, Elf32_Word);
627     }
628    
629     /* debug("symbol info=0x%02x addr=0x%016"PRIx64
630     " (%i) '%s'\n", st_info, (uint64_t) addr,
631     st_name, symbol_strings + st_name); */
632    
633     if (size == 0)
634     size ++;
635    
636     if (addr != 0) /* && ((st_info >> 4) & 0xf)
637     >= STB_GLOBAL) */ {
638     /* debug("symbol info=0x%02x addr=0x%016"PRIx64
639     " '%s'\n", st_info, (uint64_t) addr,
640     symbol_strings + st_name); */
641     add_symbol_name(&m->symbol_context,
642     addr, size, symbol_strings + st_name,
643     0, -1);
644     }
645    
646     if (strcmp(symbol_strings + st_name, "_gp") == 0) {
647     debug("found _gp address: 0x");
648     if (elf64)
649     debug("%016"PRIx64"\n", (uint64_t)addr);
650     else
651     debug("%08"PRIx32"\n", (uint32_t)addr);
652     *gpp = addr;
653     }
654     }
655     }
656    
657     *entrypointp = eentry;
658    
659     if (encoding == ELFDATA2LSB)
660     *byte_order = EMUL_LITTLE_ENDIAN;
661     else
662     *byte_order = EMUL_BIG_ENDIAN;
663    
664     if (elf64 && arch == ARCH_PPC) {
665     /*
666     * Special case for 64-bit PPC ELFs:
667     *
668     * The ELF starting symbol points to a ".opd" section
669     * which contains a function descriptor:
670     *
671     * uint64_t start;
672     * uint64_t toc_base;
673     * uint64_t something_else; (?)
674     */
675     int res;
676     unsigned char b[sizeof(uint64_t)];
677     uint64_t toc_base;
678    
679     debug("PPC64: ");
680    
681     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
682     sizeof(b), MEM_READ, NO_EXCEPTIONS);
683     if (!res)
684     debug(" [WARNING: could not read memory?] ");
685    
686     /* PPC are always big-endian: */
687     *entrypointp = ((uint64_t)b[0] << 56) +
688     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
689     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
690     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
691     (uint64_t)b[7];
692    
693     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
694     b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
695     if (!res)
696     fatal(" [WARNING: could not read memory?] ");
697    
698     toc_base = ((uint64_t)b[0] << 56) +
699     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
700     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
701     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
702     (uint64_t)b[7];
703    
704     debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n",
705     (uint64_t) *entrypointp, (uint64_t) toc_base);
706     if (tocp != NULL)
707     *tocp = toc_base;
708     }
709    
710     n_executables_loaded ++;
711     }
712    

  ViewVC Help
Powered by ViewVC 1.1.26