Annotation of XNU/osfmk/mach-o/mach_header.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  *     File: kern/mach_header.c
                     24:  *
                     25:  *     Functions for accessing mach-o headers.
                     26:  *
                     27:  * HISTORY
                     28:  * 27-MAR-97  Umesh Vaishampayan ([email protected])
                     29:  *     Added getsegdatafromheader();
                     30:  *
                     31:  * 29-Jan-92  Mike DeMoney ([email protected])
                     32:  *     Made into machine independent form from machdep/m68k/mach_header.c.
                     33:  *     Ifdef'ed out most of this since I couldn't find any references.
                     34:  */
                     35: 
                     36: #include <vm/vm_map.h>
                     37: #include <vm/vm_kern.h>
                     38: #include <mach-o/mach_header.h>
                     39: 
                     40: #ifdef __MACHO__
                     41: 
                     42: extern struct mach_header _mh_execute_header;
                     43: 
                     44: struct section *getsectbynamefromheader(
                     45:        struct mach_header      *header,
                     46:        char                    *seg_name,
                     47:        char                    *sect_name);
                     48: struct segment_command *getsegbynamefromheader(
                     49:        struct mach_header      *header,
                     50:        char                    *seg_name);
                     51: 
                     52: /*
                     53:  * return the last address (first avail)
                     54:  */
                     55: #ifdef MACH_BSD
                     56: __private_extern__
                     57: #endif
                     58: vm_offset_t getlastaddr(void)
                     59: {
                     60:        struct segment_command  *sgp;
                     61:        vm_offset_t             last_addr = 0;
                     62:        struct mach_header *header = &_mh_execute_header;
                     63:        int i;
                     64: 
                     65:        sgp = (struct segment_command *)
                     66:                ((char *)header + sizeof(struct mach_header));
                     67:        for (i = 0; i < header->ncmds; i++){
                     68:                if (   sgp->cmd == LC_SEGMENT) {
                     69:                        if (sgp->vmaddr + sgp->vmsize > last_addr)
                     70:                                last_addr = sgp->vmaddr + sgp->vmsize;
                     71:                }
                     72:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                     73:        }
                     74:        return last_addr;
                     75: }
                     76: 
                     77: #ifdef XXX_MACH_BSD
                     78: __private_extern__
                     79: #endif
                     80: struct mach_header **
                     81: getmachheaders(void)
                     82: {
                     83:        extern struct mach_header _mh_execute_header;
                     84:        struct mach_header **tl;
                     85:        
                     86:        if (kmem_alloc(kernel_map, (vm_offset_t *) &tl, 2*sizeof(struct mach_header *)) != KERN_SUCCESS)
                     87:                return  NULL;
                     88: 
                     89:        tl[0] = &_mh_execute_header;
                     90:        tl[1] = (struct mach_header *)0;
                     91:        return tl;
                     92: }
                     93: 
                     94: /*
                     95:  * This routine returns the a pointer to the data for the named section in the
                     96:  * named segment if it exist in the mach header passed to it.  Also it returns
                     97:  * the size of the section data indirectly through the pointer size.  Otherwise
                     98:  *  it returns zero for the pointer and the size.
                     99:  */
                    100: #ifdef MACH_BSD
                    101: __private_extern__
                    102: #endif
                    103: void *
                    104: getsectdatafromheader(
                    105:     struct mach_header *mhp,
                    106:     char *segname,
                    107:     char *sectname,
                    108:     int *size)
                    109: {              
                    110:        const struct section *sp;
                    111:        void *result;
                    112: 
                    113:        sp = getsectbynamefromheader(mhp, segname, sectname);
                    114:        if(sp == (struct section *)0){
                    115:            *size = 0;
                    116:            return((char *)0);
                    117:        }
                    118:        *size = sp->size;
                    119:        result = (void *)sp->addr;
                    120:        return result;
                    121: }
                    122: 
                    123: /*
                    124:  * This routine returns the a pointer to the data for the named segment
                    125:  * if it exist in the mach header passed to it.  Also it returns
                    126:  * the size of the segment data indirectly through the pointer size.
                    127:  * Otherwise it returns zero for the pointer and the size.
                    128:  */
                    129: #ifdef MACH_BSD
                    130: __private_extern__
                    131: #endif
                    132: void *
                    133: getsegdatafromheader(
                    134:     struct mach_header *mhp,
                    135:        char *segname,
                    136:        int *size)
                    137: {
                    138:        const struct segment_command *sc;
                    139:        void *result;
                    140: 
                    141:        sc = getsegbynamefromheader(mhp, segname);
                    142:        if(sc == (struct segment_command *)0){
                    143:            *size = 0;
                    144:            return((char *)0);
                    145:        }
                    146:        *size = sc->vmsize;
                    147:        result = (void *)sc->vmaddr;
                    148:        return result;
                    149: }
                    150: 
                    151: /*
                    152:  * This routine returns the section structure for the named section in the
                    153:  * named segment for the mach_header pointer passed to it if it exist.
                    154:  * Otherwise it returns zero.
                    155:  */
                    156: #ifdef MACH_BSD
                    157: __private_extern__
                    158: #endif
                    159: struct section *
                    160: getsectbynamefromheader(
                    161:     struct mach_header *mhp,
                    162:     char *segname,
                    163:     char *sectname)
                    164: {
                    165:        struct segment_command *sgp;
                    166:        struct section *sp;
                    167:        long i, j;
                    168: 
                    169:        sgp = (struct segment_command *)
                    170:              ((char *)mhp + sizeof(struct mach_header));
                    171:        for(i = 0; i < mhp->ncmds; i++){
                    172:            if(sgp->cmd == LC_SEGMENT)
                    173:                if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
                    174:                   mhp->filetype == MH_OBJECT){
                    175:                    sp = (struct section *)((char *)sgp +
                    176:                         sizeof(struct segment_command));
                    177:                    for(j = 0; j < sgp->nsects; j++){
                    178:                        if(strncmp(sp->sectname, sectname,
                    179:                           sizeof(sp->sectname)) == 0 &&
                    180:                           strncmp(sp->segname, segname,
                    181:                           sizeof(sp->segname)) == 0)
                    182:                            return(sp);
                    183:                        sp = (struct section *)((char *)sp +
                    184:                             sizeof(struct section));
                    185:                    }
                    186:                }
                    187:            sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    188:        }
                    189:        return((struct section *)0);
                    190: }
                    191: 
                    192: #ifdef MACH_BSD
                    193: __private_extern__
                    194: #endif
                    195: struct segment_command *getsegbynamefromheader(
                    196:        struct mach_header      *header,
                    197:        char                    *seg_name)
                    198: {
                    199:        struct segment_command *sgp;
                    200:        int i;
                    201: 
                    202:        sgp = (struct segment_command *)
                    203:                ((char *)header + sizeof(struct mach_header));
                    204:        for (i = 0; i < header->ncmds; i++){
                    205:                if (   sgp->cmd == LC_SEGMENT
                    206:                    && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
                    207:                        return sgp;
                    208:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    209:        }
                    210:        return (struct segment_command *)0;
                    211: }
                    212: 
                    213: 
                    214: /*
                    215:  * For now at least, all the rest of this seems unused.
                    216:  * NOTE: The constant in here for segment alignment is machine-dependent,
                    217:  * so if you include this, define a machine dependent constant for it's
                    218:  * value.
                    219:  */
                    220: static struct {
                    221:        struct segment_command  seg;
                    222:        struct section          sect;
                    223: } fvm_data = {
                    224:        {
                    225:                LC_SEGMENT,             // cmd
                    226:                sizeof(fvm_data),       // cmdsize
                    227:                "__USER",               // segname
                    228:                0,                      // vmaddr
                    229:                0,                      // vmsize
                    230:                0,                      // fileoff
                    231:                0,                      // filesize
                    232:                VM_PROT_READ,           // maxprot
                    233:                VM_PROT_READ,           // initprot,
                    234:                1,                      // nsects
                    235:                0                       // flags
                    236:        },
                    237:        {
                    238:                "",                     // sectname
                    239:                "__USER",               // segname
                    240:                0,                      // addr
                    241:                0,                      // size
                    242:                0,                      // offset
                    243:                4,                      // align
                    244:                0,                      // reloff
                    245:                0,                      // nreloc
                    246:                0                       // flags
                    247:        }
                    248: };
                    249: 
                    250: #ifdef MACH_BSD
                    251: static
                    252: #endif
                    253: struct segment_command *fvm_seg;
                    254: 
                    255: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
                    256: static vm_offset_t getsizeofmacho(struct mach_header *header);
                    257: 
                    258: /*
                    259:  * Return the first segment_command in the header.
                    260:  */
                    261: #ifdef MACH_BSD
                    262: __private_extern__
                    263: #endif
                    264: struct segment_command *firstseg(void)
                    265: {
                    266:        return firstsegfromheader(&_mh_execute_header);
                    267: }
                    268: 
                    269: #ifdef MACH_BSD
                    270: __private_extern__
                    271: #endif
                    272: struct segment_command *firstsegfromheader(struct mach_header *header)
                    273: {
                    274:        struct segment_command *sgp;
                    275:        int i;
                    276: 
                    277:        sgp = (struct segment_command *)
                    278:                ((char *)header + sizeof(struct mach_header));
                    279:        for (i = 0; i < header->ncmds; i++){
                    280:                if (sgp->cmd == LC_SEGMENT)
                    281:                        return sgp;
                    282:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    283:        }
                    284:        return (struct segment_command *)0;
                    285: }
                    286: 
                    287: #ifdef MACH_BSD
                    288: __private_extern__
                    289: #endif
                    290: struct segment_command *nextseg(struct segment_command *sgp)
                    291: {
                    292:        struct segment_command *this;
                    293: 
                    294:        this = nextsegfromheader(&_mh_execute_header, sgp);
                    295: 
                    296:        /*
                    297:         * For the kernel's header add on the faked segment for the
                    298:         * USER boot code identified by a FVMFILE_COMMAND in the mach header.
                    299:         */
                    300:        if (!this && sgp != fvm_seg)
                    301:                this = fvm_seg;
                    302: 
                    303:        return this;
                    304: }
                    305: 
                    306: #ifdef MACH_BSD
                    307: __private_extern__
                    308: #endif
                    309: struct segment_command *nextsegfromheader(
                    310:        struct mach_header      *header,
                    311:        struct segment_command  *seg)
                    312: {
                    313:        struct segment_command *sgp;
                    314:        int i;
                    315: 
                    316:        sgp = (struct segment_command *)
                    317:                ((char *)header + sizeof(struct mach_header));
                    318:        for (i = 0; i < header->ncmds; i++) {
                    319:                if (sgp == seg)
                    320:                        break;
                    321:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    322:        }
                    323: 
                    324:        if (i == header->ncmds)
                    325:                return (struct segment_command *)0;
                    326: 
                    327:        sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    328:        for (; i < header->ncmds; i++) {
                    329:                if (sgp->cmd == LC_SEGMENT)
                    330:                        return sgp;
                    331:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    332:        }
                    333: 
                    334:        return (struct segment_command *)0;
                    335: }
                    336: 
                    337: 
                    338: /*
                    339:  * Return the address of the named Mach-O segment, or NULL.
                    340:  */
                    341: #ifdef MACH_BSD
                    342: __private_extern__
                    343: #endif
                    344: struct segment_command *getsegbyname(char *seg_name)
                    345: {
                    346:        struct segment_command *this;
                    347: 
                    348:        this = getsegbynamefromheader(&_mh_execute_header, seg_name);
                    349: 
                    350:        /*
                    351:         * For the kernel's header add on the faked segment for the
                    352:         * USER boot code identified by a FVMFILE_COMMAND in the mach header.
                    353:         */
                    354:        if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
                    355:                this = fvm_seg;
                    356: 
                    357:        return this;
                    358: }
                    359: 
                    360: /*
                    361:  * This routine returns the a pointer the section structure of the named
                    362:  * section in the named segment if it exist in the mach executable it is
                    363:  * linked into.  Otherwise it returns zero.
                    364:  */
                    365: #ifdef MACH_BSD
                    366: __private_extern__
                    367: #endif
                    368: struct section *
                    369: getsectbyname(
                    370:     char *segname,
                    371:     char *sectname)
                    372: {
                    373:        return(getsectbynamefromheader(
                    374:                (struct mach_header *)&_mh_execute_header, segname, sectname));
                    375: }
                    376: 
                    377: #ifdef MACH_BSD
                    378: __private_extern__
                    379: #endif
                    380: struct section *firstsect(struct segment_command *sgp)
                    381: {
                    382:        struct section *sp;
                    383: 
                    384:        if (!sgp || sgp->nsects == 0)
                    385:                return (struct section *)0;
                    386: 
                    387:        return (struct section *)(sgp+1);
                    388: }
                    389: 
                    390: #ifdef MACH_BSD
                    391: __private_extern__
                    392: #endif
                    393: struct section *nextsect(struct segment_command *sgp, struct section *sp)
                    394: {
                    395:        struct section *fsp = firstsect(sgp);
                    396: 
                    397:        if (sp - fsp >= sgp->nsects-1)
                    398:                return (struct section *)0;
                    399: 
                    400:        return sp+1;
                    401: }
                    402: 
                    403: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
                    404: {
                    405:        struct fvmfile_command *fvp;
                    406:        int i;
                    407: 
                    408:        fvp = (struct fvmfile_command *)
                    409:                ((char *)header + sizeof(struct mach_header));
                    410:        for (i = 0; i < header->ncmds; i++){
                    411:                if (fvp->cmd == LC_FVMFILE)
                    412:                        return fvp;
                    413:                fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
                    414:        }
                    415:        return (struct fvmfile_command *)0;
                    416: }
                    417: 
                    418: /*
                    419:  * Create a fake USER seg if a fvmfile_command is present.
                    420:  */
                    421: #ifdef MACH_BSD
                    422: __private_extern__
                    423: #endif
                    424: struct segment_command *getfakefvmseg(void)
                    425: {
                    426:        struct segment_command *sgp = getsegbyname("__USER");
                    427:        struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
                    428:        struct section *sp;
                    429: 
                    430:        if (sgp)
                    431:                return sgp;
                    432: 
                    433:        if (!fvp)
                    434:                return (struct segment_command *)0;
                    435: 
                    436:        fvm_seg = &fvm_data.seg;
                    437:        sgp = fvm_seg;
                    438:        sp = &fvm_data.sect;
                    439: 
                    440:        sgp->vmaddr = fvp->header_addr;
                    441:        sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
                    442: 
                    443:        strcpy(sp->sectname, fvp->name.ptr);
                    444:        sp->addr = sgp->vmaddr;
                    445:        sp->size = sgp->vmsize;
                    446: 
                    447: #if    DEBUG
                    448:        printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
                    449:                sp->sectname, sp->addr, sp->size);
                    450: #endif /*DEBUG*/
                    451:        return sgp;
                    452: }
                    453: 
                    454: /*
                    455:  * Figure out the size the size of the data associated with a
                    456:  * loaded mach_header.
                    457:  */
                    458: static vm_offset_t getsizeofmacho(struct mach_header *header)
                    459: {
                    460:        struct segment_command  *sgp;
                    461:        struct section          *sp;
                    462:        vm_offset_t             last_addr;
                    463: 
                    464:        last_addr = 0;
                    465:        for (  sgp = firstsegfromheader(header)
                    466:            ; sgp
                    467:            ; sgp = nextsegfromheader(header, sgp))
                    468:        {
                    469:                if (sgp->fileoff + sgp->filesize > last_addr)
                    470:                        last_addr = sgp->fileoff + sgp->filesize;
                    471:        }
                    472: 
                    473:        return last_addr;
                    474: }
                    475: 
                    476: #ifdef MACH_KDB
                    477: /*
                    478:  * This routine returns the section command for the symbol table in the
                    479:  * named segment for the mach_header pointer passed to it if it exist.
                    480:  * Otherwise it returns zero.
                    481:  */
                    482: struct symtab_command *
                    483: getsectcmdsymtabfromheader(
                    484:        struct mach_header *mhp)
                    485: {
                    486:        struct segment_command *sgp;
                    487:        struct section *sp;
                    488:        long i;
                    489: 
                    490:        sgp = (struct segment_command *)
                    491:                ((char *)mhp + sizeof(struct mach_header));
                    492:        for(i = 0; i < mhp->ncmds; i++){
                    493:                if(sgp->cmd == LC_SYMTAB)
                    494:                return((struct symtab_command *)sgp);
                    495:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    496:        }
                    497:        return(NULL);
                    498: }
                    499: 
                    500: boolean_t getsymtab(struct mach_header *header,
                    501:                        vm_offset_t *symtab,
                    502:                        int *nsyms,
                    503:                        vm_offset_t *strtab,
                    504:                        vm_size_t *strtabsize)
                    505: {
                    506:        struct segment_command *seglink_cmd;
                    507:        struct symtab_command *symtab_cmd;
                    508: 
                    509:        seglink_cmd = NULL;
                    510:        
                    511:        if(header->magic != MH_MAGIC) {                                         /* Check if this is a valid header format */
                    512:                printf("Attempt to use invalid header (magic = %08X) to find symbol table\n", 
                    513:                        header->magic);                                                         /* Tell them what's wrong */
                    514:                return (FALSE);                                                                 /* Bye y'all... */
                    515:        }
                    516:        
                    517:        seglink_cmd = getsegbynamefromheader(header,"__LINKEDIT");
                    518:        if (seglink_cmd == NULL) {
                    519:                return(FALSE);
                    520:        }
                    521: 
                    522:        symtab_cmd = NULL;
                    523:        symtab_cmd = getsectcmdsymtabfromheader(header);
                    524:        if (symtab_cmd == NULL)
                    525:                return(FALSE);
                    526: 
                    527:        *nsyms = symtab_cmd->nsyms;
                    528:        if(symtab_cmd->nsyms == 0) return (FALSE);      /* No symbols */
                    529: 
                    530:        *strtabsize = symtab_cmd->strsize;
                    531:        if(symtab_cmd->strsize == 0) return (FALSE);    /* Symbol length is 0 */
                    532:        
                    533:        *symtab = seglink_cmd->vmaddr + symtab_cmd->symoff -
                    534:                seglink_cmd->fileoff;
                    535: 
                    536:        *strtab = seglink_cmd->vmaddr + symtab_cmd->stroff -
                    537:                        seglink_cmd->fileoff;
                    538: 
                    539:        return(TRUE);
                    540: }
                    541: #endif
                    542: 
                    543: #else
                    544: 
                    545: void * getsegdatafromheader( struct mach_header *mhp, char *segname, int *size)
                    546: {
                    547:        return  0;
                    548: }
                    549: 
                    550: #endif

unix.superglobalmegacorp.com

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