/[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

Contents of /trunk/src/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 6 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 /*
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 * $Id: file.c,v 1.99 2005/06/26 09:21:28 debug Exp $
29 *
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 #define N_ELF_MACHINE_TYPES 64
60 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 "COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */
75 "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */
76 "unknown60", "unknown61", "AMD64", "unknown63" /* 60..63 */
77 };
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 #define AOUT_FLAG_DECOSF1 1
127 #define AOUT_FLAG_FROM_BEGINNING 2
128 /*
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 char *filename, int flags,
139 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 if (flags & AOUT_FLAG_DECOSF1) {
158 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 textsize = ftello(f) - 512;
169 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 if (flags & AOUT_FLAG_FROM_BEGINNING) {
191 fseek(f, 0, SEEK_SET);
192 vaddr &= ~0xfff;
193 }
194
195 /* 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 if (flags & AOUT_FLAG_DECOSF1)
209 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 debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftello(f));
230 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 oldpos = ftello(f);
243 fseek(f, 0, SEEK_END);
244 strings_len = ftello(f) - oldpos;
245 fseek(f, oldpos, SEEK_SET);
246 debug("strings: %i bytes @ 0x%x\n", strings_len,(int)ftello(f));
247 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 *entrypointp = (int32_t)entry;
279
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 oldpos = ftello(f);
478
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 (long long) (ftello(f) - skip), (long long)loadaddr);
904 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 "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 exit(1);
1013 }
1014 if (eshentsize != sizeof(Elf64_Shdr)) {
1015 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 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 "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 exit(1);
1038 }
1039 if (eshentsize != sizeof(Elf32_Shdr)) {
1040 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 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 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 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 case ARCH_X86:
1091 switch (emachine) {
1092 case EM_386:
1093 case EM_486:
1094 *tocp = 1;
1095 ok = 1;
1096 break;
1097 case EM_AMD64:
1098 *tocp = 2;
1099 ok = 1;
1100 break;
1101 }
1102 break;
1103 case ARCH_ARM:
1104 switch (emachine) {
1105 case EM_ARM:
1106 ok = 1;
1107 }
1108 break;
1109 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 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
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 if (addr != 0) /* && ((st_info >> 4) & 0xf)
1443 >= STB_GLOBAL) */ {
1444 /* 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 unsigned char buf2[2];
1548 size_t len, len2, i;
1549 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 size = ftello(f);
1581 fseek(f, 0, SEEK_SET);
1582
1583 memset(buf, 0, sizeof(buf));
1584 len = fread(buf, 1, sizeof(buf), f);
1585 fseek(f, 510, SEEK_SET);
1586 len2 = fread(buf2, 1, sizeof(buf2), f);
1587 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 /* Is it an a.out? */
1603 if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) {
1604 /* MIPS a.out */
1605 file_load_aout(machine, mem, filename, 0,
1606 entrypointp, arch, byte_orderp);
1607 goto ret;
1608 }
1609 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 if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) {
1616 /* DEC OSF1 on MIPS: */
1617 file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1,
1618 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 "image? (Use the -d option.)\n");
1663 exit(1);
1664 }
1665
1666 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 /*
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
1686 if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa)
1687 fprintf(stderr, "\n\nIt has a PC-style "
1688 "bootsector marker.");
1689
1690 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