/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 20993 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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     if (elf64)
323     debug("%016"PRIx64"\n", (uint64_t) eentry);
324     else
325     debug("%08"PRIx32"\n", (uint32_t) eentry);
326    
327     /*
328     * SH64: 32-bit instruction encoding?
329     */
330     if (arch == ARCH_SH && (eentry & 1)) {
331 dpavlin 42 fatal("SH64: 32-bit instruction encoding: TODO\n");
332     /* m->cpus[0]->cd.sh.compact = 0; */
333 dpavlin 38 m->cpus[0]->cd.sh.cpu_type.bits = 64;
334 dpavlin 42 exit(1);
335 dpavlin 38 }
336    
337     /* Read the program headers: */
338    
339     for (i=0; i<ephnum; i++) {
340     int p_type;
341     uint64_t p_offset;
342     uint64_t p_vaddr;
343     uint64_t p_paddr;
344     uint64_t p_filesz;
345     uint64_t p_memsz;
346     int p_flags;
347     int p_align;
348    
349     fseek(f, ephoff + i * ephentsize, SEEK_SET);
350    
351     if (elf64) {
352     fread(&phdr64, 1, sizeof(Elf64_Phdr), f);
353     unencode(p_type, &phdr64.p_type, Elf64_Half);
354     unencode(p_flags, &phdr64.p_flags, Elf64_Half);
355     unencode(p_offset, &phdr64.p_offset, Elf64_Off);
356     unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr);
357     unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr);
358     unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword);
359     unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword);
360     unencode(p_align, &phdr64.p_align, Elf64_Xword);
361     } else {
362     fread(&phdr32, 1, sizeof(Elf32_Phdr), f);
363     unencode(p_type, &phdr32.p_type, Elf32_Word);
364     unencode(p_offset, &phdr32.p_offset, Elf32_Off);
365     unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr);
366     unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr);
367     unencode(p_filesz, &phdr32.p_filesz, Elf32_Word);
368     unencode(p_memsz, &phdr32.p_memsz, Elf32_Word);
369     unencode(p_flags, &phdr32.p_flags, Elf32_Word);
370     unencode(p_align, &phdr32.p_align, Elf32_Word);
371     }
372    
373     /*
374     * Hack for loading PPC kernels that are linked to high
375     * addresses. (This requires enabling of instruction and
376     * data virtual address translation.)
377     */
378     if (arch == ARCH_PPC) {
379     if ( (elf64 && (p_vaddr >> 60) != 0) ||
380     (!elf64 && (p_vaddr >> 28) != 0) )
381     m->cpus[m->bootstrap_cpu]->
382     cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR;
383     }
384    
385     if (p_memsz != 0 && (p_type == PT_LOAD ||
386     (p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) {
387     debug("chunk %i (", i);
388     if (p_type == PT_LOAD)
389     debug("load");
390     else
391     debug("0x%08"PRIx32, (uint32_t) p_type);
392    
393     debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset);
394    
395     if (elf64)
396     debug("%016"PRIx64, (uint64_t) p_vaddr);
397     else
398     debug("%08"PRIx32, (uint32_t) p_vaddr);
399    
400     debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz);
401    
402     if (p_vaddr != p_paddr) {
403     if (elf64)
404     debug("NOTE: vaddr (0x%"PRIx64") and "
405     "paddr (0x%"PRIx64") differ; using "
406     "vaddr\n", (uint64_t) p_vaddr,
407     (uint64_t) p_paddr);
408     else
409     debug("NOTE: vaddr (0x%08"PRIx32") and "
410     "paddr (0x%08"PRIx32") differ; usin"
411     "g vaddr\n", (uint32_t) p_vaddr,
412     (uint32_t)p_paddr);
413     }
414    
415     if (p_memsz < p_filesz) {
416     fprintf(stderr, "%s: memsz < filesz. TODO: how"
417     " to handle this? memsz=%016"PRIx64
418     " filesz=%016"PRIx64"\n", filename,
419     (uint64_t) p_memsz, (uint64_t) p_filesz);
420     exit(1);
421     }
422    
423     fseek(f, p_offset, SEEK_SET);
424     align_len = 1;
425     if ((p_vaddr & 0xf)==0) align_len = 0x10;
426     if ((p_vaddr & 0x3f)==0) align_len = 0x40;
427     if ((p_vaddr & 0xff)==0) align_len = 0x100;
428     if ((p_vaddr & 0xfff)==0) align_len = 0x1000;
429     if ((p_vaddr & 0x3fff)==0) align_len = 0x4000;
430     if ((p_vaddr & 0xffff)==0) align_len = 0x10000;
431     ofs = 0; len = chunk_len = align_len;
432     while (ofs < (int64_t)p_filesz && len==chunk_len) {
433 dpavlin 42 unsigned char *ch;
434 dpavlin 38 int i = 0;
435    
436 dpavlin 42 CHECK_ALLOCATION(ch = malloc(chunk_len));
437    
438 dpavlin 38 /* Switch to larger size, if possible: */
439     if (align_len < 0x10000 &&
440     ((p_vaddr + ofs) & 0xffff)==0) {
441     align_len = 0x10000;
442     len = chunk_len = align_len;
443     free(ch);
444 dpavlin 42 CHECK_ALLOCATION(ch=malloc(chunk_len));
445 dpavlin 38 } else if (align_len < 0x1000 &&
446     ((p_vaddr + ofs) & 0xfff)==0) {
447     align_len = 0x1000;
448     len = chunk_len = align_len;
449     free(ch);
450 dpavlin 42 CHECK_ALLOCATION(ch=malloc(chunk_len));
451 dpavlin 38 }
452    
453     len = fread(&ch[0], 1, chunk_len, f);
454     if (ofs + len > (int64_t)p_filesz)
455     len = p_filesz - ofs;
456    
457     while (i < len) {
458     size_t len_to_copy;
459     len_to_copy = (i + align_len) <= len?
460     align_len : len - i;
461     m->cpus[0]->memory_rw(m->cpus[0], mem,
462     p_vaddr + ofs, &ch[i], len_to_copy,
463     MEM_WRITE, NO_EXCEPTIONS);
464     ofs += align_len;
465     i += align_len;
466     }
467    
468     free(ch);
469     }
470     }
471     }
472    
473     /*
474     * Read the section headers to find the address of the _gp
475     * symbol (for MIPS):
476     */
477    
478     for (i=0; i<eshnum; i++) {
479     int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize;
480     uint64_t sh_addr, sh_size, sh_addralign;
481     off_t sh_offset;
482     int n_entries; /* for reading the symbol / string tables */
483    
484     /* debug("section header %i at %016"PRIx64"\n", i,
485     (uint64_t) eshoff+i*eshentsize); */
486    
487     fseek(f, eshoff + i * eshentsize, SEEK_SET);
488    
489     if (elf64) {
490     len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f);
491     if (len != sizeof(Elf64_Shdr)) {
492     fprintf(stderr, "couldn't read header\n");
493     exit(1);
494     }
495     unencode(sh_name, &shdr64.sh_name, Elf64_Half);
496     unencode(sh_type, &shdr64.sh_type, Elf64_Half);
497     unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword);
498     unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr);
499     unencode(sh_offset, &shdr64.sh_offset, Elf64_Off);
500     unencode(sh_size, &shdr64.sh_size, Elf64_Xword);
501     unencode(sh_link, &shdr64.sh_link, Elf64_Half);
502     unencode(sh_info, &shdr64.sh_info, Elf64_Half);
503     unencode(sh_addralign, &shdr64.sh_addralign,
504     Elf64_Xword);
505     unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword);
506     } else {
507     len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f);
508     if (len != sizeof(Elf32_Shdr)) {
509     fprintf(stderr, "couldn't read header\n");
510     exit(1);
511     }
512     unencode(sh_name, &shdr32.sh_name, Elf32_Word);
513     unencode(sh_type, &shdr32.sh_type, Elf32_Word);
514     unencode(sh_flags, &shdr32.sh_flags, Elf32_Word);
515     unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr);
516     unencode(sh_offset, &shdr32.sh_offset, Elf32_Off);
517     unencode(sh_size, &shdr32.sh_size, Elf32_Word);
518     unencode(sh_link, &shdr32.sh_link, Elf32_Word);
519     unencode(sh_info, &shdr32.sh_info, Elf32_Word);
520     unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word);
521     unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word);
522     }
523    
524     /* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx"
525     " sh_size=%06lx sh_entsize=%03lx\n",
526     (long)sh_name, (long)sh_type, (long)sh_flags,
527     (long)sh_size, (long)sh_entsize); */
528    
529     /* Perhaps it is bad to reuse sh_entsize like this? TODO */
530     if (elf64)
531     sh_entsize = sizeof(Elf64_Sym);
532     else
533     sh_entsize = sizeof(Elf32_Sym);
534    
535     if (sh_type == SHT_SYMTAB) {
536     size_t len;
537     n_entries = sh_size / sh_entsize;
538    
539     fseek(f, sh_offset, SEEK_SET);
540    
541     if (elf64) {
542     if (symbols_sym64 != NULL)
543     free(symbols_sym64);
544    
545 dpavlin 42 CHECK_ALLOCATION(symbols_sym64 =
546     malloc(sh_size));
547    
548 dpavlin 38 len = fread(symbols_sym64, 1, sh_entsize *
549     n_entries, f);
550     } else {
551     if (symbols_sym32 != NULL)
552     free(symbols_sym32);
553    
554 dpavlin 42 CHECK_ALLOCATION(symbols_sym32 =
555     malloc(sh_size));
556    
557 dpavlin 38 len = fread(symbols_sym32, 1,
558     sh_entsize * n_entries, f);
559     }
560    
561     if (len != sh_size) {
562     fprintf(stderr, "could not read symbols from "
563     "%s\n", filename);
564     exit(1);
565     }
566    
567     debug("%i symbol entries at 0x%"PRIx64"\n",
568     (int) n_entries, (uint64_t) sh_offset);
569    
570     n_symbols = n_entries;
571     }
572    
573     /*
574     * TODO: This is incorrect, there may be several strtab
575     * sections.
576     *
577     * For now, the simple/stupid guess that the largest string
578     * table is the one to use seems to be good enough.
579     */
580    
581     if (sh_type == SHT_STRTAB && sh_size > symbol_length) {
582     size_t len;
583    
584     if (symbol_strings != NULL)
585     free(symbol_strings);
586    
587 dpavlin 42 CHECK_ALLOCATION(symbol_strings = malloc(sh_size + 1));
588 dpavlin 38
589     fseek(f, sh_offset, SEEK_SET);
590     len = fread(symbol_strings, 1, sh_size, f);
591     if (len != sh_size) {
592     fprintf(stderr, "could not read symbols from "
593     "%s\n", filename);
594     exit(1);
595     }
596    
597     debug("%i bytes of symbol strings at 0x%"PRIx64"\n",
598     (int) sh_size, (uint64_t) sh_offset);
599    
600     symbol_strings[sh_size] = '\0';
601     symbol_length = sh_size;
602     }
603     }
604    
605     fclose(f);
606    
607     /* Decode symbols: */
608     if (symbol_strings != NULL) {
609     for (i=0; i<n_symbols; i++) {
610     uint64_t st_name, addr, size;
611     int st_info;
612    
613     if (elf64) {
614     sym64 = symbols_sym64[i];
615     unencode(st_name, &sym64.st_name, Elf64_Half);
616     unencode(st_info, &sym64.st_info, Elf_Byte);
617     unencode(addr, &sym64.st_value, Elf64_Addr);
618     unencode(size, &sym64.st_size, Elf64_Xword);
619     } else {
620     sym32 = symbols_sym32[i];
621     unencode(st_name, &sym32.st_name, Elf32_Word);
622     unencode(st_info, &sym32.st_info, Elf_Byte);
623     unencode(addr, &sym32.st_value, Elf32_Word);
624     unencode(size, &sym32.st_size, Elf32_Word);
625     }
626    
627     /* debug("symbol info=0x%02x addr=0x%016"PRIx64
628     " (%i) '%s'\n", st_info, (uint64_t) addr,
629     st_name, symbol_strings + st_name); */
630    
631     if (size == 0)
632     size ++;
633    
634     if (addr != 0) /* && ((st_info >> 4) & 0xf)
635     >= STB_GLOBAL) */ {
636     /* debug("symbol info=0x%02x addr=0x%016"PRIx64
637     " '%s'\n", st_info, (uint64_t) addr,
638     symbol_strings + st_name); */
639     add_symbol_name(&m->symbol_context,
640     addr, size, symbol_strings + st_name,
641     0, -1);
642     }
643    
644     if (strcmp(symbol_strings + st_name, "_gp") == 0) {
645     debug("found _gp address: 0x");
646     if (elf64)
647     debug("%016"PRIx64"\n", (uint64_t)addr);
648     else
649     debug("%08"PRIx32"\n", (uint32_t)addr);
650     *gpp = addr;
651     }
652     }
653     }
654    
655     *entrypointp = eentry;
656    
657     if (encoding == ELFDATA2LSB)
658     *byte_order = EMUL_LITTLE_ENDIAN;
659     else
660     *byte_order = EMUL_BIG_ENDIAN;
661    
662     if (elf64 && arch == ARCH_PPC) {
663     /*
664     * Special case for 64-bit PPC ELFs:
665     *
666     * The ELF starting symbol points to a ".opd" section
667     * which contains a function descriptor:
668     *
669     * uint64_t start;
670     * uint64_t toc_base;
671     * uint64_t something_else; (?)
672     */
673     int res;
674     unsigned char b[sizeof(uint64_t)];
675     uint64_t toc_base;
676    
677     debug("PPC64: ");
678    
679     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
680     sizeof(b), MEM_READ, NO_EXCEPTIONS);
681     if (!res)
682     debug(" [WARNING: could not read memory?] ");
683    
684     /* PPC are always big-endian: */
685     *entrypointp = ((uint64_t)b[0] << 56) +
686     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
687     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
688     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
689     (uint64_t)b[7];
690    
691     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
692     b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
693     if (!res)
694     fatal(" [WARNING: could not read memory?] ");
695    
696     toc_base = ((uint64_t)b[0] << 56) +
697     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
698     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
699     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
700     (uint64_t)b[7];
701    
702     debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n",
703     (uint64_t) *entrypointp, (uint64_t) toc_base);
704     if (tocp != NULL)
705     *tocp = toc_base;
706     }
707    
708     n_executables_loaded ++;
709     }
710    

  ViewVC Help
Powered by ViewVC 1.1.26