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, see <http://www.gnu.org/licenses/>.
20 #include <sys/types.h>
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>
38 //#define DEBUG_MACHLOAD
41 # define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
43 # define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
46 # define check_mach_header(x) (x.magic == MH_CIGAM)
48 extern const char *interp_prefix
;
50 /* we don't have a good implementation for this */
51 #define DONT_USE_DYLD_SHARED_MAP
53 /* Pass extra arg to DYLD for debug */
54 //#define ACTIVATE_DYLD_TRACE
56 //#define OVERRIDE_DYLINKER
58 #ifdef OVERRIDE_DYLINKER
60 # define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
62 # define DYLINKER_NAME "/usr/lib/dyld"
66 /* XXX: in an include */
76 unsigned long st_value
;
77 unsigned long st_size
;
80 /* Print symbols in gdb */
81 void *macho_text_sect
= 0;
84 int load_object(const char *filename
, struct target_pt_regs
* regs
, void ** mh
);
85 void qerror(const char *format
, ...);
87 typedef struct mach_i386_thread_state
{
104 } mach_i386_thread_state_t
;
106 void bswap_i386_thread_state(struct mach_i386_thread_state
*ts
)
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
);
125 #define target_thread_state mach_i386_thread_state
126 #define TARGET_CPU_TYPE CPU_TYPE_I386
127 #define TARGET_CPU_NAME "i386"
131 struct mach_ppc_thread_state
{
132 unsigned int srr0
; /* Instruction address register (PC) */
133 unsigned int srr1
; /* Machine state register (supervisor) */
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) */
173 unsigned int vrsave
; /* Vector Save Register */
176 void bswap_ppc_thread_state(struct mach_ppc_thread_state
*ts
)
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
);
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
);
219 bswap32s((uint32_t*)&ts
->vrsave
);
222 #define target_thread_state mach_ppc_thread_state
223 #define TARGET_CPU_TYPE CPU_TYPE_POWERPC
224 #define TARGET_CPU_NAME "PowerPC"
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 */
235 void bswap_tc(struct target_thread_command
*tc
)
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
);
244 # error unknown TARGET_CPU_TYPE
248 void bswap_mh(struct mach_header
*mh
)
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
);
259 void bswap_lc(struct load_command
*lc
)
261 bswap32s((uint32_t*)&lc
->cmd
);
262 bswap32s((uint32_t*)&lc
->cmdsize
);
266 void bswap_fh(struct fat_header
*fh
)
268 bswap32s((uint32_t*)&fh
->magic
);
269 bswap32s((uint32_t*)&fh
->nfat_arch
);
272 void bswap_fa(struct fat_arch
*fa
)
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
);
281 void bswap_segcmd(struct segment_command
*sc
)
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
);
293 void bswap_symtabcmd(struct symtab_command
*stc
)
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
);
303 void bswap_sym(struct nlist
*n
)
305 bswap32s((uint32_t*)&n
->n_un
.n_strx
);
306 bswap16s((uint16_t*)&n
->n_desc
);
307 bswap32s((uint32_t*)&n
->n_value
);
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
)
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
346 #elif defined(TARGET_PPC)
347 entry
= tc
->state
.srr0
;
349 DPRINTF("load_thread: entry 0x%x\n", entry
);
353 int load_dylinker(struct mach_header
*mh
, struct dylinker_command
*dc
, int fd
, int mh_pos
, int need_bswap
)
356 char * dylinker_name
;
357 size
= dc
->cmdsize
- sizeof(struct dylinker_command
);
360 dylinker_name
= (char*)(bswap_32(dc
->name
.offset
)+(int)dc
);
362 dylinker_name
= (char*)((dc
->name
.offset
)+(int)dc
);
364 #ifdef OVERRIDE_DYLINKER
365 dylinker_name
= DYLINKER_NAME
;
367 if(asprintf(&dylinker_name
, "%s%s", interp_prefix
, dylinker_name
) == -1)
368 qerror("can't allocate the new dylinker name\n");
371 DPRINTF("dylinker_name %s\n", dylinker_name
);
372 return load_object(dylinker_name
, NULL
, NULL
);
375 int load_segment(struct mach_header
*mh
, struct segment_command
*sc
, int fd
, int mh_pos
, int need_bswap
, int fixed
, int slide
)
377 unsigned long addr
= sc
->vmaddr
;
378 unsigned long size
= sc
->filesize
;
379 unsigned long error
= 0;
386 DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
390 if (strcmp(sc
->segname
, "__PAGEZERO") == 0)
392 DPRINTF("load_segment: __PAGEZERO returning\n");
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
);
407 DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide
, sc
->vmaddr
, sc
->vmaddr
+slide
);
409 addr
= target_mmap(sc
->vmaddr
+slide
, sc
->filesize
, sc
->initprot
, opt
, fd
, mh_pos
+ sc
->fileoff
);
412 qerror("load_segment: can't mmap at 0x%x\n", sc
->vmaddr
+slide
);
414 error
= addr
-sc
->vmaddr
;
418 addr
= sc
->vmaddr
+slide
;
422 if(sc
->vmsize
> sc
->filesize
)
424 addr
+= sc
->filesize
;
425 size
= sc
->vmsize
-sc
->filesize
;
426 addr
= target_mmap(addr
, size
, sc
->initprot
, MAP_ANONYMOUS
| MAP_FIXED
, -1, 0);
428 qerror("load_segment: can't mmap at 0x%x\n", sc
->vmaddr
+slide
);
434 void *load_data(int fd
, long offset
, unsigned int size
)
441 lseek(fd
, offset
, SEEK_SET
);
442 if (read(fd
, data
, size
) != size
) {
449 /* load a mach-o object file */
450 int load_object(const char *filename
, struct target_pt_regs
* regs
, void ** mh
)
454 int dyld_entry_point
= 0;
455 int slide
, mmapfixed
;
457 struct load_command
*lcmds
, *lc
;
459 unsigned int i
, magic
;
460 int mach_hdr_pos
= 0;
461 struct mach_header mach_hdr
;
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
;
469 fd
= open(filename
, O_RDONLY
);
471 qerror("can't open file '%s'", filename
);
473 /* Read magic header. */
474 if (read(fd
, &magic
, sizeof (magic
)) != sizeof (magic
))
475 qerror("unable to read Magic of '%s'", filename
);
477 /* Check Mach identification. */
478 if(magic
== MH_MAGIC
)
482 } else if (magic
== MH_CIGAM
)
486 } else if (magic
== FAT_MAGIC
)
490 } else if (magic
== FAT_CIGAM
)
496 qerror("Not a Mach-O file.", filename
);
498 DPRINTF("loading %s %s...\n", filename
, is_fat
? "[FAT]": "[REGULAR]");
502 struct fat_header fh
;
505 lseek(fd
, 0, SEEK_SET
);
507 /* Read Fat header. */
508 if (read(fd
, &fh
, sizeof (fh
)) != sizeof (fh
))
509 qerror("unable to read file header");
515 fa
= malloc(sizeof(struct fat_arch
)*fh
.nfat_arch
);
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");
520 for( i
= 0; i
< fh
.nfat_arch
; i
++, fa
++)
524 if(fa
->cputype
== TARGET_CPU_TYPE
)
526 mach_hdr_pos
= fa
->offset
;
527 lseek(fd
, mach_hdr_pos
, SEEK_SET
);
529 /* Read Mach header. */
531 if (read(fd
, &mach_hdr
, sizeof(struct mach_header
)) != sizeof (struct mach_header
))
532 qerror("unable to read file header");
534 if(mach_hdr
.magic
== MH_MAGIC
)
536 else if (mach_hdr
.magic
== MH_CIGAM
)
539 qerror("Invalid mach header in Fat Mach-O File");
545 qerror("%s: No %s CPU found in FAT Header", filename
, TARGET_CPU_NAME
);
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
);
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
);
562 switch(mach_hdr
.filetype
)
564 case MH_EXECUTE
: break;
567 case MH_DYLINKER
: break;
569 qerror("%s: Unsupported Mach type (0x%x)", filename
, mach_hdr
.filetype
);
572 /* read segment headers */
573 lcmds
= malloc(mach_hdr
.sizeofcmds
);
575 if(read(fd
, lcmds
, mach_hdr
.sizeofcmds
) != mach_hdr
.sizeofcmds
)
576 qerror("%s: unable to read load_command", filename
);
579 for(i
=0, lc
= lcmds
; i
< (mach_hdr
.ncmds
) ; i
++)
587 /* The main_exe can't be relocated */
588 if(mach_hdr
.filetype
== MH_EXECUTE
)
591 slide
= load_segment(&mach_hdr
, (struct segment_command
*)lc
, fd
, mach_hdr_pos
, need_bswap
, mmapfixed
, slide
);
593 /* other segment must be mapped according to slide exactly, if load_segment did something */
597 slide
= 0; /* load_segment didn't map the segment */
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
);
602 if(strcmp(((struct segment_command
*)(lc
))->segname
, "__TEXT") == 0)
605 if(mach_hdr
.filetype
== MH_EXECUTE
)
607 /* return the mach_header */
608 *mh
= (void*)(((struct segment_command
*)(lc
))->vmaddr
+ slide
);
612 /* it is dyld save the section for gdb, we will be interested in dyld symbol
614 macho_text_sect
= (void*)(((struct segment_command
*)(lc
))->vmaddr
+ slide
);
615 macho_offset
= slide
;
619 case LC_LOAD_DYLINKER
:
620 dyld_entry_point
= load_dylinker( &mach_hdr
, (struct dylinker_command
*)lc
, fd
, mach_hdr_pos
, need_bswap
);
623 /* dyld will do that for us */
628 struct target_pt_regs
* _regs
;
629 if(mach_hdr
.filetype
== MH_DYLINKER
)
633 entry_point
= load_thread( &mach_hdr
, (struct target_thread_command
*)lc
, _regs
, fd
, mach_hdr_pos
, need_bswap
);
637 /* Save the symtab and strtab */
638 symtabcmd
= (struct symtab_command
*)lc
;
644 case LC_TWOLEVEL_HINTS
:
645 case LC_PREBIND_CKSUM
:
648 default: fprintf(stderr
, "warning: unkown command 0x%x in '%s'\n", lc
->cmd
, filename
);
650 lc
= (struct load_command
*)((int)(lc
)+(lc
->cmdsize
));
656 bswap_symtabcmd(symtabcmd
);
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
);
661 symtab
= malloc(sizeof(struct nlist_extended
) * symtabcmd
->nsyms
);
665 for(i
= 0, syment
= symtab_std
; i
< symtabcmd
->nsyms
; i
++, syment
++)
669 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< symtabcmd
->nsyms
; i
++, sym
++, syment
++)
671 struct nlist
*sym_follow
, *sym_next
= 0;
673 memset(sym
, 0, sizeof(*sym
));
675 sym
->n_type
= syment
->n_type
;
676 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
679 memcpy(sym
, syment
, sizeof(*syment
));
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
))
686 sym_next
= sym_follow
;
689 if(!(sym_next
->n_value
> sym_follow
->n_value
))
691 sym_next
= sym_follow
;
694 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
696 sym
->st_size
= 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
698 sym
->st_value
+= slide
;
701 free((void*)symtab_std
);
704 DPRINTF("saving symtab of %s (%d symbol(s))\n", filename
, symtabcmd
->nsyms
);
706 s
= malloc(sizeof(*s
));
707 s
->disas_symtab
= symtab
;
708 s
->disas_strtab
= strtab
;
709 s
->disas_num_syms
= symtabcmd
->nsyms
;
715 if(mach_hdr
.filetype
== MH_EXECUTE
&& dyld_entry_point
)
716 return dyld_entry_point
;
718 return entry_point
+slide
;
721 extern unsigned long stack_size
;
723 unsigned long setup_arg_pages(void * mh
, char ** argv
, char ** env
)
725 unsigned long stack_base
, error
, size
;
730 /* Create enough stack to hold everything. If we don't use
731 * it for args, we'll use it for something else...
735 error
= target_mmap(0,
736 size
+ qemu_host_page_size
,
737 PROT_READ
| PROT_WRITE
,
738 MAP_PRIVATE
| MAP_ANONYMOUS
,
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
);
746 stack_base
= error
+ size
;
747 stack
= (void*)stack_base
;
779 * sp-> | mh | address of where the a.out's file offset 0 is in memory
782 /* Construct the stack Stack grows down */
785 /* XXX: string should go up there */
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]);
800 for(envc
= 0; env
[envc
]; envc
++);
802 for(i
= envc
-1; i
>= 0; i
--)
804 DPRINTF("pushing env %s (0x%x)\n", (char*)env
[i
], (int)env
[i
]);
805 stl(stack
, (int)env
[i
]);
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
);
812 /* Add on the stack the interp_prefix choosen if so */
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
);
819 stl(stack
, (int)dyld_root
);
823 #ifdef DONT_USE_DYLD_SHARED_MAP
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
);
829 stl(stack
, (int)shared_map_mode
);
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" };
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
);
846 DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env
[i
], (int)extra_env
[i
]);
847 stl(stack
, (int) extra_env
[i
]);
856 for(argc
= 0; argv
[argc
]; argc
++);
858 for(i
= argc
-1; i
>= 0; i
--)
860 DPRINTF("pushing arg %s (0x%x)\n", (char*)argv
[i
], (int)argv
[i
]);
861 stl(stack
, (int) argv
[i
]);
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
);
868 DPRINTF("pushing argc %d \n", argc
);
872 DPRINTF("pushing mh 0x%x \n", (int)mh
);
873 stl(stack
, (int) mh
);
875 /* Stack points on the mh */
876 return (unsigned long)stack
;
879 int mach_exec(const char * filename
, char ** argv
, char ** envp
,
880 struct target_pt_regs
* regs
)
882 int entrypoint
, stack
;
883 void * mh
; /* the Mach Header that will be used by dyld */
885 DPRINTF("mach_exec at 0x%x\n", (int)mach_exec
);
887 entrypoint
= load_object(filename
, regs
, &mh
);
888 stack
= setup_arg_pages(mh
, argv
, envp
);
889 #if defined(TARGET_I386)
890 regs
->eip
= entrypoint
;
892 #elif defined(TARGET_PPC)
893 regs
->nip
= entrypoint
;
894 regs
->gpr
[1] = stack
;
896 DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint
, stack
, (int)mh
);
899 qerror("%s: no entry point!\n", filename
);