|
|
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.