/[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 38 - (hide annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 21228 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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     * $Id: file_elf.c,v 1.1 2007/04/10 16:33:44 debug Exp $
29     *
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     case ARCH_M68K:
249     switch (emachine) {
250     case EM_68K:
251     ok = 1;
252     }
253     break;
254     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