]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_symfile.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24 * File: bsd/kern/kern_symfile.c
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
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.
43 #include <mach/vm_param.h>
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>
52 #include <sys/timeb.h>
53 #include <sys/times.h>
58 #include <sys/kernel.h>
61 #include <mach-o/loader.h>
62 #include <mach-o/nlist.h>
64 #include <vm/vm_kern.h>
66 extern unsigned char rootdevice
[];
67 extern vm_size_t page_size
;
70 int kernel_symfile_opened
= 0;
73 extern int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infoSize
);
74 extern void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
);
76 struct segment_command
*findSegmentByName( struct mach_header
*mh
, const char *section_name
);
81 int get_kernel_symfile( struct proc
*p
, char **symfile
)
83 if ( kernel_symfile_opened
== 0 )
85 kernel_symfile_opened
= 1;
86 error_code
= output_kernel_symbols( p
);
88 if ( error_code
== 0 ) *symfile
= "\\mach.sym";
96 int output_kernel_symbols( register struct proc
*p
)
98 register struct vnode
*vp
;
99 register struct pcred
*pcred
= p
->p_cred
;
100 register struct ucred
*cred
= pcred
->pc_ucred
;
103 struct mach_header
*orig_mh
, *mh
;
104 struct load_command
*lc
;
105 struct segment_command
*orig_ds
, *orig_ts
, *sg
;
107 struct symtab_command
*sc
, *sc0
;
109 vm_size_t orig_mhsize
, sc0_size
;
111 vm_size_t header_size
;
114 int symfoffset
, symsize
;
124 rc_mh
= IODTGetLoaderInfo( "Kernel-__HEADER", (void **)&orig_mh
, &orig_mhsize
);
125 rc_sc
= IODTGetLoaderInfo( "Kernel-__SYMTAB", (void **)&sc0
, &sc0_size
);
127 if ( rc_mh
!= 0 || orig_mh
== 0 || orig_mhsize
< sizeof(struct mach_header
) ) goto out
;
128 if ( rc_sc
!= 0 || sc0
== 0 || sc0_size
< sizeof(struct symtab_command
) ) goto out
;
130 if ( pcred
->p_svuid
!= pcred
->p_ruid
|| pcred
->p_svgid
!= pcred
->p_rgid
) goto out
;
132 if ( rootdevice
[0] == 'e' && rootdevice
[1] == 'n' ) goto out
;
134 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_SYSSPACE
, "mach.sym", p
);
135 if( (error
= vn_open(&nd
, O_CREAT
| FWRITE
, S_IRUSR
| S_IRGRP
| S_IROTH
)) != 0 ) goto out
;
139 /* Don't dump to non-regular files or files with links. */
141 if (vp
->v_type
!= VREG
|| VOP_GETATTR(vp
, &vattr
, cred
, p
) || vattr
.va_nlink
!= 1) goto out
;
145 VOP_LEASE(vp
, p
, cred
, LEASE_WRITE
);
146 VOP_SETATTR(vp
, &vattr
, cred
, p
);
147 p
->p_acflag
|= ACORE
;
149 orig_ts
= findSegmentByName(orig_mh
, "__TEXT");
150 orig_ds
= findSegmentByName(orig_mh
, "__DATA");
152 if ( orig_ts
== NULL
|| orig_ds
== NULL
) goto out
;
154 header_size
= sizeof(struct mach_header
)
157 + sizeof(struct symtab_command
);
159 (void) kmem_alloc_wired( kernel_map
,
160 (vm_offset_t
*)&header
,
161 (vm_size_t
)header_size
);
163 if ( header
== NULL
) goto out
;
165 bzero( (void *)header
, header_size
);
168 * Set up Mach-O header.
170 mh
= (struct mach_header
*) header
;
171 mh
->magic
= orig_mh
->magic
;
172 mh
->cputype
= orig_mh
->cputype
;
173 mh
->cpusubtype
= orig_mh
->cpusubtype
;
174 mh
->filetype
= orig_mh
->filetype
;
176 mh
->sizeofcmds
= header_size
- sizeof(struct mach_header
);
179 * Copy __DATA and __TEXT segment commands from mach_kernel so loadable drivers
180 * get correct section alignment hints.
182 sg
= (struct segment_command
*)(mh
+1);
183 bcopy( orig_ts
, sg
, orig_ts
->cmdsize
);
185 sg
= (struct segment_command
*)((int)sg
+ sg
->cmdsize
);
186 bcopy( orig_ds
, sg
, orig_ds
->cmdsize
);
188 sg
= (struct segment_command
*)(mh
+1);
190 for ( i
= 0; i
< 2; i
++ )
200 se
= (struct section
*)(sg
+1);
201 for ( j
= 0; j
< sg
->nsects
; j
++, se
++ )
209 sg
= (struct segment_command
*)((int)sg
+ sg
->cmdsize
);
212 symfoffset
= round_page(header_size
);
215 * Set up LC_SYMTAB command
217 sc
= (struct symtab_command
*)sg
;
219 sc
->cmdsize
= sizeof(struct symtab_command
);
220 sc
->symoff
= symfoffset
;
221 sc
->nsyms
= sc0
->nsyms
;
222 sc
->strsize
= sc0
->strsize
;
223 sc
->stroff
= symfoffset
+ sc
->nsyms
* sizeof(struct nlist
);
225 symsize
= sc
->nsyms
* sizeof(struct nlist
) + sc
->strsize
;
227 nl
= (struct nlist
*)(sc0
+1);
228 for (i
= 0; i
< sc
->nsyms
; i
++, nl
++ )
230 if ( (nl
->n_type
& N_TYPE
) == N_SECT
)
232 nl
->n_sect
= NO_SECT
;
233 nl
->n_type
= (nl
->n_type
& ~N_TYPE
) | N_ABS
;
238 * Write out the load commands at the beginning of the
241 error
= vn_rdwr(UIO_WRITE
, vp
, (caddr_t
)mh
, header_size
, (off_t
)0,
242 UIO_SYSSPACE
, IO_NODELOCKED
|IO_UNIT
, cred
, (int *) 0, p
);
243 if ( error
!= 0 ) goto out
;
246 * Write out kernel symbols
248 error
= vn_rdwr(UIO_WRITE
, vp
, (caddr_t
)(sc0
+1), symsize
, symfoffset
,
249 UIO_SYSSPACE
, IO_NODELOCKED
|IO_UNIT
, cred
, (int *) 0, p
);
250 if ( error
!= 0 ) goto out
;
253 if ( header
!= 0 ) kmem_free(kernel_map
, header
, header_size
);
254 if ( orig_mh
!= 0 ) IODTFreeLoaderInfo( "Kernel-__HEADER", (void *)orig_mh
, round_page(orig_mhsize
) );
255 if ( sc0
!= 0 ) IODTFreeLoaderInfo( "Kernel-__SYMTAB", (void *)sc0
, round_page(sc0_size
) );
259 VOP_UNLOCK(vp
, 0, p
);
260 error1
= vn_close(vp
, FWRITE
, cred
, p
);
261 if (error
== 0) error
= error1
;
270 struct segment_command
*findSegmentByName( struct mach_header
*mh
, const char *section_name
)
272 struct segment_command
*sg
;
275 sg
= (struct segment_command
*)(mh
+1);
277 for ( i
=0; i
< mh
->ncmds
; i
++ )
279 if ( (sg
->cmd
== LC_SEGMENT
) && (strcmp(sg
->segname
, section_name
) == 0) )
284 sg
= (struct segment_command
*)((int)sg
+ sg
->cmdsize
);