Statistics
| Branch: | Revision:

root / darwin-user / machload.c @ 93fcfe39

History | View | Annotate | Download (26 kB)

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
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
19
 */
20
#include <stdio.h>
21
#include <sys/types.h>
22
#include <fcntl.h>
23
#include <sys/stat.h>
24
#include <errno.h>
25
#include <unistd.h>
26
#include <sys/mman.h>
27
#include <stdlib.h>
28
#include <string.h>
29

    
30
#include "qemu.h"
31
#include "disas.h"
32

    
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>
38

    
39
//#define DEBUG_MACHLOAD
40

    
41
#ifdef DEBUG_MACHLOAD
42
# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
43
#else
44
# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
45
#endif
46

    
47
# define check_mach_header(x) (x.magic == MH_CIGAM)
48

    
49
extern const char *interp_prefix;
50

    
51
/* we don't have a good implementation for this */
52
#define DONT_USE_DYLD_SHARED_MAP
53

    
54
/* Pass extra arg to DYLD for debug */
55
//#define ACTIVATE_DYLD_TRACE
56

    
57
//#define OVERRIDE_DYLINKER
58

    
59
#ifdef OVERRIDE_DYLINKER
60
# ifdef TARGET_I386
61
#  define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
62
# else
63
#  define DYLINKER_NAME "/usr/lib/dyld"
64
# endif
65
#endif
66

    
67
/* XXX: in an include */
68
struct nlist_extended
69
{
70
    union {
71
        char *n_name;
72
        long  n_strx;
73
    } n_un;
74
    unsigned char n_type;
75
    unsigned char n_sect;
76
    short st_desc;
77
    unsigned long st_value;
78
    unsigned long st_size;
79
};
80

    
81
/* Print symbols in gdb */
82
void *macho_text_sect = 0;
83
int   macho_offset = 0;
84

    
85
int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
86
void qerror(const char *format, ...);
87
#ifdef TARGET_I386
88
typedef struct mach_i386_thread_state {
89
    unsigned int    eax;
90
    unsigned int    ebx;
91
    unsigned int    ecx;
92
    unsigned int    edx;
93
    unsigned int    edi;
94
    unsigned int    esi;
95
    unsigned int    ebp;
96
    unsigned int    esp;
97
    unsigned int    ss;
98
    unsigned int    eflags;
99
    unsigned int    eip;
100
    unsigned int    cs;
101
    unsigned int    ds;
102
    unsigned int    es;
103
    unsigned int    fs;
104
    unsigned int    gs;
105
} mach_i386_thread_state_t;
106

    
107
void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
108
{
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);
125
}
126
#define target_thread_state mach_i386_thread_state
127
#define TARGET_CPU_TYPE CPU_TYPE_I386
128
#define TARGET_CPU_NAME "i386"
129
#endif
130

    
131
#ifdef TARGET_PPC
132
struct mach_ppc_thread_state {
133
    unsigned int srr0;      /* Instruction address register (PC) */
134
    unsigned int srr1;    /* Machine state register (supervisor) */
135
    unsigned int r0;
136
    unsigned int r1;
137
    unsigned int r2;
138
    unsigned int r3;
139
    unsigned int r4;
140
    unsigned int r5;
141
    unsigned int r6;
142
    unsigned int r7;
143
    unsigned int r8;
144
    unsigned int r9;
145
    unsigned int r10;
146
    unsigned int r11;
147
    unsigned int r12;
148
    unsigned int r13;
149
    unsigned int r14;
150
    unsigned int r15;
151
    unsigned int r16;
152
    unsigned int r17;
153
    unsigned int r18;
154
    unsigned int r19;
155
    unsigned int r20;
156
    unsigned int r21;
157
    unsigned int r22;
158
    unsigned int r23;
159
    unsigned int r24;
160
    unsigned int r25;
161
    unsigned int r26;
162
    unsigned int r27;
163
    unsigned int r28;
164
    unsigned int r29;
165
    unsigned int r30;
166
    unsigned int r31;
167

    
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) */
173

    
174
    unsigned int vrsave;    /* Vector Save Register */
175
};
176

    
177
void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
178
{
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);
213

    
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);
219

    
220
    bswap32s((uint32_t*)&ts->vrsave);
