Annotation of qemu/darwin-user/machload.c, revision 1.1

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
        !            17:  * License along with this library; if not, write to the Free Software
        !            18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
        !            43: #else
        !            44: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.