/[gxemul]/trunk/src/file/file_macho.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/file_macho.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 8639 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


1 /*
2 * Copyright (C) 2005-2007 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_macho.c,v 1.1 2007/04/10 16:33:44 debug Exp $
29 *
30 * Mach-O file support.
31 */
32
33 /* Note: Included from file.c. */
34
35
36 /*
37 * file_load_macho():
38 *
39 * Loads a Mach-O binary image into the emulated memory. The entry point
40 * is stored in the specified CPU's registers.
41 *
42 * TODO:
43 *
44 * o) Almost everything.
45 *
46 * o) I haven't had time to look into whether Apple's open source
47 * license is BSD-compatible or not. Perhaps it would be possible
48 * to use a header file containing symbolic names, and not use
49 * hardcoded values.
50 */
51 static void file_load_macho(struct machine *m, struct memory *mem,
52 char *filename, uint64_t *entrypointp, int arch, int *byte_orderp,
53 int is_64bit, int is_reversed)
54 {
55 FILE *f;
56 uint64_t entry = 0;
57 int entry_set = 0;
58 int encoding = ELFDATA2MSB;
59 unsigned char buf[65536];
60 char *symbols, *strings;
61 uint32_t cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags;
62 uint64_t vmaddr, vmsize, fileoff, filesize;
63 int cmd_type, cmd_len, i, flavor;
64 int32_t symoff, nsyms, stroff, strsize;
65 size_t len, pos;
66
67 if (m->cpus[0]->byte_order == EMUL_BIG_ENDIAN)
68 encoding = ELFDATA2MSB;
69
70 f = fopen(filename, "r");
71 if (f == NULL) {
72 perror(filename);
73 exit(1);
74 }
75
76 if (is_64bit) {
77 fatal("TODO: 64-bit Mach-O. Not supported yet.\n");
78 exit(1);
79 }
80 if (is_reversed) {
81 fatal("TODO: Reversed-endianness. Not supported yet.\n");
82 exit(1);
83 }
84
85 len = fread(buf, 1, sizeof(buf), f);
86 if (len < 100) {
87 fatal("Bad Mach-O file?\n");
88 exit(1);
89 }
90
91 unencode(cputype, &buf[4], uint32_t);
92 unencode(cpusubtype, &buf[8], uint32_t);
93 unencode(filetype, &buf[12], uint32_t);
94 unencode(ncmds, &buf[16], uint32_t);
95 unencode(sizeofcmds, &buf[20], uint32_t);
96 unencode(flags, &buf[24], uint32_t);
97
98 /* debug("cputype=0x%x cpusubtype=0x%x filetype=0x%x\n",
99 cputype, cpusubtype, filetype);
100 debug("ncmds=%i sizeofcmds=0x%08x flags=0x%08x\n",
101 ncmds, sizeofcmds, flags); */
102
103 /*
104 * Compare to "normal" values.
105 * NOTE/TODO: These were for a Darwin (Macintosh PPC) kernel.
106 */
107 if (cputype != 0x12) {
108 fatal("Error: Unimplemented cputype 0x%x\n", cputype);
109 exit(1);
110 }
111 if (cpusubtype != 0) {
112 fatal("Error: Unimplemented cpusubtype 0x%x\n", cpusubtype);
113 exit(1);
114 }
115 /* Filetype 2 means an executable image. */
116 if (filetype != 2) {
117 fatal("Error: Unimplemented filetype 0x%x\n", filetype);
118 exit(1);
119 }
120 if (!(flags & 1)) {
121 fatal("Error: File has 'undefined references'. Cannot"
122 " be executed.\n", flags);
123 exit(1);
124 }
125
126 /* I've only encountered flags == 1 so far. */
127 if (flags != 1) {
128 fatal("Error: Unimplemented flags 0x%x\n", flags);
129 exit(1);
130 }
131
132 /*
133 * Read all load commands:
134 */
135 pos = is_64bit? 32 : 28;
136 cmd_type = 0;
137 do {
138 /* Read command type and length: */
139 unencode(cmd_type, &buf[pos], uint32_t);
140 unencode(cmd_len, &buf[pos+4], uint32_t);
141
142 #if 0
143 debug("cmd %i, len=%i\n", cmd_type, cmd_len);
144 for (i=8; i<cmd_len; i++) {
145 unsigned char ch = buf[pos+i];
146 if (ch >= ' ' && ch < 127)
147 debug("%c", ch);
148 else
149 debug(".");
150 }
151 #endif
152 switch (cmd_type) {
153 case 1: /* LC_SEGMENT */
154 debug("seg ");
155 for (i=0; i<16; i++) {
156 if (buf[pos + 8 + i] == 0)
157 break;
158 debug("%c", buf[pos + 8 + i]);
159 }
160 unencode(vmaddr, &buf[pos+8+16+0], uint32_t);
161 unencode(vmsize, &buf[pos+8+16+4], uint32_t);
162 unencode(fileoff, &buf[pos+8+16+8], uint32_t);
163 unencode(filesize, &buf[pos+8+16+12], uint32_t);
164 debug(": vmaddr=0x%x size=0x%x fileoff=0x%x",
165 (int)vmaddr, (int)vmsize, (int)fileoff);
166
167 if (filesize == 0) {
168 debug("\n");
169 break;
170 }
171
172 fseek(f, fileoff, SEEK_SET);
173
174 /* Load data from the file: */
175 while (filesize != 0) {
176 unsigned char buf[32768];
177 ssize_t len = filesize > sizeof(buf) ?
178 sizeof(buf) : filesize;
179 len = fread(buf, 1, len, f);
180
181 /* printf("fread len=%i vmaddr=%x buf[0..]="
182 "%02x %02x %02x\n", (int)len, (int)vmaddr,
183 buf[0], buf[1], buf[2]); */
184
185 if (len > 0) {
186 int len2 = 0;
187 uint64_t vaddr1 = vmaddr &
188 ((1 << BITS_PER_MEMBLOCK) - 1);
189 uint64_t vaddr2 = (vmaddr +
190 len) & ((1 << BITS_PER_MEMBLOCK)-1);
191 if (vaddr2 < vaddr1) {
192 len2 = len - vaddr2;
193 m->cpus[0]->memory_rw(m->cpus[
194 0], mem, vmaddr, &buf[0],
195 len2, MEM_WRITE,
196 NO_EXCEPTIONS);
197 }
198 m->cpus[0]->memory_rw(m->cpus[0], mem,
199 vmaddr + len2, &buf[len2], len-len2,
200 MEM_WRITE, NO_EXCEPTIONS);
201 } else {
202 fprintf(stderr, "error reading\n");
203 exit(1);
204 }
205
206 vmaddr += len;
207 filesize -= len;
208 }
209
210 debug("\n");
211 break;
212
213 case 2: /* LC_SYMTAB */
214 unencode(symoff, &buf[pos+8], uint32_t);
215 unencode(nsyms, &buf[pos+12], uint32_t);
216 unencode(stroff, &buf[pos+16], uint32_t);
217 unencode(strsize, &buf[pos+20], uint32_t);
218 debug("symtable: %i symbols @ 0x%x (strings at "
219 "0x%x)\n", nsyms, symoff, stroff);
220
221 symbols = malloc(12 * nsyms);
222 if (symbols == NULL) {
223 fprintf(stderr, "out of memory\n");
224 exit(1);
225 }
226 fseek(f, symoff, SEEK_SET);
227 fread(symbols, 1, 12 * nsyms, f);
228
229 strings = malloc(strsize);
230 if (strings == NULL) {
231 fprintf(stderr, "out of memory\n");
232 exit(1);
233 }
234 fseek(f, stroff, SEEK_SET);
235 fread(strings, 1, strsize, f);
236
237 for (i=0; i<nsyms; i++) {
238 int n_strx, n_type, n_sect, n_desc;
239 uint32_t n_value;
240 unencode(n_strx, &symbols[i*12+0], int32_t);
241 unencode(n_type, &symbols[i*12+4], uint8_t);
242 unencode(n_sect, &symbols[i*12+5], uint8_t);
243 unencode(n_desc, &symbols[i*12+6], int16_t);
244 unencode(n_value, &symbols[i*12+8], uint32_t);
245 /* debug("%i: strx=%i type=%i sect=%i desc=%i"
246 " value=0x%x\n", i, n_strx, n_type,
247 n_sect, n_desc, n_value); */
248 add_symbol_name(&m->symbol_context,
249 n_value, 0, strings + n_strx, 0, -1);
250 }
251
252 free(symbols);
253 free(strings);
254 break;
255
256 case 5: debug("unix thread context: ");
257 /* See http://cvs.sf.net/viewcvs.py/hte/
258 HT%20Editor/machostruc.h or similar for details
259 on the thread struct. */
260 unencode(flavor, &buf[pos+8], uint32_t);
261 if (flavor != 1) {
262 fatal("unimplemented flavor %i\n", flavor);
263 exit(1);
264 }
265
266 if (arch != ARCH_PPC) {
267 fatal("non-PPC arch? TODO\n");
268 exit(1);
269 }
270
271 unencode(entry, &buf[pos+16], uint32_t);
272 entry_set = 1;
273 debug("pc=0x%x\n", (int)entry);
274
275 for (i=1; i<40; i++) {
276 uint32_t x;
277 unencode(x, &buf[pos+16+i*4], uint32_t);
278 if (x != 0) {
279 fatal("Entry nr %i in the Mach-O"
280 " thread struct is non-zero"
281 " (0x%x). This is not supported"
282 " yet. TODO\n", i, x);
283 exit(1);
284 }
285 }
286 break;
287
288 default:fatal("WARNING! Unimplemented load command %i!\n",
289 cmd_type);
290 }
291
292 pos += cmd_len;
293 } while (pos < sizeofcmds && cmd_type != 0);
294
295 fclose(f);
296
297 if (!entry_set) {
298 fatal("No entry point? Aborting.\n");
299 exit(1);
300 }
301
302 *entrypointp = entry;
303
304 if (encoding == ELFDATA2LSB)
305 *byte_orderp = EMUL_LITTLE_ENDIAN;
306 else
307 *byte_orderp = EMUL_BIG_ENDIAN;
308
309 n_executables_loaded ++;
310 }
311

  ViewVC Help
Powered by ViewVC 1.1.26