221
}
222

    
223
#define target_thread_state mach_ppc_thread_state
224
#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
225
#define TARGET_CPU_NAME "PowerPC"
226
#endif
227

    
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 */
234
};
235

    
236
void bswap_tc(struct target_thread_command *tc)
237
{
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);
244
#else
245
# error unknown TARGET_CPU_TYPE
246
#endif
247
}
248

    
249
void bswap_mh(struct mach_header *mh)
250
{
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);
258
}
259

    
260
void bswap_lc(struct load_command *lc)
261
{
262
    bswap32s((uint32_t*)&lc->cmd);
263
    bswap32s((uint32_t*)&lc->cmdsize);
264
}
265

    
266

    
267
void bswap_fh(struct fat_header *fh)
268
{
269
    bswap32s((uint32_t*)&fh->magic);
270
    bswap32s((uint32_t*)&fh->nfat_arch);
271
}
272

    
273
void bswap_fa(struct fat_arch *fa)
274
{
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);
280
}
281

    
282
void bswap_segcmd(struct segment_command *sc)
283
{
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);
292
}
293

    
294
void bswap_symtabcmd(struct symtab_command *stc)
295
{
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);
302
}
303

    
304
void bswap_sym(struct nlist *n)
305
{
306
    bswap32s((uint32_t*)&n->n_un.n_strx);
307
    bswap16s((uint16_t*)&n->n_desc);
308
    bswap32s((uint32_t*)&n->n_value);
309
}
310

    
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)
312
{
313
    int entry;
314
    if(need_bswap)
315
        bswap_tc(tc);
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
323
    if(regs)
324
    {
325
        reg_copy(eax);
326
        reg_copy(ebx);
327
        reg_copy(ecx);
328
        reg_copy(edx);
329

    
330
        reg_copy(edi);
331
        reg_copy(esi);
332

    
333
        reg_copy(ebp);
334
        reg_copy(esp);
335

    
336
        reg_copy(eflags);
337
        reg_copy(eip);
338
    /*
339
        reg_copy(ss);
340
        reg_copy(cs);
341
        reg_copy(ds);
342
        reg_copy(es);
343
        reg_copy(fs);
344
        reg_copy(gs);*/
345
    }
346
#undef reg_copy
347
#elif defined(TARGET_PPC)
348
    entry =  tc->state.srr0;
349
#endif
350
    DPRINTF("load_thread: entry 0x%x\n", entry);
351
    return entry;
352
}
353

    
354
int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
355
{
356
    int size;
357
    char * dylinker_name;
358
    size = dc->cmdsize - sizeof(struct dylinker_command);
359

    
360
    if(need_bswap)
361
        dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
362
    else
363
        dylinker_name = (char*)((dc->name.offset)+(int)dc);
364

    
365
#ifdef OVERRIDE_DYLINKER
366
    dylinker_name = DYLINKER_NAME;
367
#else
368
    if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
369
        qerror("can't allocate the new dylinker name\n");
370
#endif
371

    
372
    DPRINTF("dylinker_name %s\n", dylinker_name);
373
    return load_object(dylinker_name, NULL, NULL);
374
}
375

    
376
int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
377
{
378
    unsigned long addr = sc->vmaddr;
379
    unsigned long size = sc->filesize;
380
    unsigned long error = 0;
381

    
382
    if(need_bswap)
383
        bswap_segcmd(sc);
384

    
385
    if(sc->vmaddr == 0)
386
    {
387
        DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
388
        return -1;
389
    }
390

    
391
    if (strcmp(sc->segname, "__PAGEZERO") == 0)
392
    {
393
        DPRINTF("load_segment: __PAGEZERO returning\n");
394
        return -1;
395
    }
396

    
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);
400

    
401
    if(sc->filesize > 0)
402
    {
403
        int opt = 0;
404

    
405
        if(fixed)
406
            opt |= MAP_FIXED;
407

    
408
        DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
409

    
410
        addr = target_mmap(sc->vmaddr+slide, sc->filesize,  sc->initprot, opt, fd, mh_pos + sc->fileoff);
411

    
412
        if(addr==-1)
413
            qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
414

    
415
        error = addr-sc->vmaddr;
416
    }
