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