2 * Mach-O object file loading
4 * Copyright (c) 2006 Pierre d'Herbemont
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
21 #include <sys/types.h>
33 #include <mach-o/loader.h>
34 #include <mach-o/fat.h>
35 #include <mach-o/nlist.h>
36 #include <mach-o/reloc.h>
37 #include <mach-o/ppc/reloc.h>
39 //#define DEBUG_MACHLOAD
42 # define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
44 # define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
47 # define check_mach_header(x) (x.magic == MH_CIGAM)
49 extern const char *interp_prefix
;
51 /* we don't have a good implementation for this */
52 #define DONT_USE_DYLD_SHARED_MAP
54 /* Pass extra arg to DYLD for debug */
55 //#define ACTIVATE_DYLD_TRACE
57 //#define OVERRIDE_DYLINKER
59 #ifdef OVERRIDE_DYLINKER
61 # define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
63 # define DYLINKER_NAME "/usr/lib/dyld"
67 /* XXX: in an include */
77 unsigned long st_value
;
78 unsigned long st_size
;
81 /* Print symbols in gdb */
82 void *macho_text_sect
= 0;
85 int load_object(const char *filename
, struct target_pt_regs
* regs
, void ** mh
);
86 void qerror(const char *format
, ...);
88 typedef struct mach_i386_thread_state
{
105 } mach_i386_thread_state_t
;
107 void bswap_i386_thread_state(struct mach_i386_thread_state
*ts
)
109 bswap32s((uint32_t*)&ts
->eax
);
110 bswap32s((uint32_t*)&ts
->ebx
);
111 bswap32s((uint32_t*)&ts
->ecx
);
112 bswap32s((uint32_t*)&ts
->edx
);
113 bswap32s((uint32_t*)&ts
->edi
);
114 bswap32s((uint32_t*)&ts
->esi
);
115 bswap32s((uint32_t*)&ts
->ebp
);
116 bswap32s((uint32_t*)&ts
->esp
);
117 bswap32s((uint32_t*)&ts
->ss
);
118 bswap32s((uint32_t*)&ts
->eflags
);
119 bswap32s((uint32_t*)&ts
->eip
);
120 bswap32s((uint32_t*)&ts
->cs
);
121 bswap32s((uint32_t*)&ts
->ds
);
122 bswap32s((uint32_t*)&ts
->es
);
123 bswap32s((uint32_t*)&ts
->fs
);
124 bswap32s((uint32_t*)&ts
->gs
);
126 #define target_thread_state mach_i386_thread_state
127 #define TARGET_CPU_TYPE CPU_TYPE_I386
128 #define TARGET_CPU_NAME "i386"
132 struct mach_ppc_thread_state
{
133 unsigned int srr0
; /* Instruction address register (PC) */
134 unsigned int srr1
; /* Machine state register (supervisor) */
168 unsigned int cr
; /* Condition register */
169 unsigned int xer
; /* User's integer exception register */
170 unsigned int lr
; /* Link register */
171 unsigned int ctr
; /* Count register */
172 unsigned int mq
; /* MQ register (601 only) */
174 unsigned int vrsave
; /* Vector Save Register */
177 void bswap_ppc_thread_state(struct mach_ppc_thread_state
*ts
)
179 bswap32s((uint32_t*)&ts
->srr0
);
180 bswap32s((uint32_t*)&ts
->srr1
);
181 bswap32s((uint32_t*)&ts
->r0
);
182 bswap32s((uint32_t*)&ts
->r1
);
183 bswap32s((uint32_t*)&ts
->r2
);
184 bswap32s((uint32_t*)&ts
->r3
);
185 bswap32s((uint32_t*)&ts
->r4
);
186 bswap32s((uint32_t*)&ts
->r5
);
187 bswap32s((uint32_t*)&ts
->r6
);
188 bswap32s((uint32_t*)&ts
->r7
);
189 bswap32s((uint32_t*)&ts
->r8
);
190 bswap32s((uint32_t*)&ts
->r9
);
191 bswap32s((uint32_t*)&ts
->r10
);
192 bswap32s((uint32_t*)&ts
->r11
);
193 bswap32s((uint32_t*)&ts
->r12
);
194 bswap32s((uint32_t*)&ts
->r13
);
195 bswap32s((uint32_t*)&ts
->r14
);
196 bswap32s((uint32_t*)&ts
->r15
);
197 bswap32s((uint32_t*)&ts
->r16
);
198 bswap32s((uint32_t*)&ts
->r17
);
199 bswap32s((uint32_t*)&ts
->r18
);
200 bswap32s((uint32_t*)&ts
->r19
);
201 bswap32s((uint32_t*)&ts
->r20
);
202 bswap32s((uint32_t*)&ts
->r21
);
203 bswap32s((uint32_t*)&ts
->r22
);
204 bswap32s((uint32_t*)&ts
->r23
);
205 bswap32s((uint32_t*)&ts
->r24
);
206 bswap32s((uint32_t*)&ts
->r25
);
207 bswap32s((uint32_t*)&ts
->r26
);
208 bswap32s((uint32_t*)&ts
->r27
);
209 bswap32s((uint32_t*)&ts
->r28
);
210 bswap32s((uint32_t*)&ts
->r29
);
211 bswap32s((uint32_t*)&ts
->r30
);
212 bswap32s((uint32_t*)&ts
->r31
);
214 bswap32s((uint32_t*)&ts
->cr
);
215 bswap32s((uint32_t*)&ts
->xer
);
216 bswap32s((uint32_t*)&ts
->lr
);
217 bswap32s((uint32_t*)&ts
->ctr
);
218 bswap32s((uint32_t*)&ts
->mq
);
220 bswap32s((uint32_t*)&ts
->vrsave
);
223 #define target_thread_state mach_ppc_thread_state
224 #define TARGET_CPU_TYPE CPU_TYPE_POWERPC
225 #define TARGET_CPU_NAME "PowerPC"
228 struct target_thread_command
{
229 unsigned long cmd
; /* LC_THREAD or LC_UNIXTHREAD */
230 unsigned long cmdsize
; /* total size of this command */
231 unsigned long flavor
; /* flavor of thread state */
232 unsigned long count
; /* count of longs in thread state */
233 struct target_thread_state state
; /* thread state for this flavor */
236 void bswap_tc(struct target_thread_command
*tc
)
238 bswap32s((uint32_t*)(&tc
->flavor
));
239 bswap32s((uint32_t*)&tc
->count
);
240 #if defined(TARGET_I386)
241 bswap_i386_thread_state(&tc
->state
);
242 #elif defined(TARGET_PPC)
243 bswap_ppc_thread_state(&tc
->state
);
245 # error unknown TARGET_CPU_TYPE
249 void bswap_mh(struct mach_header
*mh
)
251 bswap32s((uint32_t*)(&mh
->magic
));
252 bswap32s((uint32_t*)&mh
->cputype
);
253 bswap32s((uint32_t*)&mh
->cpusubtype
);
254 bswap32s((uint32_t*)&mh
->filetype
);
255 bswap32s((uint32_t*)&mh
->ncmds
);
256 bswap32s((uint32_t*)&mh
->sizeofcmds
);
257 bswap32s((uint32_t*)&mh
->flags
);
260 void bswap_lc(struct load_command
*lc
)
262 bswap32s((uint32_t*)&lc
->cmd
);
263 bswap32s((uint32_t*)&lc
->cmdsize
);
267 void bswap_fh(struct fat_header
*fh
)
269 bswap32s((uint32_t*)&fh
->magic
);
270 bswap32s((uint32_t*)&fh
->nfat_arch
);
273 void bswap_fa(struct fat_arch
*fa
)
275 bswap32s((uint32_t*)&fa
->cputype
);
276 bswap32s((uint32_t*)&fa
->cpusubtype
);
277 bswap32s((uint32_t*)&fa
->offset
);
278 bswap32s((uint32_t*)&fa
->size
);
279 bswap32s((uint32_t*)&fa
->align
);
282 void bswap_segcmd(struct segment_command
*sc
)
284 bswap32s((uint32_t*)&sc
->vmaddr
);
285 bswap32s((uint32_t*)&sc
->vmsize
);
286 bswap32s((uint32_t*)&sc
->fileoff
);
287 bswap32s((uint32_t*)&sc
->filesize
);
288 bswap32s((uint32_t*)&sc
->maxprot
);
289 bswap32s((uint32_t*)&sc
->initprot
);
290 bswap32s((uint32_t*)&sc
->nsects
);
291 bswap32s((uint32_t*)&sc
->flags
);
294 void bswap_symtabcmd(struct symtab_command
*stc
)
296 bswap32s((uint32_t*)&stc
->cmd
);
297 bswap32s((uint32_t*)&stc
->cmdsize
);
298 bswap32s((uint32_t*)&stc
->symoff
);
299 bswap32s((uint32_t*)&stc
->nsyms
);
300 bswap32s((uint32_t*)&stc
->stroff
);
301 bswap32s((uint32_t*)&stc
->strsize
);
304 void bswap_sym(struct nlist
*n
)
306 bswap32s((uint32_t*)&n
->n_un
.n_strx
);
307 bswap16s((uint16_t*)&n
->n_desc
);
308 bswap32s((uint32_t*)&n
->n_value
);
311 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
)
316 #if defined(TARGET_I386)
317 entry
= tc
->state
.eip
;
318 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",
319 tc
->state
.eax
, tc
->state
.ebx
, tc
->state
.ecx
, tc
->state
.edx
, tc
->state
.edi
, tc
->state
.esi
, tc
->state
.ebp
,
320 tc
->state
.esp
, tc
->state
.ss
, tc
->state
.eflags
, tc
->state
.eip
, tc
->state
.cs
, tc
->state
.ds
, tc
->state
.es
,
321 tc
->state
.fs
, tc
->state
.gs
);
322 #define reg_copy(reg) regs->reg = tc->state.reg
347 #elif defined(TARGET_PPC)
348 entry
= tc
->state
.srr0
;
350 DPRINTF("load_thread: entry 0x%x\n", entry
);
354 int load_dylinker(struct mach_header
*mh
, struct dylinker_command
*dc
, int fd
, int mh_pos
, int need_bswap
)
357 char * dylinker_name
;
358 size
= dc
->cmdsize
- sizeof(struct dylinker_command
);
361 dylinker_name
= (char*)(bswap_32(dc
->name
.offset
)+(int)dc
);
363 dylinker_name
= (char*)((dc
->name
.offset
)+(int)dc
);
365 #ifdef OVERRIDE_DYLINKER
366 dylinker_name
= DYLINKER_NAME
;
368 if(asprintf(&dylinker_name
, "%s%s", interp_prefix
, dylinker_name
) == -1)
369 qerror("can't allocate the new dylinker name\n");
372 DPRINTF("dylinker_name %s\n", dylinker_name
);
373 return load_object(dylinker_name
, NULL
, NULL
);
376 int load_segment(struct mach_header
*mh
, struct segment_command
*sc
, int fd
, int mh_pos
, int need_bswap
, int fixed
, int slide
)
378 unsigned long addr
= sc
->vmaddr
;
379 unsigned long size
= sc
->filesize
;
380 unsigned long error
= 0;
387 DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
391 if (strcmp(sc
->segname
, "__PAGEZERO") == 0)
393 DPRINTF("load_segment: __PAGEZERO returning\n");
397 /* Right now mmap memory */
398 /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
399 DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc
->segname
, sc
->vmaddr
, sc
->filesize
, sc
->vmsize
, slide
);
408 DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide
, sc
->vmaddr
, sc
->vmaddr
+slide
);
410 addr
= target_mmap(sc
->vmaddr
+slide
, sc
->filesize
, sc
->initprot
, opt
, fd
, mh_pos
+ sc
->fileoff
);
413 qerror("load_segment: can't mmap at 0x%x\n", sc
->vmaddr
+slide
);
415 error
= addr
-sc
->vmaddr
;
419 addr
= sc
->vmaddr
+slide
;
423 if(sc
->vmsize
> sc
->filesize
)
425 addr
+= sc
->filesize
;
426 size
= sc
->vmsize
-sc
->filesize
;
427 addr
= target_mmap(addr
, size
, sc
->initprot
, MAP_ANONYMOUS
| MAP_FIXED
, -1, 0);
429 qerror("load_segment: can't mmap at 0x%x\n", sc
->vmaddr
+slide
);
435 void *load_data(int fd
, long offset
, unsigned int size
)
442 lseek(fd
, offset
, SEEK_SET
);
443 if (read(fd
, data
, size
) != size
) {
450 /* load a mach-o object file */
451 int load_object(const char *filename
, struct target_pt_regs
* regs
, void ** mh
)
455 int dyld_entry_point
= 0;
456 int slide
, mmapfixed
;
458 struct load_command
*lcmds
, *lc
;
460 unsigned int i
, magic
;
461 int mach_hdr_pos
= 0;
462 struct mach_header mach_hdr
;
464 /* for symbol lookup whith -d flag. */
465 struct symtab_command
* symtabcmd
= 0;
466 struct nlist_extended
*symtab
, *sym
;
467 struct nlist
*symtab_std
, *syment
;
470 fd
= open(filename
, O_RDONLY
);
472 qerror("can't open file '%s'", filename
);
474 /* Read magic header. */
475 if (read(fd
, &magic
, sizeof (magic
)) != sizeof (magic
))
476 qerror("unable to read Magic of '%s'", filename
);
478 /* Check Mach identification. */
479 if(magic
== MH_MAGIC
)
483 } else if (magic
== MH_CIGAM
)
487 } else if (magic
== FAT_MAGIC
)
491 } else if (magic
== FAT_CIGAM
)
497 qerror("Not a Mach-O file.", filename
);
499 DPRINTF("loading %s %s...\n", filename
, is_fat
? "[FAT]": "[REGULAR]");
503 struct fat_header fh
;
506 lseek(fd
, 0, SEEK_SET
);
508 /* Read Fat header. */
509 if (read(fd
, &fh
, sizeof (fh
)) != sizeof (fh
))
510 qerror("unable to read file header");
516 fa
= malloc(sizeof(struct fat_arch
)*fh
.nfat_arch
);
518 if (read(fd
, fa
, sizeof(struct fat_arch
)*fh
.nfat_arch
) != sizeof(struct fat_arch
)*fh
.nfat_arch
)
519 qerror("unable to read file header");
521 for( i
= 0; i
< fh
.nfat_arch
; i
++, fa
++)
525 if(fa
->cputype
== TARGET_CPU_TYPE
)
527 mach_hdr_pos
= fa
->offset
;
528 lseek(fd
, mach_hdr_pos
, SEEK_SET
);
530 /* Read Mach header. */
532 if (read(fd
, &mach_hdr
, sizeof(struct mach_header
)) != sizeof (struct mach_header
))
533 qerror("unable to read file header");
535 if(mach_hdr
.magic
== MH_MAGIC
)
537 else if (mach_hdr
.magic
== MH_CIGAM
)
540 qerror("Invalid mach header in Fat Mach-O File");
546 qerror("%s: No %s CPU found in FAT Header", filename
, TARGET_CPU_NAME
);
550 lseek(fd
, 0, SEEK_SET
);
551 /* Read Mach header */
552 if (read(fd
, &mach_hdr
, sizeof (mach_hdr
)) != sizeof (mach_hdr
))
553 qerror("%s: unable to read file header", filename
);
559 if ((mach_hdr
.cputype
) != TARGET_CPU_TYPE
)
560 qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename
, mach_hdr
.cputype
, TARGET_CPU_TYPE
, TARGET_CPU_NAME
);
563 switch(mach_hdr
.filetype
)
565 case MH_EXECUTE
: break;
568 case MH_DYLINKER
: break;
570 qerror("%s: Unsupported Mach type (0x%x)", filename
, mach_hdr
.filetype
);
573 /* read segment headers */
574 lcmds
= malloc(mach_hdr
.sizeofcmds
);
576 if(read(fd
, lcmds
, mach_hdr
.sizeofcmds
) != mach_hdr
.sizeofcmds
)
577 qerror("%s: unable to read load_command", filename
);
580 for(i
=0, lc
= lcmds
; i
< (mach_hdr
.ncmds
) ; i
++)
588 /* The main_exe can't be relocated */
589 if(mach_hdr
.filetype
== MH_EXECUTE
)
592 slide
= load_segment(&mach_hdr
, (struct segment_command
*)lc
, fd
, mach_hdr_pos
, need_bswap
, mmapfixed
, slide
);
594 /* other segment must be mapped according to slide exactly, if load_segment did something */
598 slide
= 0; /* load_segment didn't map the segment */
600 if(mach_hdr
.filetype
== MH_EXECUTE
&& slide
!= 0)
601 qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename
, slide
);
603 if(strcmp(((struct segment_command
*)(lc
))->segname
, "__TEXT") == 0)
606 if(mach_hdr
.filetype
== MH_EXECUTE
)
608 /* return the mach_header */
609 *mh
= (void*)(((struct segment_command
*)(lc
))->vmaddr
+ slide
);
613 /* it is dyld save the section for gdb, we will be interested in dyld symbol
615 macho_text_sect
= (void*)(((struct segment_command
*)(lc
))->vmaddr
+ slide
);
616 macho_offset
= slide
;
620 case LC_LOAD_DYLINKER
:
621 dyld_entry_point
= load_dylinker( &mach_hdr
, (struct dylinker_command
*)lc
, fd
, mach_hdr_pos
, need_bswap
);
624 /* dyld will do that for us */
629 struct target_pt_regs
* _regs
;
630 if(mach_hdr
.filetype
== MH_DYLINKER
)
634 entry_point
= load_thread( &mach_hdr
, (struct target_thread_command
*)lc
, _regs
, fd
, mach_hdr_pos
, need_bswap
);
638 /* Save the symtab and strtab */
639 symtabcmd
= (struct symtab_command
*)lc
;
645 case LC_TWOLEVEL_HINTS
:
646 case LC_PREBIND_CKSUM
:
649 default: fprintf(stderr
, "warning: unkown command 0x%x in '%s'\n", lc
->cmd
, filename
);
651 lc
= (struct load_command
*)((int)(lc
)+(lc
->cmdsize
));
657 bswap_symtabcmd(symtabcmd
);
659 symtab_std
= load_data(fd
, symtabcmd
->symoff
+mach_hdr_pos
, symtabcmd
->nsyms
* sizeof(struct nlist
));
660 strtab
= load_data(fd
, symtabcmd
->stroff
+mach_hdr_pos
, symtabcmd
->strsize
);
662 symtab
= malloc(sizeof(struct nlist_extended
) * symtabcmd
->nsyms
);
666 for(i
= 0, syment
= symtab_std
; i
< symtabcmd
->nsyms
; i
++, syment
++)
670 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< symtabcmd
->nsyms
; i
++, sym
++, syment
++)
672 struct nlist
*sym_follow
, *sym_next
= 0;
674 memset(sym
, 0, sizeof(*sym
));
676 sym
->n_type
= syment
->n_type
;
677 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
680 memcpy(sym
, syment
, sizeof(*syment
));
682 /* Find the following symbol in order to get the current symbol size */
683 for(j
= 0, sym_follow
= symtab_std
; j
< symtabcmd
->nsyms
; j
++, sym_follow
++) {
684 if ( sym_follow
->n_type
& N_STAB
|| !(sym_follow
->n_value
> sym
->st_value
))
687 sym_next
= sym_follow
;
690 if(!(sym_next
->n_value
> sym_follow
->n_value
))
692 sym_next
= sym_follow
;
695 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
697 sym
->st_size
= 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
699 sym
->st_value
+= slide
;
702 free((void*)symtab_std
);
705 DPRINTF("saving symtab of %s (%d symbol(s))\n", filename
, symtabcmd
->nsyms
);
707 s
= malloc(sizeof(*s
));
708 s
->disas_symtab
= symtab
;
709 s
->disas_strtab
= strtab
;
710 s
->disas_num_syms
= symtabcmd
->nsyms
;
716 if(mach_hdr
.filetype
== MH_EXECUTE
&& dyld_entry_point
)
717 return dyld_entry_point
;
719 return entry_point
+slide
;
722 extern unsigned long stack_size
;
724 unsigned long setup_arg_pages(void * mh
, char ** argv
, char ** env
)
726 unsigned long stack_base
, error
, size
;
731 /* Create enough stack to hold everything. If we don't use
732 * it for args, we'll use it for something else...
736 error
= target_mmap(0,
737 size
+ qemu_host_page_size
,
738 PROT_READ
| PROT_WRITE
,
739 MAP_PRIVATE
| MAP_ANONYMOUS
,
744 /* we reserve one extra page at the top of the stack as guard */
745 target_mprotect(error
+ size
, qemu_host_page_size
, PROT_NONE
);
747 stack_base
= error
+ size
;
748 stack
= (void*)stack_base
;
780 * sp-> | mh | address of where the a.out's file offset 0 is in memory
783 /* Construct the stack Stack grows down */
786 /* XXX: string should go up there */
791 /* Push the absolute path of our executable */
792 DPRINTF("pushing apple %s (0x%x)\n", (char*)argv
[0], (int)argv
[0]);
793 stl(stack
, (int) argv
[0]);
801 for(envc
= 0; env
[envc
]; envc
++);
803 for(i
= envc
-1; i
>= 0; i
--)
805 DPRINTF("pushing env %s (0x%x)\n", (char*)env
[i
], (int)env
[i
]);
806 stl(stack
, (int)env
[i
]);
809 /* XXX: remove that when string will be on top of the stack */
810 page_set_flags((int)env
[i
], (int)(env
[i
]+strlen(env
[i
])), PROT_READ
| PAGE_VALID
);
813 /* Add on the stack the interp_prefix choosen if so */
817 asprintf(&dyld_root
, "DYLD_ROOT_PATH=%s", interp_prefix
);
818 page_set_flags((int)dyld_root
, (int)(dyld_root
+strlen(interp_prefix
)+1), PROT_READ
| PAGE_VALID
);
820 stl(stack
, (int)dyld_root
);
824 #ifdef DONT_USE_DYLD_SHARED_MAP
826 char *shared_map_mode
;
827 asprintf(&shared_map_mode
, "DYLD_SHARED_REGION=avoid");
828 page_set_flags((int)shared_map_mode
, (int)(shared_map_mode
+strlen(shared_map_mode
)+1), PROT_READ
| PAGE_VALID
);
830 stl(stack
, (int)shared_map_mode
);
835 #ifdef ACTIVATE_DYLD_TRACE
836 char * extra_env_static
[] = {"DYLD_DEBUG_TRACE=yes",
837 "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
838 "DYLD_PRINT_INITIALIZERS=yes",
839 "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
841 char ** extra_env
= malloc(sizeof(extra_env_static
));
842 bcopy(extra_env_static
, extra_env
, sizeof(extra_env_static
));
843 page_set_flags((int)extra_env
, (int)((void*)extra_env
+sizeof(extra_env_static
)), PROT_READ
| PAGE_VALID
);
847 DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env
[i
], (int)extra_env
[i
]);
848 stl(stack
, (int) extra_env
[i
]);
857 for(argc
= 0; argv
[argc
]; argc
++);
859 for(i
= argc
-1; i
>= 0; i
--)
861 DPRINTF("pushing arg %s (0x%x)\n", (char*)argv
[i
], (int)argv
[i
]);
862 stl(stack
, (int) argv
[i
]);
865 /* XXX: remove that when string will be on top of the stack */
866 page_set_flags((int)argv
[i
], (int)(argv
[i
]+strlen(argv
[i
])), PROT_READ
| PAGE_VALID
);
869 DPRINTF("pushing argc %d \n", argc
);
873 DPRINTF("pushing mh 0x%x \n", (int)mh
);
874 stl(stack
, (int) mh
);
876 /* Stack points on the mh */
877 return (unsigned long)stack
;
880 int mach_exec(const char * filename
, char ** argv
, char ** envp
,
881 struct target_pt_regs
* regs
)
883 int entrypoint
, stack
;
884 void * mh
; /* the Mach Header that will be used by dyld */
886 DPRINTF("mach_exec at 0x%x\n", (int)mach_exec
);
888 entrypoint
= load_object(filename
, regs
, &mh
);
889 stack
= setup_arg_pages(mh
, argv
, envp
);
890 #if defined(TARGET_I386)
891 regs
->eip
= entrypoint
;
893 #elif defined(TARGET_PPC)
894 regs
->nip
= entrypoint
;
895 regs
->gpr
[1] = stack
;
897 DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint
, stack
, (int)mh
);
900 qerror("%s: no entry point!\n", filename
);