417
    else
418
    {
419
        addr = sc->vmaddr+slide;
420
        error = slide;
421
    }
422

    
423
    if(sc->vmsize > sc->filesize)
424
    {
425
        addr += sc->filesize;
426
        size = sc->vmsize-sc->filesize;
427
        addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
428
        if(addr==-1)
429
            qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
430
    }
431

    
432
    return error;
433
}
434

    
435
void *load_data(int fd, long offset, unsigned int size)
436
{
437
    char *data;
438

    
439
    data = malloc(size);
440
    if (!data)
441
        return NULL;
442
    lseek(fd, offset, SEEK_SET);
443
    if (read(fd, data, size) != size) {
444
        free(data);
445
        return NULL;
446
    }
447
    return data;
448
}
449

    
450
/* load a mach-o object file */
451
int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
452
{
453
    int need_bswap = 0;
454
    int entry_point = 0;
455
    int dyld_entry_point = 0;
456
    int slide, mmapfixed;
457
    int fd;
458
    struct load_command *lcmds, *lc;
459
    int is_fat = 0;
460
    unsigned int i, magic;
461
    int mach_hdr_pos = 0;
462
    struct mach_header mach_hdr;
463

    
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;
468
    char            *strtab;
469

    
470
    fd = open(filename, O_RDONLY);
471
    if (fd < 0)
472
        qerror("can't open file '%s'", filename);
473

    
474
    /* Read magic header.  */
475
    if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
476
        qerror("unable to read Magic of '%s'", filename);
477

    
478
    /* Check Mach identification.  */
479
    if(magic == MH_MAGIC)
480
    {
481
        is_fat = 0;
482
        need_bswap = 0;
483
    } else if (magic == MH_CIGAM)
484
    {
485
        is_fat = 0;
486
        need_bswap = 1;
487
    } else if (magic == FAT_MAGIC)
488
    {
489
        is_fat = 1;
490
        need_bswap = 0;
491
    } else if (magic == FAT_CIGAM)
492
    {
493
        is_fat = 1;
494
        need_bswap = 1;
495
    }
496
    else
497
        qerror("Not a Mach-O file.", filename);
498

    
499
    DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
500
    if(is_fat)
501
    {
502
        int found = 0;
503
        struct fat_header fh;
504
        struct fat_arch *fa;
505

    
506
        lseek(fd, 0, SEEK_SET);
507

    
508
        /* Read Fat header.  */
509
        if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
510
            qerror("unable to read file header");
511

    
512
        if(need_bswap)
513
            bswap_fh(&fh);
514

    
515
        /* Read Fat Arch.  */
516
        fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
517

    
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");
520

    
521
        for( i = 0; i < fh.nfat_arch; i++, fa++)
522
        {
523
            if(need_bswap)
524
                bswap_fa(fa);
525
            if(fa->cputype == TARGET_CPU_TYPE)
526
            {
527
                mach_hdr_pos = fa->offset;
528
                lseek(fd, mach_hdr_pos, SEEK_SET);
529

    
530
                /* Read Mach header.  */
531

    
532
                if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
533
                    qerror("unable to read file header");
534

    
535
                if(mach_hdr.magic == MH_MAGIC)
536
                    need_bswap = 0;
537
                else if (mach_hdr.magic == MH_CIGAM)
538
                    need_bswap = 1;
539
                else
540
                    qerror("Invalid mach header in Fat Mach-O File");
541
                found = 1;
542
                break;
543
            }
544
        }
545
        if(!found)
546
            qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
547
    }
548
    else
549
    {
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);
554
    }
555

    
556
    if(need_bswap)
557
        bswap_mh(&mach_hdr);
558

    
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);
561

    
562

    
563
    switch(mach_hdr.filetype)
564
    {
565
        case MH_EXECUTE:  break;
566
        case MH_FVMLIB:
567
        case MH_DYLIB:
568
        case MH_DYLINKER: break;
569
        default:
570
            qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
571
    }
572

    
573
    /* read segment headers */
574
    lcmds = malloc(mach_hdr.sizeofcmds);
575

    
576
    if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
