Annotation of XNU/bsd/kern/kern_symfile.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: /* Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
                     23:  *
                     24:  *     File:   bsd/kern/kern_symfile.c
                     25:  *
                     26:  *     This file contains creates a dummy symbol file for mach_kernel based on
                     27:  *      the symbol table information passed by the SecondaryLoader/PlatformExpert.
                     28:  *      This allows us to correctly link other executables (drivers, etc) against the 
                     29:  *      the kernel in cases where the kernel image on the root device does not match
                     30:  *      the live kernel. This can occur during net-booting where the actual kernel
                     31:  *      image is obtained from the network via tftp rather than the root
                     32:  *      device.
                     33:  *
                     34:  *      If a symbol table is available, then the file /mach.sym will be created
                     35:  *      containing a Mach Header and a LC_SYMTAB load command followed by the
                     36:  *      the symbol table data for mach_kernel.
                     37:  *
                     38:  * HISTORY
                     39:  * 
                     40:  *     .
                     41:  */
                     42: 
                     43: #import <mach/vm_param.h>
                     44: 
                     45: #include <sys/param.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/signalvar.h>
                     48: #include <sys/resourcevar.h>
                     49: #include <sys/namei.h>
                     50: #include <sys/vnode.h>
                     51: #include <sys/proc.h>
                     52: #include <sys/timeb.h>
                     53: #include <sys/times.h>
                     54: #include <sys/buf.h>
                     55: #include <sys/acct.h>
                     56: #include <sys/file.h>
                     57: #include <sys/uio.h>
                     58: #include <sys/kernel.h>
                     59: #include <sys/stat.h>
                     60: 
                     61: #include <mach-o/loader.h>
                     62: #include <mach-o/nlist.h>
                     63: 
                     64: #include <vm/vm_kern.h>
                     65: 
                     66: extern unsigned char   rootdevice[];
                     67: extern vm_size_t       page_size;
                     68: 
                     69: 
                     70: int kernel_symfile_opened = 0;
                     71: int error_code = 0;
                     72: 
                     73: extern int  IODTGetLoaderInfo(  char *key, void **infoAddr, int *infoSize );
                     74: extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
                     75: 
                     76: /*
                     77:  * 
                     78:  */
                     79: int get_kernel_symfile( struct proc *p, char **symfile )
                     80: {
                     81:     if ( kernel_symfile_opened == 0 )
                     82:     {
                     83:         kernel_symfile_opened = 1;
                     84:         error_code = output_kernel_symbols( p );
                     85:     }
                     86:     if ( error_code == 0 ) *symfile = "\\mach.sym";
                     87: 
                     88:     return error_code;
                     89: }
                     90: 
                     91: /*
                     92:  * 
                     93:  */
                     94: int output_kernel_symbols( register struct proc *p )
                     95: {
                     96:        register struct vnode           *vp;
                     97:        register struct pcred           *pcred = p->p_cred;
                     98:        register struct ucred           *cred = pcred->pc_ucred;
                     99:        struct nameidata                nd;
                    100:        struct vattr                    vattr;
                    101:        struct mach_header              *orig_mh, *mh;
                    102:         struct load_command            *lc;
                    103:         struct segment_command         *sg;
                    104:         struct section                 *se;
                    105:        struct symtab_command           *sc, *sc0;
                    106:         struct nlist                    *nl;
                    107:        vm_size_t                       orig_mhsize, sc0_size;
                    108:         vm_offset_t                    header;
                    109:         vm_size_t                      header_size;
                    110:        int                             error, error1;
                    111:         int                            i, j;
                    112:         int                            symfoffset, symsize;
                    113:         int                             rc_mh, rc_sc;
                    114: 
                    115:         error = EFAULT;
                    116: 
                    117:         vp       = NULL;
                    118:         header   = NULL;
                    119:         orig_mh  = NULL;
                    120:         sc0      = NULL;
                    121:         
                    122:         rc_mh = IODTGetLoaderInfo( "Kernel-__HEADER", (void **)&orig_mh, &orig_mhsize );
                    123:         rc_sc = IODTGetLoaderInfo( "Kernel-__SYMTAB", (void **)&sc0, &sc0_size );
                    124:         
                    125:         if ( rc_mh != 0 || orig_mh == 0 || orig_mhsize < sizeof(struct mach_header) )    goto out;
                    126:         if ( rc_sc != 0 || sc0 == 0     || sc0_size    < sizeof(struct symtab_command) ) goto out;
                    127: 
                    128:        if ( pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid ) goto out;
                    129: 
                    130:         if ( rootdevice[0] == 'e' && rootdevice[1] == 'n' ) goto out;
                    131: 
                    132:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "mach.sym", p);
                    133:        if( (error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IRGRP | S_IROTH )) != 0 ) goto out;
                    134: 
                    135:        vp = nd.ni_vp;
                    136:        
                    137:        /* Don't dump to non-regular files or files with links. */
                    138:         error = EFAULT;
                    139:        if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) goto out;
                    140: 
                    141:        VATTR_NULL(&vattr);
                    142:        vattr.va_size = 0;
                    143:        VOP_LEASE(vp, p, cred, LEASE_WRITE);
                    144:        VOP_SETATTR(vp, &vattr, cred, p);
                    145:        p->p_acflag |= ACORE;
                    146: 
                    147:        header_size =   sizeof(struct mach_header) 
                    148:                       + sizeof(struct segment_command)
                    149:                       + sizeof(struct section)
                    150:                       + sizeof(struct symtab_command);
                    151: 
                    152:        (void) kmem_alloc_wired( kernel_map,
                    153:                                (vm_offset_t *)&header,
                    154:                                (vm_size_t)header_size);
                    155: 
                    156:         if ( header == NULL ) goto out;
                    157: 
                    158:         bzero( (void *)header, header_size );
                    159: 
                    160:        /*
                    161:         *      Set up Mach-O header.
                    162:         */
                    163:        mh = (struct mach_header *) header;
                    164:        mh->magic = orig_mh->magic;
                    165:        mh->cputype = orig_mh->cputype;
                    166:        mh->cpusubtype = orig_mh->cpusubtype;
                    167:        mh->filetype = orig_mh->filetype;
                    168:        mh->ncmds = 2;
                    169:        mh->sizeofcmds = header_size - sizeof(struct mach_header);
                    170: 
                    171:        /*
                    172:         *      Setup a dummy LC_SEGMENT command to force page alignment of  sections.
                    173:         */
                    174:         sg = (struct segment_command *)(mh+1);
                    175:         sg->cmd      = LC_SEGMENT;
                    176:         sg->cmdsize  = sizeof(struct segment_command) + sizeof(struct section);
                    177:         strcpy( sg->segname, SEG_DATA );
                    178:         sg->vmaddr   = 0;
                    179:         sg->vmsize   = 0x1000;
                    180:         sg->fileoff  = 0;
                    181:         sg->filesize = 0;
                    182:         sg->maxprot  = 0;
                    183:         sg->initprot = 0;
                    184:         sg->nsects   = 1;
                    185:         sg->flags    = 0;
                    186: 
                    187:        /*
                    188:         *      Set up alignment section.
                    189:         */
                    190:         for ( j=page_size-1, i=0; j; i++, j >>= 1 )
                    191:           ;
                    192: 
                    193:         se = (struct section *)(sg+1);
                    194:         strcpy( se->sectname, SECT_BSS );
                    195:         strcpy( se->segname, sg->segname );
                    196:         se->addr  = 0;
                    197:         se->size  = 0;
                    198:         se->align = i;
                    199:         se->flags = S_ZEROFILL;
                    200: 
                    201:         symfoffset = round_page(header_size);
                    202: 
                    203:        /*
                    204:         *      Set up LC_SYMTAB command
                    205:         */
                    206:        sc          = (struct symtab_command *)(se+1);
                    207:        sc->cmd     = LC_SYMTAB;
                    208:        sc->cmdsize = sizeof(struct symtab_command);
                    209:         sc->symoff  = symfoffset;
                    210:         sc->nsyms   = sc0->nsyms;
                    211:         sc->strsize = sc0->strsize;
                    212:         sc->stroff =  symfoffset + sc->nsyms * sizeof(struct nlist);    
                    213: 
                    214:         symsize = sc->nsyms * sizeof(struct nlist) + sc->strsize;
                    215: 
                    216:         nl = (struct nlist *)(sc0+1);
                    217:         for (i = 0; i < sc->nsyms; i++, nl++ )
                    218:         {
                    219:             if ( (nl->n_type & N_TYPE) == N_SECT )
                    220:             {
                    221:                 nl->n_sect = NO_SECT;
                    222:                 nl->n_type = (nl->n_type & ~N_TYPE) | N_ABS;
                    223:             }
                    224:         }
                    225: 
                    226:        /*
                    227:         *      Write out the load commands at the beginning of the
                    228:         *      file.
                    229:         */
                    230:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)mh, header_size, (off_t)0,
                    231:                        UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
                    232:         if ( error != 0 ) goto out;
                    233:         
                    234:         /*
                    235:          *     Write out kernel symbols
                    236:          */
                    237:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)(sc0+1), symsize, symfoffset,
                    238:                        UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
                    239:         if ( error != 0 ) goto out;
                    240: 
                    241: out:
                    242:         if ( header != 0 ) kmem_free(kernel_map, header, header_size);
                    243:         if ( orig_mh != 0 ) IODTFreeLoaderInfo( "Kernel-__HEADER", (void *)orig_mh, round_page(orig_mhsize) );
                    244:         if ( sc0     != 0 ) IODTFreeLoaderInfo( "Kernel-__SYMTAB", (void *)sc0,     round_page(sc0_size) );        
                    245:   
                    246:         if ( vp != 0 )
                    247:         {
                    248:            VOP_UNLOCK(vp, 0, p);
                    249:            error1 = vn_close(vp, FWRITE, cred, p);
                    250:            if (error == 0) error = error1;
                    251:         }
                    252: 
                    253:        return(error);
                    254: }

unix.superglobalmegacorp.com

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