Annotation of kernel/kern/mach_header.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:  *     File: kern/mach_header.c
                     27:  *
                     28:  *     Functions for accessing mach-o headers.
                     29:  *
                     30:  * HISTORY
                     31:  * 27-MAR-97  Umesh Vaishampayan ([email protected])
                     32:  *     Added getsegdatafromheader();
                     33:  *
                     34:  * 29-Jan-92  Mike DeMoney ([email protected])
                     35:  *     Made into machine independent form from machdep/m68k/mach_header.c.
                     36:  *     Ifdef'ed out most of this since I couldn't find any references.
                     37:  */
                     38: 
                     39: #if !defined(KERNEL_PRELOAD)
                     40: #import <kern/mach_header.h>
                     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: vm_offset_t getlastaddr(void)
                     56: {
                     57:        struct segment_command  *sgp;
                     58:        vm_offset_t             last_addr = 0;
                     59:        struct mach_header *header = &_mh_execute_header;
                     60:        int i;
                     61: 
                     62:        sgp = (struct segment_command *)
                     63:                ((char *)header + sizeof(struct mach_header));
                     64:        for (i = 0; i < header->ncmds; i++){
                     65:                if (   sgp->cmd == LC_SEGMENT) {
                     66:                        if (sgp->vmaddr + sgp->vmsize > last_addr)
                     67:                                last_addr = sgp->vmaddr + sgp->vmsize;
                     68:                }
                     69:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                     70:        }
                     71:        return last_addr;
                     72: }
                     73: 
                     74: struct mach_header **
                     75: getmachheaders(void)
                     76: {
                     77:        extern struct mach_header _mh_execute_header;
                     78:        struct mach_header **tl;
                     79:        
                     80:        tl = (struct mach_header **)malloc(2*sizeof(struct mach_header *));
                     81:        tl[0] = &_mh_execute_header;
                     82:        tl[1] = (struct mach_header *)0;
                     83:        return tl;
                     84: }
                     85: 
                     86: /*
                     87:  * This routine returns the a pointer to the data for the named section in the
                     88:  * named segment if it exist in the mach header passed to it.  Also it returns
                     89:  * the size of the section data indirectly through the pointer size.  Otherwise
                     90:  *  it returns zero for the pointer and the size.
                     91:  */
                     92: void *
                     93: getsectdatafromheader(
                     94:     struct mach_header *mhp,
                     95:     char *segname,
                     96:     char *sectname,
                     97:     int *size)
                     98: {              
                     99:        const struct section *sp;
                    100:        void *result;
                    101: 
                    102:        sp = getsectbynamefromheader(mhp, segname, sectname);
                    103:        if(sp == (struct section *)0){
                    104:            *size = 0;
                    105:            return((char *)0);
                    106:        }
                    107:        *size = sp->size;
                    108:        result = (void *)sp->addr;
                    109:        return result;
                    110: }
                    111: 
                    112: /*
                    113:  * This routine returns the a pointer to the data for the named segment
                    114:  * if it exist in the mach header passed to it.  Also it returns
                    115:  * the size of the segment data indirectly through the pointer size.
                    116:  * Otherwise it returns zero for the pointer and the size.
                    117:  */
                    118: void *
                    119: getsegdatafromheader(
                    120:     struct mach_header *mhp,
                    121:        char *segname,
                    122:        int *size)
                    123: {
                    124:        const struct segment_command *sc;
                    125:        void *result;
                    126: 
                    127:        sc = getsegbynamefromheader(mhp, segname);
                    128:        if(sc == (struct segment_command *)0){
                    129:            *size = 0;
                    130:            return((char *)0);
                    131:        }
                    132:        *size = sc->vmsize;
                    133:        result = (void *)sc->vmaddr;
                    134:        return result;
                    135: }
                    136: 
                    137: /*
                    138:  * This routine returns the section structure for the named section in the
                    139:  * named segment for the mach_header pointer passed to it if it exist.
                    140:  * Otherwise it returns zero.
                    141:  */
                    142: struct section *
                    143: getsectbynamefromheader(
                    144:     struct mach_header *mhp,
                    145:     char *segname,
                    146:     char *sectname)
                    147: {
                    148:        struct segment_command *sgp;
                    149:        struct section *sp;
                    150:        long i, j;
                    151: 
                    152:        sgp = (struct segment_command *)
                    153:              ((char *)mhp + sizeof(struct mach_header));
                    154:        for(i = 0; i < mhp->ncmds; i++){
                    155:            if(sgp->cmd == LC_SEGMENT)
                    156:                if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
                    157:                   mhp->filetype == MH_OBJECT){
                    158:                    sp = (struct section *)((char *)sgp +
                    159:                         sizeof(struct segment_command));
                    160:                    for(j = 0; j < sgp->nsects; j++){
                    161:                        if(strncmp(sp->sectname, sectname,
                    162:                           sizeof(sp->sectname)) == 0 &&
                    163:                           strncmp(sp->segname, segname,
                    164:                           sizeof(sp->segname)) == 0)
                    165:                            return(sp);
                    166:                        sp = (struct section *)((char *)sp +
                    167:                             sizeof(struct section));
                    168:                    }
                    169:                }
                    170:            sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    171:        }
                    172:        return((struct section *)0);
                    173: }
                    174: 
                    175: struct segment_command *getsegbynamefromheader(
                    176:        struct mach_header      *header,
                    177:        char                    *seg_name)
                    178: {
                    179:        struct segment_command *sgp;
                    180:        int i;
                    181: 
                    182:        sgp = (struct segment_command *)
                    183:                ((char *)header + sizeof(struct mach_header));
                    184:        for (i = 0; i < header->ncmds; i++){
                    185:                if (   sgp->cmd == LC_SEGMENT
                    186:                    && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
                    187:                        return sgp;
                    188:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    189:        }
                    190:        return (struct segment_command *)0;
                    191: }
                    192: 
                    193: 
                    194: /*
                    195:  * For now at least, all the rest of this seems unused.
                    196:  * NOTE: The constant in here for segment alignment is machine-dependent,
                    197:  * so if you include this, define a machine dependent constant for it's
                    198:  * value.
                    199:  */
                    200: static struct {
                    201:        struct segment_command  seg;
                    202:        struct section          sect;
                    203: } fvm_data = {
                    204:        {
                    205:                LC_SEGMENT,             // cmd
                    206:                sizeof(fvm_data),       // cmdsize
                    207:                "__USER",               // segname
                    208:                0,                      // vmaddr
                    209:                0,                      // vmsize
                    210:                0,                      // fileoff
                    211:                0,                      // filesize
                    212:                VM_PROT_READ,           // maxprot
                    213:                VM_PROT_READ,           // initprot,
                    214:                1,                      // nsects
                    215:                0                       // flags
                    216:        },
                    217:        {
                    218:                "",                     // sectname
                    219:                "__USER",               // segname
                    220:                0,                      // addr
                    221:                0,                      // size
                    222:                0,                      // offset
                    223:                4,                      // align
                    224:                0,                      // reloff
                    225:                0,                      // nreloc
                    226:                0                       // flags
                    227:        }
                    228: };
                    229: 
                    230: struct segment_command *fvm_seg;
                    231: 
                    232: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
                    233: static vm_offset_t getsizeofmacho(struct mach_header *header);
                    234: 
                    235: /*
                    236:  * Return the first segment_command in the header.
                    237:  */
                    238: struct segment_command *firstseg(void)
                    239: {
                    240:        return firstsegfromheader(&_mh_execute_header);
                    241: }
                    242: 
                    243: struct segment_command *firstsegfromheader(struct mach_header *header)
                    244: {
                    245:        struct segment_command *sgp;
                    246:        int i;
                    247: 
                    248:        sgp = (struct segment_command *)
                    249:                ((char *)header + sizeof(struct mach_header));
                    250:        for (i = 0; i < header->ncmds; i++){
                    251:                if (sgp->cmd == LC_SEGMENT)
                    252:                        return sgp;
                    253:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    254:        }
                    255:        return (struct segment_command *)0;
                    256: }
                    257: 
                    258: struct segment_command *nextseg(struct segment_command *sgp)
                    259: {
                    260:        struct segment_command *this;
                    261: 
                    262:        this = nextsegfromheader(&_mh_execute_header, sgp);
                    263: 
                    264:        /*
                    265:         * For the kernel's header add on the faked segment for the
                    266:         * USER boot code identified by a FVMFILE_COMMAND in the mach header.
                    267:         */
                    268:        if (!this && sgp != fvm_seg)
                    269:                this = fvm_seg;
                    270: 
                    271:        return this;
                    272: }
                    273: 
                    274: struct segment_command *nextsegfromheader(
                    275:        struct mach_header      *header,
                    276:        struct segment_command  *seg)
                    277: {
                    278:        struct segment_command *sgp;
                    279:        int i;
                    280: 
                    281:        sgp = (struct segment_command *)
                    282:                ((char *)header + sizeof(struct mach_header));
                    283:        for (i = 0; i < header->ncmds; i++) {
                    284:                if (sgp == seg)
                    285:                        break;
                    286:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    287:        }
                    288: 
                    289:        if (i == header->ncmds)
                    290:                return (struct segment_command *)0;
                    291: 
                    292:        sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    293:        for (; i < header->ncmds; i++) {
                    294:                if (sgp->cmd == LC_SEGMENT)
                    295:                        return sgp;
                    296:                sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
                    297:        }
                    298: 
                    299:        return (struct segment_command *)0;
                    300: }
                    301: 
                    302: 
                    303: /*
                    304:  * Return the address of the named Mach-O segment, or NULL.
                    305:  */
                    306: struct segment_command *getsegbyname(char *seg_name)
                    307: {
                    308:        struct segment_command *this;
                    309: 
                    310:        this = getsegbynamefromheader(&_mh_execute_header, seg_name);
                    311: 
                    312:        /*
                    313:         * For the kernel's header add on the faked segment for the
                    314:         * USER boot code identified by a FVMFILE_COMMAND in the mach header.
                    315:         */
                    316:        if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
                    317:                this = fvm_seg;
                    318: 
                    319:        return this;
                    320: }
                    321: 
                    322: /*
                    323:  * This routine returns the a pointer the section structure of the named
                    324:  * section in the named segment if it exist in the mach executable it is
                    325:  * linked into.  Otherwise it returns zero.
                    326:  */
                    327: struct section *
                    328: getsectbyname(
                    329:     char *segname,
                    330:     char *sectname)
                    331: {
                    332:        return(getsectbynamefromheader(
                    333:                (struct mach_header *)&_mh_execute_header, segname, sectname));
                    334: }
                    335: 
                    336: struct section *firstsect(struct segment_command *sgp)
                    337: {
                    338:        struct section *sp;
                    339: 
                    340:        if (!sgp || sgp->nsects == 0)
                    341:                return (struct section *)0;
                    342: 
                    343:        return (struct section *)(sgp+1);
                    344: }
                    345: 
                    346: struct section *nextsect(struct segment_command *sgp, struct section *sp)
                    347: {
                    348:        struct section *fsp = firstsect(sgp);
                    349: 
                    350:        if (sp - fsp >= sgp->nsects-1)
                    351:                return (struct section *)0;
                    352: 
                    353:        return sp+1;
                    354: }
                    355: 
                    356: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
                    357: {
                    358:        struct fvmfile_command *fvp;
                    359:        int i;
                    360: 
                    361:        fvp = (struct fvmfile_command *)
                    362:                ((char *)header + sizeof(struct mach_header));
                    363:        for (i = 0; i < header->ncmds; i++){
                    364:                if (fvp->cmd == LC_FVMFILE)
                    365:                        return fvp;
                    366:                fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
                    367:        }
                    368:        return (struct fvmfile_command *)0;
                    369: }
                    370: 
                    371: /*
                    372:  * Create a fake USER seg if a fvmfile_command is present.
                    373:  */
                    374: struct segment_command *getfakefvmseg(void)
                    375: {
                    376:        struct segment_command *sgp = getsegbyname("__USER");
                    377:        struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
                    378:        struct section *sp;
                    379: 
                    380:        if (sgp)
                    381:                return sgp;
                    382: 
                    383:        if (!fvp)
                    384:                return (struct segment_command *)0;
                    385: 
                    386:        fvm_seg = &fvm_data.seg;
                    387:        sgp = fvm_seg;
                    388:        sp = &fvm_data.sect;
                    389: 
                    390:        sgp->vmaddr = fvp->header_addr;
                    391:        sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
                    392: 
                    393:        strcpy(sp->sectname, fvp->name.ptr);
                    394:        sp->addr = sgp->vmaddr;
                    395:        sp->size = sgp->vmsize;
                    396: 
                    397: #if    DEBUG
                    398:        printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
                    399:                sp->sectname, sp->addr, sp->size);
                    400: #endif DEBUG
                    401: }
                    402: 
                    403: /*
                    404:  * Figure out the size the size of the data associated with a
                    405:  * loaded mach_header.
                    406:  */
                    407: static vm_offset_t getsizeofmacho(struct mach_header *header)
                    408: {
                    409:        struct segment_command  *sgp;
                    410:        struct section          *sp;
                    411:        vm_offset_t             last_addr;
                    412: 
                    413:        last_addr = 0;
                    414:        for (  sgp = firstsegfromheader(header)
                    415:            ; sgp
                    416:            ; sgp = nextsegfromheader(header, sgp))
                    417:        {
                    418:                if (sgp->fileoff + sgp->filesize > last_addr)
                    419:                        last_addr = sgp->fileoff + sgp->filesize;
                    420:        }
                    421: 
                    422:        return last_addr;
                    423: }
                    424: #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.