577
            qerror("%s: unable to read load_command", filename);
578
    slide = 0;
579
    mmapfixed = 0;
580
    for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
581
    {
582

    
583
        if(need_bswap)
584
            bswap_lc(lc);
585
        switch(lc->cmd)
586
        {
587
            case LC_SEGMENT:
588
                /* The main_exe can't be relocated */
589
                if(mach_hdr.filetype == MH_EXECUTE)
590
                    mmapfixed = 1;
591

    
592
                slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
593

    
594
                /* other segment must be mapped according to slide exactly, if load_segment did something */
595
                if(slide != -1)
596
                    mmapfixed = 1;
597
                else
598
                    slide = 0; /* load_segment didn't map the segment */
599

    
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);
602

    
603
                if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
604
                {
605
                    /* Text section */
606
                    if(mach_hdr.filetype == MH_EXECUTE)
607
                    {
608
                        /* return the mach_header */
609
                        *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
610
                    }
611
                    else
612
                    {
613
                        /* it is dyld save the section for gdb, we will be interested in dyld symbol
614
                           while debuging */
615
                        macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
616
                        macho_offset = slide;
617
                    }
618
                }
619
                break;
620
            case LC_LOAD_DYLINKER:
621
                dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
622
                break;
623
            case LC_LOAD_DYLIB:
624
                /* dyld will do that for us */
625
                break;
626
            case LC_THREAD:
627
            case LC_UNIXTHREAD:
628
                {
629
                struct target_pt_regs * _regs;
630
                if(mach_hdr.filetype == MH_DYLINKER)
631
                    _regs = regs;
632
                else
633
                    _regs = 0;
634
                entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
635
                }
636
                break;
637
            case LC_SYMTAB:
638
                /* Save the symtab and strtab */
639
                symtabcmd = (struct symtab_command *)lc;
640
                break;
641
            case LC_ID_DYLINKER:
642
            case LC_ID_DYLIB:
643
            case LC_UUID:
644
            case LC_DYSYMTAB:
645
            case LC_TWOLEVEL_HINTS:
646
            case LC_PREBIND_CKSUM:
647
            case LC_SUB_LIBRARY:
648
                break;
649
            default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
650
        }
651
        lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
652
    }
653

    
654
    if(symtabcmd)
655
    {
656
        if(need_bswap)
657
            bswap_symtabcmd(symtabcmd);
658

    
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);
661

    
662
        symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
663

    
664
        if(need_bswap)
665
        {
666
            for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
667
                bswap_sym(syment);
668
        }
669

    
670
        for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
671
        {
672
            struct nlist *sym_follow, *sym_next = 0;
673
            unsigned int j;
674
            memset(sym, 0, sizeof(*sym));
675

    
676
            sym->n_type = syment->n_type;
677
            if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
678
                continue;
679

    
680
            memcpy(sym, syment, sizeof(*syment));
681

    
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))
685
                    continue;
686
                if(!sym_next) {
687
                    sym_next = sym_follow;
688
                    continue;
689
                }
690
                if(!(sym_next->n_value > sym_follow->n_value))
691
                    continue;
692
                sym_next = sym_follow;
693
            }
694
            if(sym_next)
695
                sym->st_size = sym_next->n_value - sym->st_value;
696
            else
697
                sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
698

    
699
            sym->st_value += slide;
700
        }
701

    
702
        free((void*)symtab_std);
703

    
704
        {
705
            DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
706
            struct syminfo *s;
707
            s = malloc(sizeof(*s));
708
            s->disas_symtab = symtab;
709
            s->disas_strtab = strtab;
710
            s->disas_num_syms = symtabcmd->nsyms;
711
            s->next = syminfos;
712
            syminfos = s;
713
        }
714
    }
715
    close(fd);
716
    if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
717
        return dyld_entry_point;
718
    else
719
        return entry_point+slide;
