|
|
1.1 root 1: /*
2: * Mach-O object file loading
3: *
4: * Copyright (c) 2006 Pierre d'Herbemont
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
1.1.1.3 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
19: #include <stdio.h>
20: #include <sys/types.h>
21: #include <fcntl.h>
22: #include <sys/stat.h>
23: #include <errno.h>
24: #include <unistd.h>
25: #include <sys/mman.h>
26: #include <stdlib.h>
27: #include <string.h>
28:
29: #include "qemu.h"
30: #include "disas.h"
31:
32: #include <mach-o/loader.h>
33: #include <mach-o/fat.h>
34: #include <mach-o/nlist.h>
35: #include <mach-o/reloc.h>
36: #include <mach-o/ppc/reloc.h>
37:
38: //#define DEBUG_MACHLOAD
39:
40: #ifdef DEBUG_MACHLOAD
1.1.1.2 root 41: # define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
1.1 root 42: #else
1.1.1.2 root 43: # define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
1.1 root 44: #endif
45:
46: # define check_mach_header(x) (x.magic == MH_CIGAM)
47:
48: extern const char *interp_prefix;
49:
50: /* we don't have a good implementation for this */
51: #define DONT_USE_DYLD_SHARED_MAP
52:
53: /* Pass extra arg to DYLD for debug */
54: //#define ACTIVATE_DYLD_TRACE
55:
56: //#define OVERRIDE_DYLINKER
57:
58: #ifdef OVERRIDE_DYLINKER
59: # ifdef TARGET_I386
60: # define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
61: # else
62: # define DYLINKER_NAME "/usr/lib/dyld"
63: # endif
64: #endif
65:
66: /* XXX: in an include */
67: struct nlist_extended
68: {
69: union {
70: char *n_name;
71: long n_strx;
72: } n_un;
73: unsigned char n_type;
74: unsigned char n_sect;
75: short st_desc;
76: unsigned long st_value;
77: unsigned long st_size;
78: };
79:
80: /* Print symbols in gdb */
81: void *macho_text_sect = 0;
82: int macho_offset = 0;
83:
84: int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
1.1.1.4 root 85:
1.1 root 86: #ifdef TARGET_I386
87: typedef struct mach_i386_thread_state {
88: unsigned int eax;
89: unsigned int ebx;
90: unsigned int ecx;
91: unsigned int edx;
92: unsigned int edi;
93: unsigned int esi;
94: unsigned int ebp;
95: unsigned int esp;
96: unsigned int ss;
97: unsigned int eflags;
98: unsigned int eip;
99: unsigned int cs;
100: unsigned int ds;
101: unsigned int es;
102: unsigned int fs;
103: unsigned int gs;
104: } mach_i386_thread_state_t;
105:
106: void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
107: {
108: bswap32s((uint32_t*)&ts->eax);
109: bswap32s((uint32_t*)&ts->ebx);
110: bswap32s((uint32_t*)&ts->ecx);
111: bswap32s((uint32_t*)&ts->edx);
112: bswap32s((uint32_t*)&ts->edi);
113: bswap32s((uint32_t*)&ts->esi);
114: bswap32s((uint32_t*)&ts->ebp);
115: bswap32s((uint32_t*)&ts->esp);
116: bswap32s((uint32_t*)&ts->ss);
117: bswap32s((uint32_t*)&ts->eflags);
118: bswap32s((uint32_t*)&ts->eip);
119: bswap32s((uint32_t*)&ts->cs);
120: bswap32s((uint32_t*)&ts->ds);
121: bswap32s((uint32_t*)&ts->es);
122: bswap32s((uint32_t*)&ts->fs);
123: bswap32s((uint32_t*)&ts->gs);
124: }
125: #define target_thread_state mach_i386_thread_state
126: #define TARGET_CPU_TYPE CPU_TYPE_I386
127: #define TARGET_CPU_NAME "i386"
128: #endif
129:
130: #ifdef TARGET_PPC
131: struct mach_ppc_thread_state {
132: unsigned int srr0; /* Instruction address register (PC) */
133: unsigned int srr1; /* Machine state register (supervisor) */
134: unsigned int r0;
135: unsigned int r1;
136: unsigned int r2;
137: unsigned int r3;
138: unsigned int r4;
139: unsigned int r5;
140: unsigned int r6;
141: unsigned int r7;
142: unsigned int r8;
143: unsigned int r9;
144: unsigned int r10;
145: unsigned int r11;
146: unsigned int r12;
147: unsigned int r13;
148: unsigned int r14;
149: unsigned int r15;
150: unsigned int r16;
151: unsigned int r17;
152: unsigned int r18;
153: unsigned int r19;
154: unsigned int r20;
155: unsigned int r21;
156: unsigned int r22;
157: unsigned int r23;
158: unsigned int r24;
159: unsigned int r25;
160: unsigned int r26;
161: unsigned int r27;
162: unsigned int r28;
163: unsigned int r29;
164: unsigned int r30;
165: unsigned int r31;
166:
167: unsigned int cr; /* Condition register */
168: unsigned int xer; /* User's integer exception register */
169: unsigned int lr; /* Link register */
170: unsigned int ctr; /* Count register */
171: unsigned int mq; /* MQ register (601 only) */
172:
173: unsigned int vrsave; /* Vector Save Register */
174: };
175:
176: void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
177: {
178: bswap32s((uint32_t*)&ts->srr0);
179: bswap32s((uint32_t*)&ts->srr1);
180: bswap32s((uint32_t*)&ts->r0);
181: bswap32s((uint32_t*)&ts->r1);
182: bswap32s((uint32_t*)&ts->r2);
183: bswap32s((uint32_t*)&ts->r3);
184: bswap32s((uint32_t*)&ts->r4);
185: bswap32s((uint32_t*)&ts->r5);
186: bswap32s((uint32_t*)&ts->r6);
187: bswap32s((uint32_t*)&ts->r7);
188: bswap32s((uint32_t*)&ts->r8);
189: bswap32s((uint32_t*)&ts->r9);
190: bswap32s((uint32_t*)&ts->r10);
191: bswap32s((uint32_t*)&ts->r11);
192: bswap32s((uint32_t*)&ts->r12);
193: bswap32s((uint32_t*)&ts->r13);
194: bswap32s((uint32_t*)&ts->r14);
195: bswap32s((uint32_t*)&ts->r15);
196: bswap32s((uint32_t*)&ts->r16);
197: bswap32s((uint32_t*)&ts->r17);
198: bswap32s((uint32_t*)&ts->r18);
199: bswap32s((uint32_t*)&ts->r19);
200: bswap32s((uint32_t*)&ts->r20);
201: bswap32s((uint32_t*)&ts->r21);
202: bswap32s((uint32_t*)&ts->r22);
203: bswap32s((uint32_t*)&ts->r23);
204: bswap32s((uint32_t*)&ts->r24);
205: bswap32s((uint32_t*)&ts->r25);
206: bswap32s((uint32_t*)&ts->r26);
207: bswap32s((uint32_t*)&ts->r27);
208: bswap32s((uint32_t*)&ts->r28);
209: bswap32s((uint32_t*)&ts->r29);
210: bswap32s((uint32_t*)&ts->r30);
211: bswap32s((uint32_t*)&ts->r31);
212:
213: bswap32s((uint32_t*)&ts->cr);
214: bswap32s((uint32_t*)&ts->xer);
215: bswap32s((uint32_t*)&ts->lr);
216: bswap32s((uint32_t*)&ts->ctr);
217: bswap32s((uint32_t*)&ts->mq);
218:
219: bswap32s((uint32_t*)&ts->vrsave);
220: }
221:
222: #define target_thread_state mach_ppc_thread_state
223: #define TARGET_CPU_TYPE CPU_TYPE_POWERPC
224: #define TARGET_CPU_NAME "PowerPC"
225: #endif
226:
227: struct target_thread_command {
228: unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */
229: unsigned long cmdsize; /* total size of this command */
230: unsigned long flavor; /* flavor of thread state */
231: unsigned long count; /* count of longs in thread state */
232: struct target_thread_state state; /* thread state for this flavor */
233: };
234:
235: void bswap_tc(struct target_thread_command *tc)
236: {
237: bswap32s((uint32_t*)(&tc->flavor));
238: bswap32s((uint32_t*)&tc->count);
239: #if defined(TARGET_I386)
240: bswap_i386_thread_state(&tc->state);
241: #elif defined(TARGET_PPC)
242: bswap_ppc_thread_state(&tc->state);
243: #else
244: # error unknown TARGET_CPU_TYPE
245: #endif
246: }
247:
248: void bswap_mh(struct mach_header *mh)
249: {
250: bswap32s((uint32_t*)(&mh->magic));
251: bswap32s((uint32_t*)&mh->cputype);
252: bswap32s((uint32_t*)&mh->cpusubtype);
253: bswap32s((uint32_t*)&mh->filetype);
254: bswap32s((uint32_t*)&mh->ncmds);
255: bswap32s((uint32_t*)&mh->sizeofcmds);
256: bswap32s((uint32_t*)&mh->flags);
257: }
258:
259: void bswap_lc(struct load_command *lc)
260: {
261: bswap32s((uint32_t*)&lc->cmd);
262: bswap32s((uint32_t*)&lc->cmdsize);
263: }
264:
265:
266: void bswap_fh(struct fat_header *fh)
267: {
268: bswap32s((uint32_t*)&fh->magic);
269: bswap32s((uint32_t*)&fh->nfat_arch);
270: }
271:
272: void bswap_fa(struct fat_arch *fa)
273: {
274: bswap32s((uint32_t*)&fa->cputype);
275: bswap32s((uint32_t*)&fa->cpusubtype);
276: bswap32s((uint32_t*)&fa->offset);
277: bswap32s((uint32_t*)&fa->size);
278: bswap32s((uint32_t*)&fa->align);
279: }
280:
281: void bswap_segcmd(struct segment_command *sc)
282: {
283: bswap32s((uint32_t*)&sc->vmaddr);
284: bswap32s((uint32_t*)&sc->vmsize);
285: bswap32s((uint32_t*)&sc->fileoff);
286: bswap32s((uint32_t*)&sc->filesize);
287: bswap32s((uint32_t*)&sc->maxprot);
288: bswap32s((uint32_t*)&sc->initprot);
289: bswap32s((uint32_t*)&sc->nsects);
290: bswap32s((uint32_t*)&sc->flags);
291: }
292:
293: void bswap_symtabcmd(struct symtab_command *stc)
294: {
295: bswap32s((uint32_t*)&stc->cmd);
296: bswap32s((uint32_t*)&stc->cmdsize);
297: bswap32s((uint32_t*)&stc->symoff);
298: bswap32s((uint32_t*)&stc->nsyms);
299: bswap32s((uint32_t*)&stc->stroff);
300: bswap32s((uint32_t*)&stc->strsize);
301: }
302:
303: void bswap_sym(struct nlist *n)
304: {
305: bswap32s((uint32_t*)&n->n_un.n_strx);
306: bswap16s((uint16_t*)&n->n_desc);
307: bswap32s((uint32_t*)&n->n_value);
308: }
309:
310: int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap)
311: {
312: int entry;
313: if(need_bswap)
314: bswap_tc(tc);
315: #if defined(TARGET_I386)
316: entry = tc->state.eip;
317: DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n",
318: tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
319: tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
320: tc->state.fs, tc->state.gs );
321: #define reg_copy(reg) regs->reg = tc->state.reg
322: if(regs)
323: {
324: reg_copy(eax);
325: reg_copy(ebx);
326: reg_copy(ecx);
327: reg_copy(edx);
328:
329: reg_copy(edi);
330: reg_copy(esi);
331:
332: reg_copy(ebp);
333: reg_copy(esp);
334:
335: reg_copy(eflags);
336: reg_copy(eip);
337: /*
338: reg_copy(ss);
339: reg_copy(cs);
340: reg_copy(ds);
341: reg_copy(es);
342: reg_copy(fs);
343: reg_copy(gs);*/
344: }
345: #undef reg_copy
346: #elif defined(TARGET_PPC)
347: entry = tc->state.srr0;
348: #endif
349: DPRINTF("load_thread: entry 0x%x\n", entry);
350: return entry;
351: }
352:
353: int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
354: {
355: int size;
356: char * dylinker_name;
357: size = dc->cmdsize - sizeof(struct dylinker_command);
358:
359: if(need_bswap)
360: dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
361: else
362: dylinker_name = (char*)((dc->name.offset)+(int)dc);
363:
364: #ifdef OVERRIDE_DYLINKER
365: dylinker_name = DYLINKER_NAME;
366: #else
367: if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
368: qerror("can't allocate the new dylinker name\n");
369: #endif
370:
371: DPRINTF("dylinker_name %s\n", dylinker_name);
372: return load_object(dylinker_name, NULL, NULL);
373: }
374:
375: int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
376: {
377: unsigned long addr = sc->vmaddr;
378: unsigned long size = sc->filesize;
379: unsigned long error = 0;
380:
381: if(need_bswap)
382: bswap_segcmd(sc);
383:
384: if(sc->vmaddr == 0)
385: {
386: DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
387: return -1;
388: }
389:
390: if (strcmp(sc->segname, "__PAGEZERO") == 0)
391: {
392: DPRINTF("load_segment: __PAGEZERO returning\n");
393: return -1;
394: }
395:
396: /* Right now mmap memory */
397: /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
398: DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
399:
400: if(sc->filesize > 0)
401: {
402: int opt = 0;
403:
404: if(fixed)
405: opt |= MAP_FIXED;
406:
407: DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
408:
409: addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff);
410:
411: if(addr==-1)
412: qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
413:
414: error = addr-sc->vmaddr;
415: }
416: else
417: {
418: addr = sc->vmaddr+slide;
419: error = slide;
420: }
421:
422: if(sc->vmsize > sc->filesize)
423: {
424: addr += sc->filesize;
425: size = sc->vmsize-sc->filesize;
426: addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
427: if(addr==-1)
428: qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
429: }
430:
431: return error;
432: }
433:
434: void *load_data(int fd, long offset, unsigned int size)
435: {
436: char *data;
437:
438: data = malloc(size);
439: if (!data)
440: return NULL;
441: lseek(fd, offset, SEEK_SET);
442: if (read(fd, data, size) != size) {
443: free(data);
444: return NULL;
445: }
446: return data;
447: }
448:
449: /* load a mach-o object file */
450: int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
451: {
452: int need_bswap = 0;
453: int entry_point = 0;
454: int dyld_entry_point = 0;
455: int slide, mmapfixed;
456: int fd;
457: struct load_command *lcmds, *lc;
458: int is_fat = 0;
459: unsigned int i, magic;
460: int mach_hdr_pos = 0;
461: struct mach_header mach_hdr;
462:
463: /* for symbol lookup whith -d flag. */
464: struct symtab_command * symtabcmd = 0;
465: struct nlist_extended *symtab, *sym;
466: struct nlist *symtab_std, *syment;
467: char *strtab;
468:
469: fd = open(filename, O_RDONLY);
470: if (fd < 0)
471: qerror("can't open file '%s'", filename);
472:
473: /* Read magic header. */
474: if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
475: qerror("unable to read Magic of '%s'", filename);
476:
477: /* Check Mach identification. */
478: if(magic == MH_MAGIC)
479: {
480: is_fat = 0;
481: need_bswap = 0;
482: } else if (magic == MH_CIGAM)
483: {
484: is_fat = 0;
485: need_bswap = 1;
486: } else if (magic == FAT_MAGIC)
487: {
488: is_fat = 1;
489: need_bswap = 0;
490: } else if (magic == FAT_CIGAM)
491: {
492: is_fat = 1;
493: need_bswap = 1;
494: }
495: else
496: qerror("Not a Mach-O file.", filename);
497:
498: DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
499: if(is_fat)
500: {
501: int found = 0;
502: struct fat_header fh;
503: struct fat_arch *fa;
504:
505: lseek(fd, 0, SEEK_SET);
506:
507: /* Read Fat header. */
508: if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
509: qerror("unable to read file header");
510:
511: if(need_bswap)
512: bswap_fh(&fh);
513:
514: /* Read Fat Arch. */
515: fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
516:
517: if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
518: qerror("unable to read file header");
519:
520: for( i = 0; i < fh.nfat_arch; i++, fa++)
521: {
522: if(need_bswap)
523: bswap_fa(fa);
524: if(fa->cputype == TARGET_CPU_TYPE)
525: {
526: mach_hdr_pos = fa->offset;
527: lseek(fd, mach_hdr_pos, SEEK_SET);
528:
529: /* Read Mach header. */
530:
531: if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
532: qerror("unable to read file header");
533:
534: if(mach_hdr.magic == MH_MAGIC)
535: need_bswap = 0;
536: else if (mach_hdr.magic == MH_CIGAM)
537: need_bswap = 1;
538: else
539: qerror("Invalid mach header in Fat Mach-O File");
540: found = 1;
541: break;
542: }
543: }
544: if(!found)
545: qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
546: }
547: else
548: {
549: lseek(fd, 0, SEEK_SET);
550: /* Read Mach header */
551: if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
552: qerror("%s: unable to read file header", filename);
553: }
554:
555: if(need_bswap)
556: bswap_mh(&mach_hdr);
557:
558: if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
559: qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
560:
561:
562: switch(mach_hdr.filetype)
563: {
564: case MH_EXECUTE: break;
565: case MH_FVMLIB:
566: case MH_DYLIB:
567: case MH_DYLINKER: break;
568: default:
569: qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
570: }
571:
572: /* read segment headers */
573: lcmds = malloc(mach_hdr.sizeofcmds);
574:
575: if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
576: qerror("%s: unable to read load_command", filename);
577: slide = 0;
578: mmapfixed = 0;
579: for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
580: {
581:
582: if(need_bswap)
583: bswap_lc(lc);
584: switch(lc->cmd)
585: {
586: case LC_SEGMENT:
587: /* The main_exe can't be relocated */
588: if(mach_hdr.filetype == MH_EXECUTE)
589: mmapfixed = 1;
590:
591: slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
592:
593: /* other segment must be mapped according to slide exactly, if load_segment did something */
594: if(slide != -1)
595: mmapfixed = 1;
596: else
597: slide = 0; /* load_segment didn't map the segment */
598:
599: if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
600: qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
601:
602: if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
603: {
604: /* Text section */
605: if(mach_hdr.filetype == MH_EXECUTE)
606: {
607: /* return the mach_header */
608: *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
609: }
610: else
611: {
612: /* it is dyld save the section for gdb, we will be interested in dyld symbol
613: while debuging */
614: macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
615: macho_offset = slide;
616: }
617: }
618: break;
619: case LC_LOAD_DYLINKER:
620: dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
621: break;
622: case LC_LOAD_DYLIB:
623: /* dyld will do that for us */
624: break;
625: case LC_THREAD:
626: case LC_UNIXTHREAD:
627: {
628: struct target_pt_regs * _regs;
629: if(mach_hdr.filetype == MH_DYLINKER)
630: _regs = regs;
631: else
632: _regs = 0;
633: entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
634: }
635: break;
636: case LC_SYMTAB:
637: /* Save the symtab and strtab */
638: symtabcmd = (struct symtab_command *)lc;
639: break;
640: case LC_ID_DYLINKER:
641: case LC_ID_DYLIB:
642: case LC_UUID:
643: case LC_DYSYMTAB:
644: case LC_TWOLEVEL_HINTS:
645: case LC_PREBIND_CKSUM:
646: case LC_SUB_LIBRARY:
647: break;
648: default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
649: }
650: lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
651: }
652:
653: if(symtabcmd)
654: {
655: if(need_bswap)
656: bswap_symtabcmd(symtabcmd);
657:
658: symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
659: strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
660:
661: symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
662:
663: if(need_bswap)
664: {
665: for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
666: bswap_sym(syment);
667: }
668:
669: for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
670: {
671: struct nlist *sym_follow, *sym_next = 0;
672: unsigned int j;
673: memset(sym, 0, sizeof(*sym));
674:
675: sym->n_type = syment->n_type;
676: if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
677: continue;
678:
679: memcpy(sym, syment, sizeof(*syment));
680:
681: /* Find the following symbol in order to get the current symbol size */
682: for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
683: if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
684: continue;
685: if(!sym_next) {
686: sym_next = sym_follow;
687: continue;
688: }
689: if(!(sym_next->n_value > sym_follow->n_value))
690: continue;
691: sym_next = sym_follow;
692: }
693: if(sym_next)
694: sym->st_size = sym_next->n_value - sym->st_value;
695: else
696: sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
697:
698: sym->st_value += slide;
699: }
700:
701: free((void*)symtab_std);
702:
703: {
704: DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
705: struct syminfo *s;
706: s = malloc(sizeof(*s));
707: s->disas_symtab = symtab;
708: s->disas_strtab = strtab;
709: s->disas_num_syms = symtabcmd->nsyms;
710: s->next = syminfos;
711: syminfos = s;
712: }
713: }
714: close(fd);
715: if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
716: return dyld_entry_point;
717: else
718: return entry_point+slide;
719: }
720:
721: extern unsigned long stack_size;
722:
723: unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
724: {
725: unsigned long stack_base, error, size;
726: int i;
727: int * stack;
728: int argc, envc;
729:
730: /* Create enough stack to hold everything. If we don't use
731: * it for args, we'll use it for something else...
732: */
733: size = stack_size;
734:
735: error = target_mmap(0,
736: size + qemu_host_page_size,
737: PROT_READ | PROT_WRITE,
738: MAP_PRIVATE | MAP_ANONYMOUS,
739: -1, 0);
740: if (error == -1)
741: qerror("stk mmap");
742:
743: /* we reserve one extra page at the top of the stack as guard */
744: target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
745:
746: stack_base = error + size;
747: stack = (void*)stack_base;
748: /*
749: * | STRING AREA |
750: * +-------------+
751: * | 0 |
752: * +-------------+
753: * | apple[n] |
754: * +-------------+
755: * :
756: * +-------------+
757: * | apple[0] |
758: * +-------------+
759: * | 0 |
760: * +-------------+
761: * | env[n] |
762: * +-------------+
763: * :
764: * :
765: * +-------------+
766: * | env[0] |
767: * +-------------+
768: * | 0 |
769: * +-------------+
770: * | arg[argc-1] |
771: * +-------------+
772: * :
773: * :
774: * +-------------+
775: * | arg[0] |
776: * +-------------+
777: * | argc |
778: * +-------------+
779: * sp-> | mh | address of where the a.out's file offset 0 is in memory
780: * +-------------+
781: */
782: /* Construct the stack Stack grows down */
783: stack--;
784:
785: /* XXX: string should go up there */
786:
787: *stack = 0;
788: stack--;
789:
790: /* Push the absolute path of our executable */
791: DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
792: stl(stack, (int) argv[0]);
793:
794: stack--;
795:
796: stl(stack, 0);
797: stack--;
798:
799: /* Get envc */
800: for(envc = 0; env[envc]; envc++);
801:
802: for(i = envc-1; i >= 0; i--)
803: {
804: DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
805: stl(stack, (int)env[i]);
806: stack--;
807:
808: /* XXX: remove that when string will be on top of the stack */
809: page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
810: }
811:
812: /* Add on the stack the interp_prefix choosen if so */
813: if(interp_prefix[0])
814: {
815: char *dyld_root;
816: asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
817: page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
818:
819: stl(stack, (int)dyld_root);
820: stack--;
821: }
822:
823: #ifdef DONT_USE_DYLD_SHARED_MAP
824: {
825: char *shared_map_mode;
826: asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
827: page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
828:
829: stl(stack, (int)shared_map_mode);
830: stack--;
831: }
832: #endif
833:
834: #ifdef ACTIVATE_DYLD_TRACE
835: char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
836: "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
837: "DYLD_PRINT_INITIALIZERS=yes",
838: "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
839:
840: char ** extra_env = malloc(sizeof(extra_env_static));
841: bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
842: page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
843:
844: for(i = 0; i<9; i++)
845: {
846: DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
847: stl(stack, (int) extra_env[i]);
848: stack--;
849: }
850: #endif
851:
852: stl(stack, 0);
853: stack--;
854:
855: /* Get argc */
856: for(argc = 0; argv[argc]; argc++);
857:
858: for(i = argc-1; i >= 0; i--)
859: {
860: DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
861: stl(stack, (int) argv[i]);
862: stack--;
863:
864: /* XXX: remove that when string will be on top of the stack */
865: page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
866: }
867:
1.1.1.5 ! root 868: DPRINTF("pushing argc %d\n", argc);
1.1 root 869: stl(stack, argc);
870: stack--;
871:
1.1.1.5 ! root 872: DPRINTF("pushing mh 0x%x\n", (int)mh);
1.1 root 873: stl(stack, (int) mh);
874:
875: /* Stack points on the mh */
876: return (unsigned long)stack;
877: }
878:
879: int mach_exec(const char * filename, char ** argv, char ** envp,
880: struct target_pt_regs * regs)
881: {
882: int entrypoint, stack;
883: void * mh; /* the Mach Header that will be used by dyld */
884:
885: DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
886:
887: entrypoint = load_object(filename, regs, &mh);
888: stack = setup_arg_pages(mh, argv, envp);
889: #if defined(TARGET_I386)
890: regs->eip = entrypoint;
891: regs->esp = stack;
892: #elif defined(TARGET_PPC)
893: regs->nip = entrypoint;
894: regs->gpr[1] = stack;
895: #endif
896: DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
897:
898: if(!entrypoint)
899: qerror("%s: no entry point!\n", filename);
900:
901: return 0;
902: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.