1 /*
2 * Copyright (C) 2003-2020 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, IRIX, 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 */
file_n_executables_loaded(void)104 int file_n_executables_loaded(void)
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 */
file_load(struct machine * machine,struct memory * mem,char * filename,uint64_t * entrypointp,int arch,uint64_t * gpp,int * byte_orderp,uint64_t * tocp)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
156 old_quiet_mode = quiet_mode;
157 if (verbose < 1)
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);
312 if (machine->machine_type == MACHINE_DREAMCAST &&
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
365 symbol_readfile(&machine->symbol_context, filename);
366
367 ret:
368 debug_indentation(-iadd);
369 quiet_mode = old_quiet_mode;
370 }
371
372