|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.