/[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 12 - (hide annotations)
Mon Oct 8 16:18:38 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 48299 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26