Annotation of XNU/bsd/kern/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: #if !defined(KERNEL_PRELOAD)
                     37: #include <kern/mach_header.h>
                     38: 
                     39: extern struct mach_header _mh_execute_header;
                     40: 
                     41: struct section *getsectbynamefromheader(
                     42:        struct mach_header      *header,
                     43:        char                    *seg_name,
                     44:        char                    *sect_name);
                     45: struct segment_command *getsegbynamefromheader(
                     46:        struct mach_header      *header,
                     47:        char                    *seg_name);
                     48: 
                     49: /*
                     50:  * return the last address (first avail)
                     51:  */
                     52: vm_offset_t getlastaddr(void)
                     53: {
                     54:        struct segment_command  *sgp;
                     55:        vm_offset_t             last_addr = 0;
                     56:        struct mach_header *header = &_mh_execute_header;
                     57:        int i;
                     58: 
                     59:        sgp = (struct segment_command *)
                     60:                ((char *)header + sizeof(struct mach_header));
                     61:        for (i = 0; i < header->ncmds; i++){
                     62:                if (   sgp->cmd == LC_SEGMENT) {
                     63:                        if (sgp->vmaddr + sgp->vmsize > last_addr)
                     64:                                last_addr = sgp->vmaddr + sgp->vmsize;
                     65:                }
                     66:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                     67:        }
                     68:        return last_addr;
                     69: }
                     70: 
                     71: #if FIXME  /* [ */
                     72: struct mach_header **
                     73: getmachheaders(void)
                     74: {
                     75:        extern struct mach_header _mh_execute_header;
                     76:        struct mach_header **tl;
                     77:        tl = (struct mach_header **)malloc(2*sizeof(struct mach_header *));
                     78:        tl[0] = &_mh_execute_header;
                     79:        tl[1] = (struct mach_header *)0;
                     80:        return tl;
                     81: }
                     82: #endif  /* FIXME ] */
                     83: 
                     84: /*
                     85:  * This routine returns the a pointer to the data for the named section in the
                     86:  * named segment if it exist in the mach header passed to it.  Also it returns
                     87:  * the size of the section data indirectly through the pointer size.  Otherwise
                     88:  *  it returns zero for the pointer and the size.
                     89:  */
                     90: void *
                     91: getsectdatafromheader(
                     92:     struct mach_header *mhp,
                     93:     char *segname,
                     94:     char *sectname,
                     95:     int *size)
                     96: {              
                     97:        const struct section *sp;
                     98:        void *result;
                     99: 
                    100:        sp = getsectbynamefromheader(mhp, segname, sectname);
                    101:        if(sp == (struct section *)0){
                    102:            *size = 0;
                    103:            return((char *)0);
                    104:        }
                    105:        *size = sp->size;
                    106:        result = (void *)sp->addr;
                    107:        return result;
                    108: }
                    109: 
                    110: /*
                    111:  * This routine returns the a pointer to the data for the named segment
                    112:  * if it exist in the mach header passed to it.  Also it returns
                    113:  * the size of the segment data indirectly through the pointer size.
                    114:  * Otherwise it returns zero for the pointer and the size.
                    115:  */
                    116: void *
                    117: getsegdatafromheader(
                    118:     struct mach_header *mhp,
                    119:        char *segname,
                    120:        int *size)
                    121: {
                    122:        const struct segment_command *sc;
                    123:        void *result;
                    124: 
                    125:        sc = getsegbynamefromheader(mhp, segname);
                    126:        if(sc == (struct segment_command *)0){
                    127:            *size = 0;
                    128:            return((char *)0);
                    129:        }
                    130:        *size = sc->vmsize;
                    131:        result = (void *)sc->vmaddr;
                    132:        return result;
                    133: }
                    134: 
                    135: /*
                    136:  * This routine returns the section structure for the named section in the
                    137:  * named segment for the mach_header pointer passed to it if it exist.
                    138:  * Otherwise it returns zero.
                    139:  */
                    140: struct section *
                    141: getsectbynamefromheader(
                    142:     struct mach_header *mhp,
                    143:     char *segname,
                    144:     char *sectname)
                    145: {
                    146:        struct segment_command *sgp;
                    147:        struct section *sp;
                    148:        long i, j;
                    149: 
                    150:        sgp = (struct segment_command *)
                    151:              ((char *)mhp + sizeof(struct mach_header));
                    152:        for(i = 0; i < mhp->ncmds; i++){
                    153:            if(sgp->cmd == LC_SEGMENT)
                    154:                if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
                    155:                   mhp->filetype == MH_OBJECT){
                    156:                    sp = (struct section *)((char *)sgp +
                    157:                         sizeof(struct segment_command));
                    158:                    for(j = 0; j < sgp->nsects; j++){
                    159:                        if(strncmp(sp->sectname, sectname,
                    160:                           sizeof(sp->sectname)) == 0 &&
                    161:                           strncmp(sp->segname, segname,
                    162:                           sizeof(sp->segname)) == 0)
                    163:                            return(sp);
                    164:                        sp = (struct section *)((char *)sp +
                    165:                             sizeof(struct section));
                    166:                    }
                    167:                }
                    168:            sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    169:        }
                    170:        return((struct section *)0);
                    171: }
                    172: 
                    173: struct segment_command *getsegbynamefromheader(
                    174:        struct mach_header      *header,
                    175:        char                    *seg_name)
                    176: {
                    177:        struct segment_command *sgp;
                    178:        int i;
                    179: 
                    180:        sgp = (struct segment_command *)
                    181:                ((char *)header + sizeof(struct mach_header));
                    182:        for (i = 0; i < header->ncmds; i++){
                    183:                if (   sgp->cmd == LC_SEGMENT
                    184:                    && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
                    185:                        return sgp;
                    186:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    187:        }
                    188:        return (struct segment_command *)0;
                    189: }
                    190: 
                    191: 
                    192: /*
                    193:  * For now at least, all the rest of this seems unused.
                    194:  * NOTE: The constant in here for segment alignment is machine-dependent,
                    195:  * so if you include this, define a machine dependent constant for it's
                    196:  * value.
                    197:  */
                    198: static struct {
                    199:        struct segment_command  seg;
                    200:        struct section          sect;
                    201: } fvm_data = {
                    202:        {
                    203:                LC_SEGMENT,             // cmd
                    204:                sizeof(fvm_data),       // cmdsize
                    205:                "__USER",               // segname
                    206:                0,                      // vmaddr
                    207:                0,                      // vmsize
                    208:                0,                      // fileoff
                    209:                0,                      // filesize
                    210:                VM_PROT_READ,           // maxprot
                    211:                VM_PROT_READ,           // initprot,
                    212:                1,                      // nsects
                    213:                0                       // flags
                    214:        },
                    215:        {
                    216:                "",                     // sectname
                    217:                "__USER",               // segname
                    218:                0,                      // addr
                    219:                0,                      // size
                    220:                0,                      // offset
                    221:                4,                      // align
                    222:                0,                      // reloff
                    223:                0,                      // nreloc
                    224:                0                       // flags
                    225:        }
                    226: };
                    227: 
                    228: struct segment_command *fvm_seg;
                    229: 
                    230: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
                    231: static vm_offset_t getsizeofmacho(struct mach_header *header);
                    232: 
                    233: /*
                    234:  * Return the first segment_command in the header.
                    235:  */
                    236: struct segment_command *firstseg(void)
                    237: {
                    238:        return firstsegfromheader(&_mh_execute_header);
                    239: }
                    240: 
                    241: struct segment_command *firstsegfromheader(struct mach_header *header)
                    242: {
                    243:        struct segment_command *sgp;
                    244:        int i;
                    245: 
                    246:        sgp = (struct segment_command *)
                    247:                ((char *)header + sizeof(struct mach_header));
                    248:        for (i = 0; i < header->ncmds; i++){
                    249:                if (sgp->cmd == LC_SEGMENT)
                    250:                        return sgp;
                    251:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    252:        }
                    253:        return (struct segment_command *)0;
                    254: }
                    255: 
                    256: struct segment_command *nextseg(struct segment_command *sgp)
                    257: {
                    258:        struct segment_command *this;
                    259: 
                    260:        this = nextsegfromheader(&_mh_execute_header, sgp);
                    261: 
                    262:        /*
                    263:         * For the kernel's header add on the faked segment for the
                    264:         * USER boot code identified by a FVMFILE_COMMAND in the mach header.
                    265:         */
                    266:        if (!this && sgp != fvm_seg)
                    267:                this = fvm_seg;
                    268: 
                    269:        return this;
                    270: }
                    271: 
                    272: struct segment_command *nextsegfromheader(
                    273:        struct mach_header      *header,
                    274:        struct segment_command  *seg)
                    275: {
                    276:        struct segment_command *sgp;
                    277:        int i;
                    278: 
                    279:        sgp = (struct segment_command *)
                    280:                ((char *)header + sizeof(struct mach_header));
                    281:        for (i = 0; i < header->ncmds; i++) {
                    282:                if (sgp == seg)
                    283:                        break;
                    284:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    285:        }
                    286: 
                    287:        if (i == header->ncmds)
                    288:                return (struct segment_command *)0;
                    289: 
                    290:        sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    291:        for (; i < header->ncmds; i++) {
                    292:                if (sgp->cmd == LC_SEGMENT)
                    293:                        return sgp;
                    294:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    295:        }
                    296: 
                    297:        return (struct segment_command *)0;
                    298: }
                    299: 
                    300: 
                    301: /*
                    302:  * Return the address of the named Mach-O segment, or NULL.
                    303:  */
                    304: struct segment_command *getsegbyname(char *seg_name)
                    305: {
                    306:        struct segment_command *this;
                    307: 
                    308:        this = getsegbynamefromheader(&_mh_execute_header, seg_name);
                    309: 
                    310:        /*
                    311:         * For the kernel's header add on the faked segment for the
                    312:         * USER boot code identified by a FVMFILE_COMMAND in the mach header.
                    313:         */
                    314:        if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
                    315:                this = fvm_seg;
                    316: 
                    317:        return this;
                    318: }
                    319: 
                    320: /*
                    321:  * This routine returns the a pointer the section structure of the named
                    322:  * section in the named segment if it exist in the mach executable it is
                    323:  * linked into.  Otherwise it returns zero.
                    324:  */
                    325: struct section *
                    326: getsectbyname(
                    327:     char *segname,
                    328:     char *sectname)
                    329: {
                    330:        return(getsectbynamefromheader(
                    331:                (struct mach_header *)&_mh_execute_header, segname, sectname));
                    332: }
                    333: 
                    334: struct section *firstsect(struct segment_command *sgp)
                    335: {
                    336:        struct section *sp;
                    337: 
                    338:        if (!sgp || sgp->nsects == 0)
                    339:                return (struct section *)0;
                    340: 
                    341:        return (struct section *)(sgp+1);
                    342: }
                    343: 
                    344: struct section *nextsect(struct segment_command *sgp, struct section *sp)
                    345: {
                    346:        struct section *fsp = firstsect(sgp);
                    347: 
                    348:        if (sp - fsp >= sgp->nsects-1)
                    349:                return (struct section *)0;
                    350: 
                    351:        return sp+1;
                    352: }
                    353: 
                    354: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
                    355: {
                    356:        struct fvmfile_command *fvp;
                    357:        int i;
                    358: 
                    359:        fvp = (struct fvmfile_command *)
                    360:                ((char *)header + sizeof(struct mach_header));
                    361:        for (i = 0; i < header->ncmds; i++){
                    362:                if (fvp->cmd == LC_FVMFILE)
                    363:                        return fvp;
                    364:                fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
                    365:        }
                    366:        return (struct fvmfile_command *)0;
                    367: }
                    368: 
                    369: /*
                    370:  * Create a fake USER seg if a fvmfile_command is present.
                    371:  */
                    372: struct segment_command *getfakefvmseg(void)
                    373: {
                    374:        struct segment_command *sgp = getsegbyname("__USER");
                    375:        struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
                    376:        struct section *sp;
                    377: 
                    378:        if (sgp)
                    379:                return sgp;
                    380: 
                    381:        if (!fvp)
                    382:                return (struct segment_command *)0;
                    383: 
                    384:        fvm_seg = &fvm_data.seg;
                    385:        sgp = fvm_seg;
                    386:        sp = &fvm_data.sect;
                    387: 
                    388:        sgp->vmaddr = fvp->header_addr;
                    389:        sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
                    390: 
                    391:        strcpy(sp->sectname, fvp->name.ptr);
                    392:        sp->addr = sgp->vmaddr;
                    393:        sp->size = sgp->vmsize;
                    394: 
                    395: #if    DEBUG
                    396:        printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
                    397:                sp->sectname, sp->addr, sp->size);
                    398: #endif DEBUG
                    399: }
                    400: 
                    401: /*
                    402:  * Figure out the size the size of the data associated with a
                    403:  * loaded mach_header.
                    404:  */
                    405: static vm_offset_t getsizeofmacho(struct mach_header *header)
                    406: {
                    407:        struct segment_command  *sgp;
                    408:        struct section          *sp;
                    409:        vm_offset_t             last_addr;
                    410: 
                    411:        last_addr = 0;
                    412:        for (  sgp = firstsegfromheader(header)
                    413:            ; sgp
                    414:            ; sgp = nextsegfromheader(header, sgp))
                    415:        {
                    416:                if (sgp->fileoff + sgp->filesize > last_addr)
                    417:                        last_addr = sgp->fileoff + sgp->filesize;
                    418:        }
                    419: 
                    420:        return last_addr;
                    421: }
                    422: #endif  /* !defined(KERNEL_PRELOAD) */

unix.superglobalmegacorp.com

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