/[gxemul]/trunk/src/file.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.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 47276 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 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 10 * $Id: file.c,v 1.99 2005/06/26 09:21:28 debug Exp $
29 dpavlin 2 *
30     * This file contains functions which load executable images into (emulated)
31     * memory. File formats recognized so far:
32     *
33     * ELF 32-bit and 64-bit ELFs
34     * a.out old format used by OpenBSD 2.x pmax kernels
35     * ecoff old format used by Ultrix, Windows NT, etc
36     * srec Motorola SREC format
37     * raw raw binaries, "address:[skiplen:[entrypoint:]]filename"
38     *
39     * If a file is not of one of the above mentioned formats, it is assumed
40     * to be symbol data generated by 'nm' or 'nm -S'.
41     */
42    
43     #include <stdio.h>
44     #include <stdlib.h>
45     #include <string.h>
46     #include <sys/types.h>
47    
48     #include "cpu.h"
49     #include "exec_aout.h"
50     #include "exec_ecoff.h"
51     #include "exec_elf.h"
52     #include "machine.h"
53     #include "memory.h"
54     #include "misc.h"
55     #include "symbol.h"
56    
57    
58     /* ELF machine types as strings: (same as exec_elf.h) */
59 dpavlin 4 #define N_ELF_MACHINE_TYPES 64
60 dpavlin 2 static char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
61     "NONE", "M32", "SPARC", "386", /* 0..3 */
62     "68K", "88K", "486", "860", /* 4..7 */
63     "MIPS", "S370", "MIPS_RS3_LE", "RS6000", /* 8..11 */
64     "unknown12", "unknown13", "unknown14", "PARISC", /* 12..15 */
65     "NCUBE", "VPP500", "SPARC32PLUS", "960", /* 16..19 */
66     "PPC", "PPC64", "unknown22", "unknown23", /* 20..23 */
67     "unknown24", "unknown25", "unknown26", "unknown27", /* 24..27 */
68     "unknown28", "unknown29", "unknown30", "unknown31", /* 28..31 */
69     "unknown32", "unknown33", "unknown34", "unknown35", /* 32..35 */
70     "V800", "FR20", "RH32", "RCE", /* 36..39 */
71     "ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */
72     "TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */
73     "H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */
74 dpavlin 4 "COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */
75     "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */
76     "unknown60", "unknown61", "AMD64", "unknown63" /* 60..63 */
77 dpavlin 2 };
78    
79    
80     /*
81     * This should be increased by every routine here that actually loads an
82     * executable file into memory. (For example, loading a symbol file should
83     * NOT increase this.)
84     */
85     static int n_executables_loaded = 0;
86    
87    
88     struct aout_symbol {
89     uint32_t strindex;
90     uint32_t type;
91     uint32_t addr;
92     };
93    
94     /* Special symbol format used by Microsoft-ish COFF files: */
95     struct ms_sym {
96     unsigned char name[8];
97     unsigned char value[4];
98     unsigned char section[2];
99     unsigned char type[2];
100     unsigned char storage_class;
101     unsigned char n_aux_syms;
102     };
103    
104    
105     #define unencode(var,dataptr,typ) { \
106     int Wi; unsigned char Wb; \
107     unsigned char *Wp = (unsigned char *) dataptr; \
108     int Wlen = sizeof(typ); \
109     var = 0; \
110     for (Wi=0; Wi<Wlen; Wi++) { \
111     if (encoding == ELFDATA2LSB) \
112     Wb = Wp[Wlen-1 - Wi]; \
113     else \
114     Wb = Wp[Wi]; \
115     if (Wi == 0 && (Wb & 0x80)) { \
116     var --; /* set var to -1 :-) */ \
117     var <<= 8; \
118     } \
119     var |= Wb; \
120     if (Wi < Wlen-1) \
121     var <<= 8; \
122     } \
123     }
124    
125    
126 dpavlin 6 #define AOUT_FLAG_DECOSF1 1
127     #define AOUT_FLAG_FROM_BEGINNING 2
128 dpavlin 2 /*
129     * file_load_aout():
130     *
131     * Loads an a.out binary image into the emulated memory. The entry point
132     * (read from the a.out header) is stored in the specified CPU's registers.
133     *
134     * TODO: This has to be rewritten / corrected to support multiple a.out
135     * formats, where text/data are aligned differently.
136     */
137     static void file_load_aout(struct machine *m, struct memory *mem,
138 dpavlin 6 char *filename, int flags,
139 dpavlin 2 uint64_t *entrypointp, int arch, int *byte_orderp)
140     {
141     struct exec aout_header;
142     FILE *f;
143     int len;
144     int encoding = ELFDATA2LSB;
145     uint32_t entry, datasize, textsize;
146     int32_t symbsize = 0;
147     uint32_t vaddr, total_len;
148     unsigned char buf[4096];
149     unsigned char *syms;
150    
151     f = fopen(filename, "r");
152     if (f == NULL) {
153     perror(filename);
154     exit(1);
155     }
156    
157 dpavlin 6 if (flags & AOUT_FLAG_DECOSF1) {
158 dpavlin 2 fread(&buf, 1, 32, f);
159     vaddr = buf[16] + (buf[17] << 8) +
160     (buf[18] << 16) + (buf[19] << 24);
161     entry = buf[20] + (buf[21] << 8) +
162     (buf[22] << 16) + (buf[23] << 24);
163     debug("OSF1 a.out, load address 0x%08lx, "
164     "entry point 0x%08x\n", (long)vaddr, (long)entry);
165     symbsize = 0;
166     fseek(f, 0, SEEK_END);
167     /* This is of course wrong, but should work anyway: */
168 dpavlin 10 textsize = ftello(f) - 512;
169 dpavlin 2 datasize = 0;
170     fseek(f, 512, SEEK_SET);
171     } else {
172     len = fread(&aout_header, 1, sizeof(aout_header), f);
173     if (len != sizeof(aout_header)) {
174     fprintf(stderr, "%s: not a complete a.out image\n",
175     filename);
176     exit(1);
177     }
178    
179     unencode(entry, &aout_header.a_entry, uint32_t);
180     vaddr = entry;
181     debug("a.out, entry point 0x%08lx\n", (long)entry);
182    
183     unencode(textsize, &aout_header.a_text, uint32_t);
184     unencode(datasize, &aout_header.a_data, uint32_t);
185     debug("text + data = %i + %i bytes\n", textsize, datasize);
186    
187     unencode(symbsize, &aout_header.a_syms, uint32_t);
188     }
189    
190 dpavlin 6 if (flags & AOUT_FLAG_FROM_BEGINNING) {
191     fseek(f, 0, SEEK_SET);
192     vaddr &= ~0xfff;
193     }
194    
195 dpavlin 2 /* Load text and data: */
196     total_len = textsize + datasize;
197     while (total_len != 0) {
198     len = total_len > sizeof(buf) ? sizeof(buf) : total_len;
199     len = fread(buf, 1, len, f);
200    
201     /* printf("fread len=%i vaddr=%x buf[0..]=%02x %02x %02x\n",
202     len, (int)vaddr, buf[0], buf[1], buf[2]); */
203    
204     if (len > 0)
205     m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr,
206     &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);
207     else {
208 dpavlin 6 if (flags & AOUT_FLAG_DECOSF1)
209 dpavlin 2 break;
210     else {
211     fprintf(stderr, "could not read from %s\n",
212     filename);
213     exit(1);
214     }
215     }
216    
217     vaddr += len;
218     total_len -= len;
219     }
220    
221     if (symbsize != 0) {
222     struct aout_symbol *aout_symbol_ptr;
223     int i, n_symbols;
224     uint32_t type, addr, str_index;
225     uint32_t strings_len;
226     char *string_symbols;
227     off_t oldpos;
228    
229 dpavlin 10 debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftello(f));
230 dpavlin 2 syms = malloc(symbsize);
231     if (syms == NULL) {
232     fprintf(stderr, "out of memory\n");
233     exit(1);
234     }
235     len = fread(syms, 1, symbsize, f);
236     if (len != symbsize) {
237     fprintf(stderr, "error reading symbols from %s\n",
238     filename);
239     exit(1);
240     }
241    
242 dpavlin 10 oldpos = ftello(f);
243 dpavlin 2 fseek(f, 0, SEEK_END);
244 dpavlin 10 strings_len = ftello(f) - oldpos;
245 dpavlin 2 fseek(f, oldpos, SEEK_SET);
246 dpavlin 10 debug("strings: %i bytes @ 0x%x\n", strings_len,(int)ftello(f));
247 dpavlin 2 string_symbols = malloc(strings_len);
248     if (string_symbols == NULL) {
249     fprintf(stderr, "out of memory\n");
250     exit(1);
251     }
252     fread(string_symbols, 1, strings_len, f);
253    
254     aout_symbol_ptr = (struct aout_symbol *) syms;
255     n_symbols = symbsize / sizeof(struct aout_symbol);
256     i = 0;
257     while (i < n_symbols) {
258     unencode(str_index, &aout_symbol_ptr[i].strindex,
259     uint32_t);
260     unencode(type, &aout_symbol_ptr[i].type, uint32_t);
261     unencode(addr, &aout_symbol_ptr[i].addr, uint32_t);
262    
263     /* debug("symbol type 0x%04x @ 0x%08x: %s\n",
264     type, addr, string_symbols + str_index); */
265    
266     if (type != 0 && addr != 0)
267     add_symbol_name(&m->symbol_context,
268     addr, 0, string_symbols + str_index, 0);
269     i++;
270     }
271    
272     free(string_symbols);
273     free(syms);
274     }
275    
276     fclose(f);
277    
278 dpavlin 6 *entrypointp = (int32_t)entry;
279 dpavlin 2
280     if (encoding == ELFDATA2LSB)
281     *byte_orderp = EMUL_LITTLE_ENDIAN;
282     else
283     *byte_orderp = EMUL_BIG_ENDIAN;
284    
285     n_executables_loaded ++;
286     }
287    
288    
289     /*
290     * file_load_ecoff():
291     *
292     * Loads an ecoff binary image into the emulated memory. The entry point
293     * (read from the ecoff header) is stored in the specified CPU's registers.
294     */
295     static void file_load_ecoff(struct machine *m, struct memory *mem,
296     char *filename, uint64_t *entrypointp,
297     int arch, uint64_t *gpp, int *byte_orderp)
298     {
299     struct ecoff_exechdr exechdr;
300     int f_magic, f_nscns, f_nsyms;
301     int a_magic;
302     off_t f_symptr, a_tsize, a_dsize, a_bsize;
303     uint64_t a_entry, a_tstart, a_dstart, a_bstart, a_gp, end_addr=0;
304     char *format_name;
305     struct ecoff_scnhdr scnhdr;
306     FILE *f;
307     int len, secn, total_len, chunk_size;
308     int encoding = ELFDATA2LSB; /* Assume little-endian. See below */
309     int program_byte_order = -1;
310     unsigned char buf[8192];
311    
312     f = fopen(filename, "r");
313     if (f == NULL) {
314     perror(filename);
315     exit(1);
316     }
317    
318     len = fread(&exechdr, 1, sizeof(exechdr), f);
319     if (len != sizeof(exechdr)) {
320     fprintf(stderr, " not a complete ecoff image\n");
321     exit(1);
322     }
323    
324     /*
325     * The following code looks a bit ugly, but it should work. The ECOFF
326     * 16-bit magic value seems to be stored in MSB byte order for
327     * big-endian binaries, and LSB byte order for little-endian binaries.
328     *
329     * The unencode() assumes little-endianness by default.
330     */
331     unencode(f_magic, &exechdr.f.f_magic, uint16_t);
332     switch (f_magic) {
333     case ((ECOFF_MAGIC_MIPSEB & 0xff) << 8) +
334     ((ECOFF_MAGIC_MIPSEB >> 8) & 0xff):
335     format_name = "MIPS1 BE";
336     encoding = ELFDATA2MSB;
337     break;
338     case ECOFF_MAGIC_MIPSEB:
339     /* NOTE: Big-endian header, little-endian code! */
340     format_name = "MIPS1 BE-LE";
341     encoding = ELFDATA2MSB;
342     program_byte_order = ELFDATA2LSB;
343     break;
344     case ECOFF_MAGIC_MIPSEL:
345     format_name = "MIPS1 LE";
346     encoding = ELFDATA2LSB;
347     break;
348     case ((ECOFF_MAGIC_MIPSEB2 & 0xff) << 8) +
349     ((ECOFF_MAGIC_MIPSEB2 >> 8) & 0xff):
350     format_name = "MIPS2 BE";
351     encoding = ELFDATA2MSB;
352     break;
353     case ECOFF_MAGIC_MIPSEL2:
354     format_name = "MIPS2 LE";
355     encoding = ELFDATA2LSB;
356     break;
357     case ((ECOFF_MAGIC_MIPSEB3 & 0xff) << 8) +
358     ((ECOFF_MAGIC_MIPSEB3 >> 8) & 0xff):
359     format_name = "MIPS3 BE";
360     encoding = ELFDATA2MSB;
361     break;
362     case ECOFF_MAGIC_MIPSEL3:
363     format_name = "MIPS3 LE";
364     encoding = ELFDATA2LSB;
365     break;
366     default:
367     fprintf(stderr, "%s: unimplemented ECOFF format, magic = "
368     "0x%04x\n", filename, (int)f_magic);
369     exit(1);
370     }
371    
372     /* Read various header information: */
373     unencode(f_nscns, &exechdr.f.f_nscns, uint16_t);
374     unencode(f_symptr, &exechdr.f.f_symptr, uint32_t);
375     unencode(f_nsyms, &exechdr.f.f_nsyms, uint32_t);
376     debug("ECOFF, %s, %i sections, %i symbols @ 0x%lx\n",
377     format_name, f_nscns, f_nsyms, (long)f_symptr);
378    
379     unencode(a_magic, &exechdr.a.magic, uint16_t);
380     unencode(a_tsize, &exechdr.a.tsize, uint32_t);
381     unencode(a_dsize, &exechdr.a.dsize, uint32_t);
382     unencode(a_bsize, &exechdr.a.bsize, uint32_t);
383     debug("magic 0x%04x, tsize 0x%x, dsize 0x%x, bsize 0x%x\n",
384     a_magic, (int)a_tsize, (int)a_dsize, (int)a_bsize);
385    
386     unencode(a_tstart, &exechdr.a.text_start, uint32_t);
387     unencode(a_dstart, &exechdr.a.data_start, uint32_t);
388     unencode(a_bstart, &exechdr.a.bss_start, uint32_t);
389     debug("text @ 0x%08x, data @ 0x%08x, bss @ 0x%08x\n",
390     (int)a_tstart, (int)a_dstart, (int)a_bstart);
391    
392     unencode(a_entry, &exechdr.a.entry, uint32_t);
393     unencode(a_gp, &exechdr.a.gp_value, uint32_t);
394     debug("entrypoint 0x%08x, gp = 0x%08x\n",
395     (int)a_entry, (int)a_gp);
396    
397     /*
398     * Special hack for a MACH/pmax kernel, I don't know how applicable
399     * this is for other files:
400     * there are no sections (!), and a_magic = 0x0108 instead of
401     * 0x0107 as it is on most other (E)COFF files I've seen.
402     *
403     * Then load everything after the header to the text start address.
404     */
405     if (f_nscns == 0 && a_magic == 0x108) {
406     uint64_t where = a_tstart;
407     total_len = 0;
408     fseek(f, 0x50, SEEK_SET);
409     while (!feof(f)) {
410     chunk_size = 256;
411     len = fread(buf, 1, chunk_size, f);
412    
413     if (len > 0)
414     m->cpus[0]->memory_rw(m->cpus[0], mem, where,
415     &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);
416     where += len;
417     total_len += len;
418     }
419     debug("MACH/pmax hack (!), read 0x%x bytes\n", total_len);
420     }
421    
422     /* Go through all the section headers: */
423     for (secn=0; secn<f_nscns; secn++) {
424     off_t s_scnptr, s_relptr, s_lnnoptr, oldpos;
425     int s_nreloc, s_nlnno, s_flags;
426     int s_size;
427     unsigned int i;
428     uint64_t s_paddr, s_vaddr;
429    
430     /* Read a section header: */
431     len = fread(&scnhdr, 1, sizeof(scnhdr), f);
432     if (len != sizeof(scnhdr)) {
433     fprintf(stderr, "%s: incomplete section "
434     "header %i\n", filename, secn);
435     exit(1);
436     }
437    
438     /* Show the section name: */
439     debug("section ");
440     for (i=0; i<sizeof(scnhdr.s_name); i++)
441     if (scnhdr.s_name[i] >= 32 && scnhdr.s_name[i] < 127)
442     debug("%c", scnhdr.s_name[i]);
443     else
444     break;
445     debug(" (");
446    
447     unencode(s_paddr, &scnhdr.s_paddr, uint32_t);
448     unencode(s_vaddr, &scnhdr.s_vaddr, uint32_t);
449     unencode(s_size, &scnhdr.s_size, uint32_t);
450     unencode(s_scnptr, &scnhdr.s_scnptr, uint32_t);
451     unencode(s_relptr, &scnhdr.s_relptr, uint32_t);
452     unencode(s_lnnoptr, &scnhdr.s_lnnoptr, uint32_t);
453     unencode(s_nreloc, &scnhdr.s_nreloc, uint16_t);
454     unencode(s_nlnno, &scnhdr.s_nlnno, uint16_t);
455     unencode(s_flags, &scnhdr.s_flags, uint32_t);
456    
457     debug("0x%x @ 0x%08x, offset 0x%lx, flags 0x%x)\n",
458     (int)s_size, (int)s_vaddr, (long)s_scnptr, (int)s_flags);
459    
460     end_addr = s_vaddr + s_size;
461    
462     if (s_relptr != 0) {
463     /*
464     * TODO: Read this url, or similar:
465     * http://www.iecc.com/linker/linker07.html
466     */
467     fprintf(stderr, "%s: relocatable code/data in "
468     "section nr %i: not yet implemented\n",
469     filename, secn);
470     exit(1);
471     }
472    
473     /* Loadable? Then load the section: */
474     if (s_scnptr != 0 && s_size != 0 &&
475     s_vaddr != 0 && !(s_flags & 0x02)) {
476     /* Remember the current file offset: */
477 dpavlin 10 oldpos = ftello(f);
478 dpavlin 2
479     /* Load the section into emulated memory: */
480     fseek(f, s_scnptr, SEEK_SET);
481     total_len = 0;
482     chunk_size = 1;
483     if ((s_vaddr & 0xf) == 0) chunk_size = 0x10;
484     if ((s_vaddr & 0xff) == 0) chunk_size = 0x100;
485     if ((s_vaddr & 0xfff) == 0) chunk_size = 0x1000;
486     while (total_len < s_size) {
487     len = chunk_size;
488     if (total_len + len > s_size)
489     len = s_size - total_len;
490     len = fread(buf, 1, chunk_size, f);
491     if (len == 0) {
492     debug("!!! total_len = %i, "
493     "chunk_size = %i, len = %i\n",
494     total_len, chunk_size, len);
495     break;
496     }
497    
498     m->cpus[0]->memory_rw(m->cpus[0], mem, s_vaddr,
499     &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);
500     s_vaddr += len;
501     total_len += len;
502     }
503    
504     /* Return to position inside the section headers: */
505     fseek(f, oldpos, SEEK_SET);
506     }
507     }
508    
509     if (f_symptr != 0 && f_nsyms != 0) {
510     struct ecoff_symhdr symhdr;
511     int sym_magic, iextMax, issExtMax, issMax, crfd;
512     off_t cbRfdOffset, cbExtOffset, cbSsExtOffset, cbSsOffset;
513     char *symbol_data;
514     struct ecoff_extsym *extsyms;
515     int nsymbols, sym_nr;
516    
517     fseek(f, f_symptr, SEEK_SET);
518    
519     len = fread(&symhdr, 1, sizeof(symhdr), f);
520     if (len != sizeof(symhdr)) {
521     fprintf(stderr, "%s: not a complete "
522     "ecoff image: symhdr broken\n", filename);
523     exit(1);
524     }
525    
526     unencode(sym_magic, &symhdr.magic, uint16_t);
527     unencode(crfd, &symhdr.crfd, uint32_t);
528     unencode(cbRfdOffset, &symhdr.cbRfdOffset, uint32_t);
529     unencode(issMax, &symhdr.issMax, uint32_t);
530     unencode(cbSsOffset, &symhdr.cbSsOffset, uint32_t);
531     unencode(issExtMax, &symhdr.issExtMax, uint32_t);
532     unencode(cbSsExtOffset, &symhdr.cbSsExtOffset, uint32_t);
533     unencode(iextMax, &symhdr.iextMax, uint32_t);
534     unencode(cbExtOffset, &symhdr.cbExtOffset, uint32_t);
535    
536     if (sym_magic != MIPS_MAGIC_SYM) {
537     unsigned char *ms_sym_buf;
538     struct ms_sym *sym;
539     int n_real_symbols = 0;
540    
541     debug("bad symbol magic, assuming Microsoft format: ");
542    
543     /*
544     * See http://www.lisoleg.net/lisoleg/elfandlib/
545     * Microsoft%20Portable%20Executable%20COFF%20For
546     * mat%20Specification.txt
547     * for more details.
548     */
549     ms_sym_buf = malloc(sizeof(struct ms_sym) * f_nsyms);
550     if (ms_sym_buf == NULL) {
551     fprintf(stderr, "out of memory\n");
552     exit(1);
553     }
554     fseek(f, f_symptr, SEEK_SET);
555     len = fread(ms_sym_buf, 1,
556     sizeof(struct ms_sym) * f_nsyms, f);
557     sym = (struct ms_sym *) ms_sym_buf;
558     for (sym_nr=0; sym_nr<f_nsyms; sym_nr++) {
559     char name[300];
560     uint32_t v, t, altname;
561     /* debug("sym %5i: '", sym_nr);
562     for (i=0; i<8 && sym->name[i]; i++)
563     debug("%c", sym->name[i]); */
564     v = sym->value[0] + (sym->value[1] << 8)
565     + (sym->value[2] << 16)
566     + (sym->value[3] << 24);
567     altname = sym->name[4] + (sym->name[5] << 8)
568     + (sym->name[6] << 16)
569     + (sym->name[3] << 24);
570     t = (sym->type[1] << 8) + sym->type[0];
571     /* TODO: big endian COFF? */
572     /* debug("' value=0x%x type=0x%04x", v, t); */
573    
574     if (t == 0x20 && sym->name[0]) {
575     memcpy(name, sym->name, 8);
576     name[8] = '\0';
577     add_symbol_name(&m->symbol_context,
578     v, 0, name, 0);
579     n_real_symbols ++;
580     } else if (t == 0x20 && !sym->name[0]) {
581     off_t ofs;
582     ofs = f_symptr + altname +
583     sizeof(struct ms_sym) * f_nsyms;
584     fseek(f, ofs, SEEK_SET);
585     fread(name, 1, sizeof(name), f);
586     name[sizeof(name)-1] = '\0';
587     /* debug(" [altname=0x%x '%s']",
588     altname, name); */
589     add_symbol_name(&m->symbol_context,
590     v, 0, name, 0);
591     n_real_symbols ++;
592     }
593    
594    
595     if (sym->n_aux_syms) {
596     int n = sym->n_aux_syms;
597     /* debug(" aux='"); */
598     while (n-- > 0) {
599     sym ++; sym_nr ++;
600     /* for (i=0; i<8 &&
601     sym->name[i]; i++)
602     debug("%c",
603     sym->name[i]); */
604     }
605     /* debug("'"); */
606     }
607     /* debug("\n"); */
608     sym ++;
609     }
610    
611     debug("%i symbols\n", n_real_symbols);
612     free(ms_sym_buf);
613    
614     goto skip_normal_coff_symbols;
615     }
616    
617     debug("symbol header: magic = 0x%x\n", sym_magic);
618    
619     debug("%i symbols @ 0x%08x (strings @ 0x%08x)\n",
620     iextMax, cbExtOffset, cbSsExtOffset);
621    
622     symbol_data = malloc(issExtMax + 2);
623     if (symbol_data == NULL) {
624     fprintf(stderr, "out of memory\n");
625     exit(1);
626     }
627     memset(symbol_data, 0, issExtMax + 2);
628     fseek(f, cbSsExtOffset, SEEK_SET);
629     fread(symbol_data, 1, issExtMax + 1, f);
630    
631     nsymbols = iextMax;
632    
633     extsyms = malloc(iextMax * sizeof(struct ecoff_extsym));
634     if (extsyms == NULL) {
635     fprintf(stderr, "out of memory\n");
636     exit(1);
637     }
638     memset(extsyms, 0, iextMax * sizeof(struct ecoff_extsym));
639     fseek(f, cbExtOffset, SEEK_SET);
640     fread(extsyms, 1, iextMax * sizeof(struct ecoff_extsym), f);
641    
642     /* Unencode the strindex and value first: */
643     for (sym_nr=0; sym_nr<nsymbols; sym_nr++) {
644     uint64_t value, strindex;
645    
646     unencode(strindex, &extsyms[sym_nr].es_strindex,
647     uint32_t);
648     unencode(value, &extsyms[sym_nr].es_value, uint32_t);
649    
650     extsyms[sym_nr].es_strindex = strindex;
651     extsyms[sym_nr].es_value = value;
652     }
653    
654     for (sym_nr=0; sym_nr<nsymbols; sym_nr++) {
655     /* debug("symbol%6i: 0x%08x = %s\n",
656     sym_nr, (int)extsyms[sym_nr].es_value,
657     symbol_data + extsyms[sym_nr].es_strindex); */
658    
659     add_symbol_name(&m->symbol_context,
660     extsyms[sym_nr].es_value, 0,
661     symbol_data + extsyms[sym_nr].es_strindex, 0);
662     }
663    
664     free(extsyms);
665     free(symbol_data);
666    
667     skip_normal_coff_symbols:
668     ;
669     }
670    
671     fclose(f);
672    
673     *entrypointp = a_entry;
674     *gpp = a_gp;
675     m->file_loaded_end_addr = end_addr;
676    
677     if (program_byte_order != -1)
678     encoding = program_byte_order;
679    
680     if (encoding == ELFDATA2LSB)
681     *byte_orderp = EMUL_LITTLE_ENDIAN;
682     else
683     *byte_orderp = EMUL_BIG_ENDIAN;
684    
685     n_executables_loaded ++;
686     }
687    
688    
689     /*
690     * file_load_srec():
691     *
692     * Loads a Motorola SREC file into emulated memory. Description of the SREC
693     * file format can be found at here:
694     *
695     * http://www.ndsu.nodak.edu/instruct/tareski/373f98/notes/srecord.htm
696     * or http://www.amelek.gda.pl/avr/uisp/srecord.htm
697     */
698     static void file_load_srec(struct machine *m, struct memory *mem,
699     char *filename, uint64_t *entrypointp)
700     {
701     FILE *f;
702     unsigned char buf[516];
703     unsigned char bytes[270];
704     uint64_t entry = 0, vaddr = 0;
705     int i, j, count;
706     char ch;
707     int buf_len, data_start = 0;
708     int entry_set = 0;
709     int warning = 0;
710     int warning_len = 0;
711     int total_bytes_loaded = 0;
712    
713     f = fopen(filename, "r");
714     if (f == NULL) {
715     perror(filename);
716     exit(1);
717     }
718    
719     /* Load file contents: */
720     while (!feof(f)) {
721     memset(buf, 0, sizeof(buf));
722     fgets((char *)buf, sizeof(buf)-1, f);
723    
724     if (buf[0] == 0 || buf[0]=='\r' || buf[0]=='\n')
725     continue;
726    
727     if (buf[0] != 'S') {
728     if (!warning)
729     debug("WARNING! non-S-record found\n");
730     warning = 1;
731     continue;
732     }
733    
734     buf_len = strlen((char *)buf);
735    
736     if (buf_len < 10) {
737     if (!warning_len)
738     debug("WARNING! invalid S-record found\n");
739     warning_len = 1;
740     continue;
741     }
742    
743     /*
744     * Stype count address data checksum
745     * 01 23 4.. .. (last 2 bytes)
746     *
747     * TODO: actually check the checksum
748     */
749    
750     j = 0;
751     for (i=1; i<buf_len; i++) {
752     if (buf[i]>='a' && buf[i]<='f')
753     buf[i] += 10 - 'a';
754     else if (buf[i] >= 'A' && buf[i] <= 'F')
755     buf[i] += 10 - 'A';
756     else if (buf[i] >= '0' && buf[i] <= '9')
757     buf[i] -= '0';
758     else if (buf[i] == '\r' || buf[i] == '\n') {
759     } else
760     fatal("invalid characters '%c' in S-record\n",
761     buf[i]);
762    
763     if (i >= 4) {
764     if (i & 1)
765     bytes[j++] += buf[i];
766     else
767     bytes[j] = buf[i] * 16;
768     }
769     }
770    
771     count = buf[2] * 16 + buf[3];
772     /* debug("count=%i j=%i\n", count, j); */
773     /* count is j - 1. */
774    
775     switch (buf[1]) {
776     case 0:
777     debug("SREC \"");
778     for (i=2; i<count-1; i++) {
779     ch = bytes[i];
780     if (ch >= ' ' && ch < 127)
781     debug("%c", ch);
782     else
783     debug("?");
784     }
785     debug("\"\n");
786     break;
787     case 1:
788     case 2:
789     case 3:
790     /* switch again, to get the load address: */
791     switch (buf[1]) {
792     case 1: data_start = 2;
793     vaddr = (bytes[0] << 8) + bytes[1];
794     break;
795     case 2: data_start = 3;
796     vaddr = (bytes[0] << 16) + (bytes[1] << 8) +
797     bytes[2];
798     break;
799     case 3: data_start = 4;
800     vaddr = (bytes[0] << 24) + (bytes[1] << 16) +
801     (bytes[2] << 8) + bytes[3];
802     }
803     m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr,
804     &bytes[data_start], count - 1 - data_start,
805     MEM_WRITE, NO_EXCEPTIONS);
806     total_bytes_loaded += count - 1 - data_start;
807     break;
808     case 7:
809     case 8:
810     case 9:
811     /* switch again, to get the entry point: */
812     switch (buf[1]) {
813     case 7: entry = (bytes[0] << 24) + (bytes[1] << 16) +
814     (bytes[2] << 8) + bytes[3];
815     break;
816     case 8: entry = (bytes[0] << 16) + (bytes[1] << 8) +
817     bytes[2];
818     break;
819     case 9: entry = (bytes[0] << 8) + bytes[1];
820     break;
821     }
822     entry_set = 1;
823     debug("entry point 0x%08x\n", (unsigned int)entry);
824     break;
825     default:
826     debug("unimplemented S-record type %i\n", buf[1]);
827     }
828     }
829    
830     debug("0x%x bytes loaded\n", total_bytes_loaded);
831    
832     fclose(f);
833    
834     if (!entry_set)
835     debug("WARNING! no entrypoint found!\n");
836     else
837     *entrypointp = entry;
838    
839     n_executables_loaded ++;
840     }
841    
842    
843     /*
844     * file_load_raw():
845     *
846     * Loads a raw binary into emulated memory. The filename should be
847     * of the following form: loadaddress:filename
848     * or loadaddress:skiplen:filename
849     * or loadaddress:skiplen:pc:filename
850     */
851     static void file_load_raw(struct machine *m, struct memory *mem,
852     char *filename, uint64_t *entrypointp)
853     {
854     FILE *f;
855     int len;
856     unsigned char buf[4096];
857     uint64_t entry, loadaddr, vaddr, skip = 0;
858     char *p, *p2;
859    
860     p = strchr(filename, ':');
861     if (p == NULL) {
862     fprintf(stderr, "\n");
863     perror(filename);
864     exit(1);
865     }
866    
867     loadaddr = vaddr = entry = strtoull(filename, NULL, 0);
868     p2 = p+1;
869    
870     /* A second value? That's the optional skip value */
871     p = strchr(p2, ':');
872     if (p != NULL) {
873     skip = strtoull(p2, NULL, 0);
874     p = p+1;
875     /* A third value? That's the initial pc: */
876     if (strchr(p, ':') != NULL) {
877     entry = strtoull(p, NULL, 0);
878     p = strchr(p, ':') + 1;
879     }
880     } else
881     p = p2;
882    
883     f = fopen(strrchr(filename, ':')+1, "r");
884     if (f == NULL) {
885     perror(p);
886     exit(1);
887     }
888    
889     fseek(f, skip, SEEK_SET);
890    
891     /* Load file contents: */
892     while (!feof(f)) {
893     len = fread(buf, 1, sizeof(buf), f);
894    
895     if (len > 0)
896     m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0],
897     len, MEM_WRITE, NO_EXCEPTIONS);
898    
899     vaddr += len;
900     }
901    
902     debug("RAW: 0x%llx bytes @ 0x%08llx",
903 dpavlin 10 (long long) (ftello(f) - skip), (long long)loadaddr);
904 dpavlin 2 if (skip != 0)
905     debug(" (0x%llx bytes of header skipped)", (long long)skip);
906     debug("\n");
907    
908     fclose(f);
909    
910     *entrypointp = entry;
911    
912     n_executables_loaded ++;
913     }
914    
915    
916     /*
917     * file_load_elf():
918     *
919     * Loads an ELF image into the emulated memory. The entry point (read from
920     * the ELF header) and the initial value of the gp register (read from the
921     * ELF symbol table) are stored in the specified CPU's registers.
922     *
923     * This is pretty heavy stuff, but is needed because of the heaviness of
924     * ELF files. :-/ Hopefully it will be able to recognize most valid ELFs.
925     */
926     static void file_load_elf(struct machine *m, struct memory *mem,
927     char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp,
928     int *byte_order, uint64_t *tocp)
929     {
930     Elf32_Ehdr hdr32;
931     Elf64_Ehdr hdr64;
932     FILE *f;
933     uint64_t eentry;
934     int len, i, ok;
935     int elf64, encoding, eflags;
936     int etype, emachine;
937     int ephnum, ephentsize, eshnum, eshentsize;
938     off_t ephoff, eshoff;
939     Elf32_Phdr phdr32;
940     Elf64_Phdr phdr64;
941     Elf32_Shdr shdr32;
942     Elf64_Shdr shdr64;
943     Elf32_Sym sym32;
944     Elf64_Sym sym64;
945     int ofs;
946     int chunk_len = 1024, align_len;
947     char *symbol_strings = NULL; size_t symbol_length = 0;
948     char *s;
949     Elf32_Sym *symbols_sym32 = NULL; int n_symbols = 0;
950     Elf64_Sym *symbols_sym64 = NULL;
951    
952     f = fopen(filename, "r");
953     if (f == NULL) {
954     perror(filename);
955     exit(1);
956     }
957    
958     len = fread(&hdr32, 1, sizeof(Elf32_Ehdr), f);
959     if (len < (signed int)sizeof(Elf32_Ehdr)) {
960     fprintf(stderr, "%s: not an ELF file image\n", filename);
961     exit(1);
962     }
963    
964     if (memcmp(&hdr32.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0) {
965     fprintf(stderr, "%s: not an ELF file image\n", filename);
966     exit(1);
967     }
968    
969     switch (hdr32.e_ident[EI_CLASS]) {
970     case ELFCLASS32:
971     elf64 = 0;
972     break;
973     case ELFCLASS64:
974     elf64 = 1;
975     fseek(f, 0, SEEK_SET);
976     len = fread(&hdr64, 1, sizeof(Elf64_Ehdr), f);
977     if (len < (signed int)sizeof(Elf64_Ehdr)) {
978     fprintf(stderr, "%s: not an ELF64 file image\n",
979     filename);
980     exit(1);
981     }
982     break;
983     default:
984     fprintf(stderr, "%s: unknown ELF class '%i'\n",
985     filename, hdr32.e_ident[EI_CLASS]);
986     exit(1);
987     }
988    
989     encoding = hdr32.e_ident[EI_DATA];
990     if (encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) {
991     fprintf(stderr, "%s: unknown data encoding '%i'\n",
992     filename, hdr32.e_ident[EI_DATA]);
993     exit(1);
994     }
995    
996     if (elf64) {
997     unencode(etype, &hdr64.e_type, Elf64_Quarter);
998     unencode(eflags, &hdr64.e_flags, Elf64_Half);
999     unencode(emachine, &hdr64.e_machine, Elf64_Quarter);
1000     unencode(eentry, &hdr64.e_entry, Elf64_Addr);
1001     unencode(ephnum, &hdr64.e_phnum, Elf64_Quarter);
1002     unencode(ephentsize, &hdr64.e_phentsize, Elf64_Quarter);
1003     unencode(ephoff, &hdr64.e_phoff, Elf64_Off);
1004     unencode(eshnum, &hdr64.e_shnum, Elf64_Quarter);
1005     unencode(eshentsize, &hdr64.e_shentsize, Elf64_Quarter);
1006     unencode(eshoff, &hdr64.e_shoff, Elf64_Off);
1007     if (ephentsize != sizeof(Elf64_Phdr)) {
1008     fprintf(stderr, "%s: incorrect phentsize? %i, should "
1009 dpavlin 6 "be %i\nPerhaps this is a dynamically linked "
1010     "binary (which isn't supported yet).\n", filename,
1011     (int)ephentsize, (int)sizeof(Elf64_Phdr));
1012 dpavlin 2 exit(1);
1013     }
1014     if (eshentsize != sizeof(Elf64_Shdr)) {
1015 dpavlin 6 fprintf(stderr, "%s: incorrect shentsize? %i, should "
1016     "be %i\nPerhaps this is a dynamically linked "
1017     "binary (which isn't supported yet).\n", filename,
1018     (int)eshentsize, (int)sizeof(Elf64_Shdr));
1019 dpavlin 2 exit(1);
1020     }
1021     } else {
1022     unencode(etype, &hdr32.e_type, Elf32_Half);
1023     unencode(eflags, &hdr32.e_flags, Elf32_Word);
1024     unencode(emachine, &hdr32.e_machine, Elf32_Half);
1025     unencode(eentry, &hdr32.e_entry, Elf32_Addr);
1026     unencode(ephnum, &hdr32.e_phnum, Elf32_Half);
1027     unencode(ephentsize, &hdr32.e_phentsize, Elf32_Half);
1028     unencode(ephoff, &hdr32.e_phoff, Elf32_Off);
1029     unencode(eshnum, &hdr32.e_shnum, Elf32_Half);
1030     unencode(eshentsize, &hdr32.e_shentsize, Elf32_Half);
1031     unencode(eshoff, &hdr32.e_shoff, Elf32_Off);
1032     if (ephentsize != sizeof(Elf32_Phdr)) {
1033     fprintf(stderr, "%s: incorrect phentsize? %i, should "
1034 dpavlin 6 "be %i\nPerhaps this is a dynamically linked "
1035     "binary (which isn't supported yet).\n", filename,
1036     (int)ephentsize, (int)sizeof(Elf32_Phdr));
1037 dpavlin 2 exit(1);
1038     }
1039     if (eshentsize != sizeof(Elf32_Shdr)) {
1040 dpavlin 6 fprintf(stderr, "%s: incorrect shentsize? %i, should "
1041     "be %i\nPerhaps this is a dynamically linked "
1042     "binary (which isn't supported yet).\n", filename,
1043     (int)eshentsize, (int)sizeof(Elf32_Shdr));
1044 dpavlin 2 exit(1);
1045     }
1046     }
1047    
1048     if ( etype != ET_EXEC ) {
1049     fprintf(stderr, "%s is not an ELF Executable file, type = %i\n",
1050     filename, etype);
1051     exit(1);
1052     }
1053    
1054     ok = 0;
1055     switch (arch) {
1056 dpavlin 4 case ARCH_ALPHA:
1057     switch (emachine) {
1058     case EM_ALPHA:
1059     case -28634:
1060     ok = 1;
1061     }
1062     break;
1063     case ARCH_HPPA:
1064     switch (emachine) {
1065     case EM_PARISC:
1066     ok = 1;
1067     }
1068     break;
1069 dpavlin 2 case ARCH_MIPS:
1070     switch (emachine) {
1071     case EM_MIPS:
1072     case EM_MIPS_RS3_LE:
1073     ok = 1;
1074     }
1075     break;
1076     case ARCH_PPC:
1077     switch (emachine) {
1078     case EM_PPC:
1079     case EM_PPC64:
1080     ok = 1;
1081     }
1082     break;
1083     case ARCH_SPARC:
1084     switch (emachine) {
1085     case EM_SPARC:
1086     case EM_SPARCV9:
1087     ok = 1;
1088     }
1089     break;
1090 dpavlin 4 case ARCH_X86:
1091 dpavlin 2 switch (emachine) {
1092 dpavlin 4 case EM_386:
1093     case EM_486:
1094 dpavlin 6 *tocp = 1;
1095 dpavlin 2 ok = 1;
1096 dpavlin 4 break;
1097     case EM_AMD64:
1098 dpavlin 6 *tocp = 2;
1099 dpavlin 2 ok = 1;
1100 dpavlin 4 break;
1101 dpavlin 2 }
1102     break;
1103 dpavlin 6 case ARCH_ARM:
1104     switch (emachine) {
1105     case EM_ARM:
1106     ok = 1;
1107     }
1108     break;
1109 dpavlin 2 default:
1110     fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n");
1111     }
1112     if (!ok) {
1113     fprintf(stderr, "%s: this is a ", filename);
1114     if (emachine >= 0 && emachine < N_ELF_MACHINE_TYPES)
1115     fprintf(stderr, elf_machine_type[emachine]);
1116     else
1117     fprintf(stderr, "machine type '%i'", emachine);
1118     fprintf(stderr, " ELF binary!\n");
1119     exit(1);
1120     }
1121    
1122     s = "entry point";
1123     if (elf64 && arch == ARCH_PPC)
1124     s = "function descriptor at";
1125    
1126     debug("ELF%i %s, %s 0x", elf64? 64 : 32,
1127     encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s);
1128    
1129     if (elf64)
1130     debug("%016llx\n", (long long)eentry);
1131     else
1132     debug("%08x\n", (int)eentry);
1133    
1134     /*
1135     * MIPS16 encoding?
1136     *
1137     * TODO: Find out what e_flag actually contains.
1138     * TODO 2: This only sets mips16 for cpu 0. Yuck. Fix this!
1139     */
1140    
1141     if (((eflags >> 24) & 0xff) == 0x24) {
1142     debug("MIPS16 encoding (e_flags = 0x%08x)\n", eflags);
1143     #ifdef ENABLE_MIPS16
1144     m->cpus[0]->cd.mips.mips16 = 1;
1145     #else
1146     fatal("ENABLE_MIPS16 must be defined in misc.h.\n"
1147     "(or use the --mips16 configure option)\n");
1148     exit(1);
1149     #endif
1150     } else if (eentry & 0x3) {
1151     debug("MIPS16 encoding (eentry not 32-bit aligned)\n");
1152     #ifdef ENABLE_MIPS16
1153     m->cpus[0]->cd.mips.mips16 = 1;
1154     #else
1155     fatal("ENABLE_MIPS16 must be defined in misc.h.\n"
1156     "(or use the --mips16 configure option)\n");
1157     exit(1);
1158     #endif
1159     }
1160    
1161     /* Read the program headers: */
1162    
1163     for (i=0; i<ephnum; i++) {
1164     int p_type;
1165     uint64_t p_offset;
1166     uint64_t p_vaddr;
1167     uint64_t p_paddr;
1168     uint64_t p_filesz;
1169     uint64_t p_memsz;
1170     int p_flags;
1171     int p_align;
1172    
1173     fseek(f, ephoff + i * ephentsize, SEEK_SET);
1174    
1175     if (elf64) {
1176     fread(&phdr64, 1, sizeof(Elf64_Phdr), f);
1177     unencode(p_type, &phdr64.p_type, Elf64_Half);
1178     unencode(p_flags, &phdr64.p_flags, Elf64_Half);
1179     unencode(p_offset, &phdr64.p_offset, Elf64_Off);
1180     unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr);
1181     unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr);
1182     unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword);
1183     unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword);
1184     unencode(p_align, &phdr64.p_align, Elf64_Xword);
1185     } else {
1186     fread(&phdr32, 1, sizeof(Elf32_Phdr), f);
1187     unencode(p_type, &phdr32.p_type, Elf32_Word);
1188     unencode(p_offset, &phdr32.p_offset, Elf32_Off);
1189     unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr);
1190     unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr);
1191     unencode(p_filesz, &phdr32.p_filesz, Elf32_Word);
1192     unencode(p_memsz, &phdr32.p_memsz, Elf32_Word);
1193     unencode(p_flags, &phdr32.p_flags, Elf32_Word);
1194     unencode(p_align, &phdr32.p_align, Elf32_Word);
1195     }
1196    
1197     if (p_memsz != 0 && (p_type == PT_LOAD ||
1198     (p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) {
1199     debug("chunk %i (", i);
1200     if (p_type == PT_LOAD)
1201     debug("load");
1202     else
1203     debug("0x%08x", (int)p_type);
1204    
1205     debug(") @ 0x%llx, vaddr 0x", (long long)p_offset);
1206    
1207     if (elf64)
1208     debug("%016llx", (long long)p_vaddr);
1209     else
1210     debug("%08x", (int)p_vaddr);
1211    
1212     debug(" len=0x%llx\n", (long long)p_memsz);
1213    
1214 dpavlin 10 if (p_vaddr != p_paddr)
1215     fatal("WARNING! vaddr (0x%llx) and paddr "
1216     "(0x%llx) differ; using vaddr\n",
1217     (long long)p_vaddr, (long long)p_paddr);
1218 dpavlin 2
1219     if (p_memsz < p_filesz) {
1220     fprintf(stderr, "%s: memsz < filesz. TODO: how"
1221     " to handle this? memsz=%016llx filesz="
1222     "%016llx\n", filename, (long long)p_memsz,
1223     (long long)p_filesz);
1224     exit(1);
1225     }
1226    
1227     fseek(f, p_offset, SEEK_SET);
1228     align_len = 1;
1229     if ((p_vaddr & 0xf)==0) align_len = 0x10;
1230     if ((p_vaddr & 0x3f)==0) align_len = 0x40;
1231     if ((p_vaddr & 0xff)==0) align_len = 0x100;
1232     if ((p_vaddr & 0xfff)==0) align_len = 0x1000;
1233     if ((p_vaddr & 0x3fff)==0) align_len = 0x4000;
1234     if ((p_vaddr & 0xffff)==0) align_len = 0x10000;
1235     ofs = 0; len = chunk_len = align_len;
1236     while (ofs < (int64_t)p_filesz && len==chunk_len) {
1237     unsigned char *ch = malloc(chunk_len);
1238     int i = 0;
1239    
1240     /* Switch to larger size, if possible: */
1241     if (align_len < 0x10000 &&
1242     ((p_vaddr + ofs) & 0xffff)==0) {
1243     align_len = 0x10000;
1244     len = chunk_len = align_len;
1245     free(ch);
1246     ch = malloc(chunk_len);
1247     } else if (align_len < 0x1000 &&
1248     ((p_vaddr + ofs) & 0xfff)==0) {
1249     align_len = 0x1000;
1250     len = chunk_len = align_len;
1251     free(ch);
1252     ch = malloc(chunk_len);
1253     }
1254    
1255     if (ch == NULL) {
1256     fprintf(stderr, "out of memory\n");
1257     exit(1);
1258     }
1259    
1260     len = fread(&ch[0], 1, chunk_len, f);
1261     if (ofs + len > (int64_t)p_filesz)
1262     len = p_filesz - ofs;
1263    
1264     while (i < len) {
1265     size_t len_to_copy;
1266     len_to_copy = (i + align_len) <= len?
1267     align_len : len - i;
1268     m->cpus[0]->memory_rw(m->cpus[0], mem,
1269     p_vaddr + ofs, &ch[i], len_to_copy,
1270     MEM_WRITE, NO_EXCEPTIONS);
1271     ofs += align_len;
1272     i += align_len;
1273     }
1274    
1275     free(ch);
1276     }
1277     }
1278     }
1279    
1280     /* Read the section headers to find the address of the _gp symbol: */
1281    
1282     for (i=0; i<eshnum; i++) {
1283     int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize;
1284     uint64_t sh_addr, sh_size, sh_addralign;
1285     off_t sh_offset;
1286     int n_entries; /* for reading the symbol / string tables */
1287    
1288     /* debug("section header %i at %016llx\n", i,
1289     (long long) eshoff+i*eshentsize); */
1290    
1291     fseek(f, eshoff + i * eshentsize, SEEK_SET);
1292    
1293     if (elf64) {
1294     len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f);
1295     if (len != sizeof(Elf64_Shdr)) {
1296     fprintf(stderr, "couldn't read header\n");
1297     exit(1);
1298     }
1299     unencode(sh_name, &shdr64.sh_name, Elf64_Half);
1300     unencode(sh_type, &shdr64.sh_type, Elf64_Half);
1301     unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword);
1302     unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr);
1303     unencode(sh_offset, &shdr64.sh_offset, Elf64_Off);
1304     unencode(sh_size, &shdr64.sh_size, Elf64_Xword);
1305     unencode(sh_link, &shdr64.sh_link, Elf64_Half);
1306     unencode(sh_info, &shdr64.sh_info, Elf64_Half);
1307     unencode(sh_addralign, &shdr64.sh_addralign,
1308     Elf64_Xword);
1309     unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword);
1310     } else {
1311     len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f);
1312     if (len != sizeof(Elf32_Shdr)) {
1313     fprintf(stderr, "couldn't read header\n");
1314     exit(1);
1315     }
1316     unencode(sh_name, &shdr32.sh_name, Elf32_Word);
1317     unencode(sh_type, &shdr32.sh_type, Elf32_Word);
1318     unencode(sh_flags, &shdr32.sh_flags, Elf32_Word);
1319     unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr);
1320     unencode(sh_offset, &shdr32.sh_offset, Elf32_Off);
1321     unencode(sh_size, &shdr32.sh_size, Elf32_Word);
1322     unencode(sh_link, &shdr32.sh_link, Elf32_Word);
1323     unencode(sh_info, &shdr32.sh_info, Elf32_Word);
1324     unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word);
1325     unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word);
1326     }
1327    
1328     /* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx"
1329     " sh_size=%06lx sh_entsize=%03lx\n",
1330     (long)sh_name, (long)sh_type, (long)sh_flags,
1331     (long)sh_size, (long)sh_entsize); */
1332    
1333     /* Perhaps it is bad to reuse sh_entsize like this? TODO */
1334     if (elf64)
1335     sh_entsize = sizeof(Elf64_Sym);
1336     else
1337     sh_entsize = sizeof(Elf32_Sym);
1338    
1339     if (sh_type == SHT_SYMTAB) {
1340     size_t len;
1341     n_entries = sh_size / sh_entsize;
1342    
1343     fseek(f, sh_offset, SEEK_SET);
1344    
1345     if (elf64) {
1346     if (symbols_sym64 != NULL)
1347     free(symbols_sym64);
1348     symbols_sym64 = malloc(sh_size);
1349     if (symbols_sym64 == NULL) {
1350     fprintf(stderr, "out of memory\n");
1351     exit(1);
1352     }
1353    
1354     len = fread(symbols_sym64, 1, sh_entsize *
1355     n_entries, f);
1356     } else {
1357     if (symbols_sym32 != NULL)
1358     free(symbols_sym32);
1359     symbols_sym32 = malloc(sh_size);
1360     if (symbols_sym32 == NULL) {
1361     fprintf(stderr, "out of memory\n");
1362     exit(1);
1363     }
1364    
1365     len = fread(symbols_sym32, 1,
1366     sh_entsize * n_entries, f);
1367     }
1368    
1369     if (len != sh_size) {
1370     fprintf(stderr, "could not read symbols from "
1371     "%s\n", filename);
1372     exit(1);
1373     }
1374    
1375     debug("%i symbol entries at 0x%llx\n",
1376     (int)n_entries, (long long)sh_offset);
1377    
1378     n_symbols = n_entries;
1379     }
1380    
1381     /*
1382     * TODO: This is incorrect, there may be several strtab
1383     * sections.
1384     *
1385     * For now, the simple/stupid guess that the largest string
1386     * table is the one to use seems to be good enough.
1387     */
1388    
1389     if (sh_type == SHT_STRTAB && sh_size > symbol_length) {
1390     size_t len;
1391    
1392     if (symbol_strings != NULL)
1393     free(symbol_strings);
1394    
1395     symbol_strings = malloc(sh_size + 1);
1396     if (symbol_strings == NULL) {
1397     fprintf(stderr, "out of memory\n");
1398     exit(1);
1399     }
1400    
1401     fseek(f, sh_offset, SEEK_SET);
1402     len = fread(symbol_strings, 1, sh_size, f);
1403     if (len != sh_size) {
1404     fprintf(stderr, "could not read symbols from "
1405     "%s\n", filename);
1406     exit(1);
1407     }
1408    
1409     debug("%i bytes of symbol strings at 0x%llx\n",
1410     (int)sh_size, (long long)sh_offset);
1411    
1412     symbol_strings[sh_size] = '\0';
1413     symbol_length = sh_size;
1414     }
1415     }
1416    
1417     fclose(f);
1418    
1419     /* Decode symbols: */
1420     if (symbol_strings != NULL) {
1421     for (i=0; i<n_symbols; i++) {
1422     uint64_t st_name, addr, size;
1423     int st_info;
1424    
1425     if (elf64) {
1426     sym64 = symbols_sym64[i];
1427     unencode(st_name, &sym64.st_name, Elf64_Half);
1428     unencode(st_info, &sym64.st_info, Elf_Byte);
1429     unencode(addr, &sym64.st_value, Elf64_Addr);
1430     unencode(size, &sym64.st_size, Elf64_Xword);
1431     } else {
1432     sym32 = symbols_sym32[i];
1433     unencode(st_name, &sym32.st_name, Elf32_Word);
1434     unencode(st_info, &sym64.st_info, Elf_Byte);
1435     unencode(addr, &sym32.st_value, Elf32_Word);
1436     unencode(size, &sym32.st_size, Elf32_Word);
1437     }
1438    
1439     if (size == 0)
1440     size ++;
1441    
1442 dpavlin 6 if (addr != 0) /* && ((st_info >> 4) & 0xf)
1443     >= STB_GLOBAL) */ {
1444 dpavlin 2 /* debug("symbol info=0x%02x addr=0x%016llx"
1445     " '%s'\n", st_info, (long long)addr,
1446     symbol_strings + st_name); */
1447     add_symbol_name(&m->symbol_context,
1448     addr, size, symbol_strings + st_name, 0);
1449     }
1450    
1451     if (strcmp(symbol_strings + st_name, "_gp") == 0) {
1452     debug("found _gp address: 0x");
1453     if (elf64)
1454     debug("%016llx\n", (long long)addr);
1455     else
1456     debug("%08x\n", (int)addr);
1457     *gpp = addr;
1458     }
1459     }
1460     }
1461    
1462     *entrypointp = eentry;
1463    
1464     if (encoding == ELFDATA2LSB)
1465     *byte_order = EMUL_LITTLE_ENDIAN;
1466     else
1467     *byte_order = EMUL_BIG_ENDIAN;
1468    
1469     if (elf64 && arch == ARCH_PPC) {
1470     /*
1471     * Special case for 64-bit PPC ELFs:
1472     *
1473     * The ELF starting symbol points to a ".opd" section
1474     * which contains a function descriptor:
1475     *
1476     * uint64_t start;
1477     * uint64_t toc_base;
1478     * uint64_t something_else; (?)
1479     */
1480     int res;
1481     unsigned char b[sizeof(uint64_t)];
1482     uint64_t toc_base;
1483    
1484     debug("PPC64: ");
1485    
1486     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
1487     sizeof(b), MEM_READ, NO_EXCEPTIONS);
1488     if (!res)
1489     debug(" [WARNING: could not read memory?] ");
1490    
1491     /* PPC are always big-endian: */
1492     *entrypointp = ((uint64_t)b[0] << 56) +
1493     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
1494     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
1495     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
1496     (uint64_t)b[7];
1497    
1498     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
1499     b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
1500     if (!res)
1501     fatal(" [WARNING: could not read memory?] ");
1502    
1503     toc_base = ((uint64_t)b[0] << 56) +
1504     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
1505     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
1506     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
1507     (uint64_t)b[7];
1508    
1509     debug("entrypoint 0x%016llx, toc_base 0x%016llx\n",
1510     (long long)*entrypointp, (long long)toc_base);
1511     if (tocp != NULL)
1512     *tocp = toc_base;
1513     }
1514    
1515     n_executables_loaded ++;
1516     }
1517    
1518    
1519     /*
1520     * file_n_executables_loaded():
1521     *
1522     * Returns the number of executable files loaded into emulated memory.
1523     */
1524     int file_n_executables_loaded(void)
1525     {
1526     return n_executables_loaded;
1527     }
1528    
1529    
1530     /*
1531     * file_load():
1532     *
1533     * Sense the file format of a file (ELF, a.out, ecoff), and call the
1534     * right file_load_XXX() function. If the file isn't of a recognized
1535     * binary format, assume that it contains symbol definitions.
1536     *
1537     * If the filename doesn't exist, try to treat the name as
1538     * "address:filename" and load the file as a raw binary.
1539     */
1540     void file_load(struct machine *machine, struct memory *mem,
1541     char *filename, uint64_t *entrypointp,
1542     int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp)
1543     {
1544     int iadd = 4;
1545     FILE *f;
1546     unsigned char buf[12];
1547 dpavlin 6 unsigned char buf2[2];
1548     size_t len, len2, i;
1549 dpavlin 2 off_t size;
1550    
1551     if (byte_orderp == NULL) {
1552     fprintf(stderr, "file_load(): byte_order == NULL\n");
1553     exit(1);
1554     }
1555    
1556     if (arch == ARCH_NOARCH) {
1557     fprintf(stderr, "file_load(): FATAL ERROR: no arch?\n");
1558     exit(1);
1559     }
1560    
1561     if (mem == NULL || filename == NULL) {
1562     fprintf(stderr, "file_load(): mem or filename is NULL\n");
1563     exit(1);
1564     }
1565    
1566     /* Skip configuration files: */
1567     if (filename[0] == '@')
1568     return;
1569    
1570     debug("loading %s:\n", filename);
1571     debug_indentation(iadd);
1572    
1573     f = fopen(filename, "r");
1574     if (f == NULL) {
1575     file_load_raw(machine, mem, filename, entrypointp);
1576     goto ret;
1577     }
1578    
1579     fseek(f, 0, SEEK_END);
1580 dpavlin 10 size = ftello(f);
1581 dpavlin 2 fseek(f, 0, SEEK_SET);
1582    
1583     memset(buf, 0, sizeof(buf));
1584     len = fread(buf, 1, sizeof(buf), f);
1585 dpavlin 6 fseek(f, 510, SEEK_SET);
1586     len2 = fread(buf2, 1, sizeof(buf2), f);
1587 dpavlin 2 fclose(f);
1588    
1589     if (len < (signed int)sizeof(buf)) {
1590     fprintf(stderr, "\nThis file is too small to contain "
1591     "anything useful\n");
1592     exit(1);
1593     }
1594    
1595     /* Is it an ELF? */
1596     if (buf[0] == 0x7f && buf[1]=='E' && buf[2]=='L' && buf[3]=='F') {
1597     file_load_elf(machine, mem, filename,
1598     entrypointp, arch, gpp, byte_orderp, tocp);
1599     goto ret;
1600     }
1601    
1602 dpavlin 6 /* Is it an a.out? */
1603 dpavlin 2 if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) {
1604 dpavlin 6 /* MIPS a.out */
1605 dpavlin 2 file_load_aout(machine, mem, filename, 0,
1606     entrypointp, arch, byte_orderp);
1607     goto ret;
1608     }
1609 dpavlin 6 if (buf[0]==0x00 && buf[1]==0x86 && buf[2]==0x01 && buf[3]==0x0b) {
1610     /* i386 a.out (old OpenBSD and NetBSD etc) */
1611     file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING,
1612     entrypointp, arch, byte_orderp);
1613     goto ret;
1614     }
1615 dpavlin 2 if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) {
1616 dpavlin 6 /* DEC OSF1 on MIPS: */
1617     file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1,
1618 dpavlin 2 entrypointp, arch, byte_orderp);
1619     goto ret;
1620     }
1621    
1622     /*
1623     * Is it an ecoff?
1624     *
1625     * TODO: What's the deal with the magic value's byte order? Sometimes
1626     * it seems to be reversed for BE when compared to LE, but not always?
1627     */
1628     if (buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB ||
1629     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL ||
1630     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB2 ||
1631     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL2 ||
1632     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB3 ||
1633     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL3 ||
1634     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB ||
1635     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL ||
1636     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB2 ||
1637     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL2 ||
1638     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB3 ||
1639     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL3) {
1640     file_load_ecoff(machine, mem, filename, entrypointp,
1641     arch, gpp, byte_orderp);
1642     goto ret;
1643     }
1644    
1645     /* Is it a Motorola SREC file? */
1646     if ((buf[0]=='S' && buf[1]>='0' && buf[1]<='9')) {
1647     file_load_srec(machine, mem, filename, entrypointp);
1648     goto ret;
1649     }
1650    
1651     /* gzipped files are not supported: */
1652     if (buf[0]==0x1f && buf[1]==0x8b) {
1653     fprintf(stderr, "\nYou need to gunzip the file before you"
1654     " try to use it.\n");
1655     exit(1);
1656     }
1657    
1658     if (size > 24000000) {
1659     fprintf(stderr, "\nThis file is very large (%lli bytes)\n",
1660     (long long)size);
1661     fprintf(stderr, "Are you sure it is a kernel and not a disk "
1662 dpavlin 6 "image? (Use the -d option.)\n");
1663 dpavlin 2 exit(1);
1664     }
1665    
1666 dpavlin 4 if (size == 1474560)
1667     fprintf(stderr, "Hm... this file is the size of a 1.44 MB "
1668     "floppy image. Maybe you forgot the\n-d switch?\n");
1669    
1670 dpavlin 2 /*
1671     * Last resort: symbol definitions from nm (or nm -S):
1672     *
1673     * If the buf contains typical 'binary' characters, then print
1674     * an error message and quit instead of assuming that it is a
1675     * symbol file.
1676     */
1677     for (i=0; i<(signed)sizeof(buf); i++)
1678     if (buf[i] < 32 && buf[i] != '\t' &&
1679     buf[i] != '\n' && buf[i] != '\r' &&
1680     buf[i] != '\f') {
1681     fprintf(stderr, "\nThe file format of '%s' is "
1682     "unknown.\n\n ", filename);
1683     for (i=0; i<(signed)sizeof(buf); i++)
1684     fprintf(stderr, " %02x", buf[i]);
1685 dpavlin 6
1686     if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa)
1687     fprintf(stderr, "\n\nIt has a PC-style "
1688     "bootsector marker.");
1689    
1690 dpavlin 2 fprintf(stderr, "\n\nPossible explanations:\n\n"
1691     " o) If this is a disk image, you forgot '-d' "
1692     "on the command line.\n"
1693     " o) This is an unsupported binary format.\n\n");
1694     exit(1);
1695     }
1696    
1697     symbol_readfile(&machine->symbol_context, filename);
1698    
1699     ret:
1700     debug_indentation(-iadd);
1701     }
1702    

  ViewVC Help
Powered by ViewVC 1.1.26