720
}
721

    
722
extern unsigned long stack_size;
723

    
724
unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
725
{
726
    unsigned long stack_base, error, size;
727
    int i;
728
    int * stack;
729
    int argc, envc;
730

    
731
    /* Create enough stack to hold everything.  If we don't use
732
     * it for args, we'll use it for something else...
733
     */
734
    size = stack_size;
735

    
736
    error = target_mmap(0,
737
                        size + qemu_host_page_size,
738
                        PROT_READ | PROT_WRITE,
739
                        MAP_PRIVATE | MAP_ANONYMOUS,
740
                        -1, 0);
741
    if (error == -1)
742
        qerror("stk mmap");
743

    
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);
746

    
747
    stack_base = error + size;
748
    stack = (void*)stack_base;
749
/*
750
 *    | STRING AREA |
751
 *    +-------------+
752
 *    |      0      |
753
*    +-------------+
754
 *    |  apple[n]   |
755
 *    +-------------+
756
 *           :
757
 *    +-------------+
758
 *    |  apple[0]   |
759
 *    +-------------+
760
 *    |      0      |
761
 *    +-------------+
762
 *    |    env[n]   |
763
 *    +-------------+
764
 *           :
765
 *           :
766
 *    +-------------+
767
 *    |    env[0]   |
768
 *    +-------------+
769
 *    |      0      |
770
 *    +-------------+
771
 *    | arg[argc-1] |
772
 *    +-------------+
773
 *           :
774
 *           :
775
 *    +-------------+
776
 *    |    arg[0]   |
777
 *    +-------------+
778
 *    |     argc    |
779
 *    +-------------+
780
 * sp->    |      mh     | address of where the a.out's file offset 0 is in memory
781
 *    +-------------+
782
*/
783
    /* Construct the stack Stack grows down */
784
    stack--;
785

    
786
    /* XXX: string should go up there */
787

    
788
    *stack = 0;
789
    stack--;
790

    
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]);
794

    
795
    stack--;
796

    
797
    stl(stack, 0);
798
    stack--;
799

    
800
    /* Get envc */
801
    for(envc = 0; env[envc]; envc++);
802

    
803
    for(i = envc-1; i >= 0; i--)
804
    {
805
        DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
806
        stl(stack, (int)env[i]);
807
        stack--;
808

    
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);
811
    }
812

    
813
    /* Add on the stack the interp_prefix choosen if so */
814
    if(interp_prefix[0])
815
    {
816
        char *dyld_root;
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);
819

    
820
        stl(stack, (int)dyld_root);
821
        stack--;
822
    }
823

    
824
#ifdef DONT_USE_DYLD_SHARED_MAP
825
    {
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);
829

    
830
        stl(stack, (int)shared_map_mode);
831
        stack--;
832
    }
833
#endif
834

    
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" };
840

    
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);
844

    
845
    for(i = 0; i<9; i++)
846
    {
847
        DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
848
        stl(stack, (int) extra_env[i]);
849
        stack--;
850
    }
851
#endif
852

    
853
    stl(stack, 0);
854
    stack--;
855

    
856
    /* Get argc */
857
    for(argc = 0; argv[argc]; argc++);
858

    
859
    for(i = argc-1; i >= 0; i--)
860
    {
861
        DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
862
        stl(stack, (int) argv[i]);
863
        stack--;
864

    
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);
867
    }
868

    
869
    DPRINTF("pushing argc %d \n", argc);
870
    stl(stack, argc);
871
    stack--;
872

    
873
    DPRINTF("pushing mh 0x%x \n", (int)mh);
874
    stl(stack, (int) mh);
875

    
876
    /* Stack points on the mh */
877
    return (unsigned long)stack;
878
}
879

    
880
int mach_exec(const char * filename, char ** argv, char ** envp,
881
             struct target_pt_regs * regs)
882
{
883
    int entrypoint, stack;
884
    void * mh; /* the Mach Header that will be  used by dyld */
885

    
886
    DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
887

    
888
    entrypoint = load_object(filename, regs, &mh);
889
    stack = setup_arg_pages(mh, argv, envp);
890
#if defined(TARGET_I386)
891
    regs->eip = entrypoint;
892
    regs->esp = stack;
893
#elif defined(TARGET_PPC)
894
    regs->nip = entrypoint;
895
    regs->gpr[1] = stack;
896
#endif
897
    DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
898

    
899
    if(!entrypoint)
900
        qerror("%s: no entry point!\n", filename);
901

    
902
    return 0;
903
}