file.cc Source File

Back to the index.

file.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2018 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  * This module contains functions which load executable images into (emulated)
29  * memory. File formats recognized so far are:
30  *
31  * android Android boot.img format
32  * a.out traditional old-style Unix binary format
33  * Mach-O MacOS X format, etc.
34  * ecoff old format used by Ultrix, Windows NT, etc
35  * srec Motorola SREC format
36  * raw raw binaries, "address:[skiplen:[entrypoint:]]filename"
37  * ELF 32-bit and 64-bit ELFs
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 "machine.h"
50 #include "memory.h"
51 #include "misc.h"
52 #include "symbol.h"
53 
54 
55 extern int quiet_mode;
56 extern int verbose;
57 
58 
59 /*
60  * This should be increased by every routine here that actually loads an
61  * executable file into memory. (For example, loading a symbol file should
62  * NOT increase this.)
63  */
64 static int n_executables_loaded = 0;
65 
66 
67 #include "thirdparty/exec_elf.h" /* Ugly; needed for ELFDATA2LSB etc. */
68 
69 #define unencode(var,dataptr,typ) { \
70  int Wi; unsigned char Wb; \
71  unsigned char *Wp = (unsigned char *) dataptr; \
72  int Wlen = sizeof(typ); \
73  var = 0; \
74  for (Wi=0; Wi<Wlen; Wi++) { \
75  if (encoding == ELFDATA2LSB) \
76  Wb = Wp[Wlen-1 - Wi]; \
77  else \
78  Wb = Wp[Wi]; \
79  if (Wi == 0 && (Wb & 0x80)) { \
80  var --; /* set var to -1 :-) */ \
81  var <<= 8; \
82  } \
83  var |= Wb; \
84  if (Wi < Wlen-1) \
85  var <<= 8; \
86  } \
87  }
88 
89 
90 #include "file_android.cc"
91 #include "file_aout.cc"
92 #include "file_ecoff.cc"
93 #include "file_elf.cc"
94 #include "file_macho.cc"
95 #include "file_raw.cc"
96 #include "file_srec.cc"
97 
98 
99 /*
100  * file_n_executables_loaded():
101  *
102  * Returns the number of executable files loaded into emulated memory.
103  */
105 {
106  return n_executables_loaded;
107 }
108 
109 
110 /*
111  * file_load():
112  *
113  * Sense the file format of a file (ELF, a.out, ecoff), and call the
114  * right file_load_XXX() function. If the file isn't of a recognized
115  * binary format, assume that it contains symbol definitions.
116  *
117  * If the filename doesn't exist, try to treat the name as
118  * "address:filename" and load the file as a raw binary.
119  */
120 void file_load(struct machine *machine, struct memory *mem,
121  char *filename, uint64_t *entrypointp,
122  int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp)
123 {
124  int iadd = DEBUG_INDENTATION, old_quiet_mode;
125  FILE *f;
126  const char *tmpdir = getenv("TMPDIR") == NULL?
127  DEFAULT_TMP_DIR : getenv("TMPDIR");
128  unsigned char buf[12];
129  unsigned char buf2[2];
130  char tmpname[400];
131  size_t len, len2, i;
132  off_t size;
133 
134  if (byte_orderp == NULL) {
135  fprintf(stderr, "file_load(): byte_order == NULL\n");
136  exit(1);
137  }
138 
139  if (arch == ARCH_NOARCH) {
140  fprintf(stderr, "file_load(): FATAL ERROR: no arch?\n");
141  exit(1);
142  }
143 
144  if (mem == NULL || filename == NULL) {
145  fprintf(stderr, "file_load(): mem or filename is NULL\n");
146  exit(1);
147  }
148 
149  /* Skip configuration files: */
150  if (filename[0] == '@')
151  return;
152 
153  debug("loading %s%s\n", filename, verbose >= 2? ":" : "");
154  debug_indentation(iadd);
155 
157  if (verbose < 2)
158  quiet_mode = 1;
159 
160  f = fopen(filename, "r");
161  if (f == NULL) {
162  file_load_raw(machine, mem, filename, entrypointp);
163  goto ret;
164  }
165 
166  fseek(f, 0, SEEK_END);
167  size = ftello(f);
168  fseek(f, 0, SEEK_SET);
169 
170  memset(buf, 0, sizeof(buf));
171  len = fread(buf, 1, sizeof(buf), f);
172  fseek(f, 510, SEEK_SET);
173  len2 = fread(buf2, 1, sizeof(buf2), f);
174  fclose(f);
175 
176  if (len < (signed int)sizeof(buf)) {
177  fprintf(stderr, "\nThis file is too small to contain "
178  "anything useful\n");
179  exit(1);
180  }
181 
182  /* Is it an ELF? */
183  if (buf[0] == 0x7f && buf[1]=='E' && buf[2]=='L' && buf[3]=='F') {
184  file_load_elf(machine, mem, filename,
185  entrypointp, arch, gpp, byte_orderp, tocp);
186  goto ret;
187  }
188 
189  /* Is it an Android boot.img? */
190  if (memcmp("ANDROID!", &buf[0], 8) == 0) {
191  file_load_android(machine, mem, filename, 0,
192  entrypointp, arch, byte_orderp);
193  goto ret;
194  }
195 
196  /* Is it an a.out? */
197  if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) {
198  /* MIPS a.out */
199  file_load_aout(machine, mem, filename, 0,
200  entrypointp, arch, byte_orderp);
201  goto ret;
202  }
203  if (buf[0]==0x00 && buf[1]==0x87 && buf[2]==0x01 && buf[3]==0x08) {
204  /* M68K a.out */
205  file_load_aout(machine, mem, filename,
206  AOUT_FLAG_VADDR_ZERO_HACK /* for OpenBSD/mac68k */,
207  entrypointp, arch, byte_orderp);
208  goto ret;
209  }
210  if (buf[0]==0x00 && buf[1]==0x99 && buf[2]==0x01 && buf[3]==0x0b) {
211  /* OpenBSD/M88K a.out */
212  file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING,
213  entrypointp, arch, byte_orderp);
214  goto ret;
215  }
216  if (buf[0]==0x00 && buf[1]==0x8f && buf[2]==0x01 && buf[3]==0x0b) {
217  /* ARM a.out */
218  file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING,
219  entrypointp, arch, byte_orderp);
220  goto ret;
221  }
222  if (buf[0]==0x00 && buf[1]==0x86 && buf[2]==0x01 && buf[3]==0x0b) {
223  /* i386 a.out (old OpenBSD and NetBSD etc) */
224  file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING,
225  entrypointp, arch, byte_orderp);
226  goto ret;
227  }
228  if (buf[0]==0x01 && buf[1]==0x03 && buf[2]==0x01 && buf[3]==0x07) {
229  /* SPARC a.out (old 32-bit NetBSD etc) */
230  file_load_aout(machine, mem, filename, AOUT_FLAG_NO_SIZES,
231  entrypointp, arch, byte_orderp);
232  goto ret;
233  }
234  if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) {
235  /* DEC OSF1 on MIPS: */
236  file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1,
237  entrypointp, arch, byte_orderp);
238  goto ret;
239  }
240 
241  /*
242  * Is it a Mach-O file?
243  */
244  if (buf[0] == 0xfe && buf[1] == 0xed && buf[2] == 0xfa &&
245  (buf[3] == 0xce || buf[3] == 0xcf)) {
246  file_load_macho(machine, mem, filename, entrypointp,
247  arch, byte_orderp, buf[3] == 0xcf, 0);
248  goto ret;
249  }
250  if ((buf[0] == 0xce || buf[0] == 0xcf) && buf[1] == 0xfa &&
251  buf[2] == 0xed && buf[3] == 0xfe) {
252  file_load_macho(machine, mem, filename, entrypointp,
253  arch, byte_orderp, buf[0] == 0xcf, 1);
254  goto ret;
255  }
256 
257  /*
258  * Is it an ecoff?
259  *
260  * TODO: What's the deal with the magic value's byte order? Sometimes
261  * it seems to be reversed for BE when compared to LE, but not always?
262  */
263  if (buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB ||
264  buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL ||
265  buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB2 ||
266  buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL2 ||
267  buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB3 ||
268  buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL3 ||
269  buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB ||
270  buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL ||
271  buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB2 ||
272  buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL2 ||
273  buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB3 ||
274  buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL3) {
275  file_load_ecoff(machine, mem, filename, entrypointp,
276  arch, gpp, byte_orderp);
277  goto ret;
278  }
279 
280  /* Is it a Motorola SREC file? */
281  if ((buf[0]=='S' && buf[1]>='0' && buf[1]<='9')) {
282  file_load_srec(machine, mem, filename, entrypointp);
283  goto ret;
284  }
285 
286  /* gzipped files are not supported: */
287  if (buf[0]==0x1f && buf[1]==0x8b) {
288  fprintf(stderr, "\nYou need to gunzip the file before you"
289  " try to use it.\n");
290  exit(1);
291  }
292 
293  if (size > 24000000) {
294  fprintf(stderr, "\nThis file is very large (%lli bytes)\n",
295  (long long)size);
296  fprintf(stderr, "Are you sure it is a kernel and not a disk "
297  "image? (Use the -d option.)\n");
298  exit(1);
299  }
300 
301  if (size == 1474560)
302  fprintf(stderr, "Hm... this file is the size of a 1.44 MB "
303  "floppy image. Maybe you forgot the\n-d switch?\n");
304 
305  /*
306  * Ugly hack for Dreamcast: When booting from a Dreamcast CDROM
307  * image, a temporary file is extracted into /tmp/gxemul.*, but this
308  * is a "scrambled" raw binary. This code unscrambles it, and loads
309  * it as a raw binary.
310  */
311  snprintf(tmpname, sizeof(tmpname), "%s/gxemul.", tmpdir);
313  strncmp(filename, tmpname, strlen(tmpname)) == 0) {
314  char *tmp_filename = (char *) malloc(strlen(filename) + 100);
315  snprintf(tmp_filename, strlen(filename) + 100,
316  "%s.descrambled", filename);
317  debug("descrambling into %s\n", tmp_filename);
318  dreamcast_descramble(filename, tmp_filename);
319 
320  snprintf(tmp_filename, strlen(filename) + 100,
321  "0x8c010000:%s.descrambled", filename);
322  debug("loading descrambled Dreamcast binary\n");
323  file_load_raw(machine, mem, tmp_filename, entrypointp);
324 
325  snprintf(tmp_filename, strlen(filename) + 100,
326  "%s.descrambled", filename);
327  remove(tmp_filename);
328  free(tmp_filename);
329 
330  /* Hack: Start a "boot from CDROM" sequence: */
331  *entrypointp = 0x8c000140;
332  goto ret;
333  }
334 
335  /*
336  * Last resort: symbol definitions from nm (or nm -S):
337  *
338  * If the buf contains typical 'binary' characters, then print
339  * an error message and quit instead of assuming that it is a
340  * symbol file.
341  */
342  for (i=0; i<(signed)sizeof(buf); i++)
343  if (buf[i] < 32 && buf[i] != '\t' &&
344  buf[i] != '\n' && buf[i] != '\r' &&
345  buf[i] != '\f') {
346  fprintf(stderr, "\nThe file format of '%s' is "
347  "unknown.\n\n ", filename);
348  for (i=0; i<(signed)sizeof(buf); i++)
349  fprintf(stderr, " %02x", buf[i]);
350 
351  if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa)
352  fprintf(stderr, "\n\nIt has a PC-style "
353  "bootsector marker.");
354 
355  fprintf(stderr, "\n\nPossible explanations:\n\n"
356  " o) If this is a disk image, you forgot '-d' "
357  "on the command line.\n"
358  " o) You are attempting to load a raw binary "
359  "into emulated memory,\n"
360  " but forgot to add the address prefix.\n"
361  " o) This is an unsupported binary format.\n\n");
362  exit(1);
363  }
364 
366 
367 ret:
368  debug_indentation(-iadd);
370 }
371 
AOUT_FLAG_NO_SIZES
#define AOUT_FLAG_NO_SIZES
Definition: file_aout.cc:40
file_load
void file_load(struct machine *machine, struct memory *mem, char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp)
Definition: file.cc:120
ECOFF_MAGIC_MIPSEL2
#define ECOFF_MAGIC_MIPSEL2
Definition: exec_ecoff_mips.h:66
file_ecoff.cc
f
void f(int s, int func, int only_name)
Definition: generate_arm_r.c:45
ECOFF_MAGIC_MIPSEB2
#define ECOFF_MAGIC_MIPSEB2
Definition: exec_ecoff_mips.h:65
file_n_executables_loaded
int file_n_executables_loaded(void)
Definition: file.cc:104
machine::symbol_context
struct symbol_context symbol_context
Definition: machine.h:144
memory
Definition: memory.h:75
debug
#define debug
Definition: dev_adb.cc:57
ECOFF_MAGIC_MIPSEL
#define ECOFF_MAGIC_MIPSEL
Definition: exec_ecoff_mips.h:64
file_aout.cc
verbose
int verbose
Definition: main.cc:77
dreamcast_descramble
void dreamcast_descramble(char *from, char *to)
Definition: dreamcast_scramble.cc:190
MACHINE_DREAMCAST
#define MACHINE_DREAMCAST
Definition: machine.h:251
AOUT_FLAG_DECOSF1
#define AOUT_FLAG_DECOSF1
Definition: file_aout.cc:37
exec_elf.h
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2686
misc.h
machine.h
machine
Definition: machine.h:97
file_android.cc
AOUT_FLAG_VADDR_ZERO_HACK
#define AOUT_FLAG_VADDR_ZERO_HACK
Definition: file_aout.cc:39
symbol.h
cpu.h
file_elf.cc
ARCH_NOARCH
#define ARCH_NOARCH
Definition: machine.h:202
file_raw.cc
ECOFF_MAGIC_MIPSEB3
#define ECOFF_MAGIC_MIPSEB3
Definition: exec_ecoff_mips.h:67
file_macho.cc
quiet_mode
int quiet_mode
Definition: main.cc:78
machine::machine_type
int machine_type
Definition: machine.h:111
AOUT_FLAG_FROM_BEGINNING
#define AOUT_FLAG_FROM_BEGINNING
Definition: file_aout.cc:38
DEBUG_INDENTATION
#define DEBUG_INDENTATION
Definition: misc.h:212
DEFAULT_TMP_DIR
#define DEFAULT_TMP_DIR
Definition: misc.h:148
file_srec.cc
ECOFF_MAGIC_MIPSEL3
#define ECOFF_MAGIC_MIPSEL3
Definition: exec_ecoff_mips.h:68
old_quiet_mode
int old_quiet_mode
Definition: debugger.cc:76
ECOFF_MAGIC_MIPSEB
#define ECOFF_MAGIC_MIPSEB
Definition: exec_ecoff_mips.h:63
memory.h
debug_indentation
void debug_indentation(int diff)
Definition: main.cc:120
symbol_readfile
void symbol_readfile(struct symbol_context *, char *fname)
Definition: symbol.cc:284

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18