]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_symfile.c
xnu-792.1.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_symfile.c
index f4607b9d3aa85078766c1787689b09a2f33cceeb..ed56bd1cddf50ff18cb82d942ac60cb0a7d72ab3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  *     File:   bsd/kern/kern_symfile.c
  *
- *     This file contains creates a dummy symbol file for mach_kernel based on
- *      the symbol table information passed by the SecondaryLoader/PlatformExpert.
- *      This allows us to correctly link other executables (drivers, etc) against the 
- *      the kernel in cases where the kernel image on the root device does not match
- *      the live kernel. This can occur during net-booting where the actual kernel
- *      image is obtained from the network via tftp rather than the root
- *      device.
+ *     This file contains creates a dummy symbol file for mach_kernel
+ *     based on the symbol table information passed by the
+ *     SecondaryLoader/PlatformExpert.  This allows us to correctly
+ *     link other executables (drivers, etc) against the the kernel in
+ *     cases where the kernel image on the root device does not match
+ *      the live kernel. This can occur during net-booting where the
+ *     actual kernel image is obtained from the network via tftp rather
+ *     than the root device.
  *
- *      If a symbol table is available, then the file /mach.sym will be created
- *      containing a Mach Header and a LC_SYMTAB load command followed by the
- *      the symbol table data for mach_kernel.
+ *      If a symbol table is available, then the file /mach.sym will be
+ *     created containing a Mach Header and a LC_SYMTAB load command
+ *     followed by the the symbol table data for mach_kernel.
+ *
+ * NOTE:       This file supports only 32 bit kernels at the present time;
+ *             adding support for 64 bit kernels is possible, but is not
+ *             necessary at the present time.
  *
  * HISTORY
  * 
 #include <sys/signalvar.h>
 #include <sys/resourcevar.h>
 #include <sys/namei.h>
-#include <sys/vnode.h>
-#include <sys/proc.h>
+#include <sys/vnode_internal.h>
+#include <sys/proc_internal.h>
+#include <sys/kauth.h>
 #include <sys/timeb.h>
 #include <sys/times.h>
-#include <sys/buf.h>
 #include <sys/acct.h>
-#include <sys/file.h>
+#include <sys/file_internal.h>
 #include <sys/uio.h>
 #include <sys/kernel.h>
 #include <sys/stat.h>
+#include <sys/disk.h>
+#include <sys/conf.h>
 
 #include <mach-o/loader.h>
 #include <mach-o/nlist.h>
 
+#include <kern/kalloc.h>
 #include <vm/vm_kern.h>
+#include <pexpert/pexpert.h>
 
 extern unsigned char   rootdevice[];
 extern struct mach_header _mh_execute_header;
@@ -73,15 +82,15 @@ extern int  IODTGetLoaderInfo(char *key, void **infoAddr, int *infoSize);
 extern void IODTFreeLoaderInfo(char *key, void *infoAddr, int infoSize);
 
 /*
- * 
+ * Can only operate against currently running 32 bit mach_kernel
  */
-static int output_kernel_symbols(struct proc *p)
+static int
+output_kernel_symbols(struct proc *p)
 {
     struct vnode               *vp;
-    struct pcred               *pcred = p->p_cred;
-    struct ucred               *cred = pcred->pc_ucred;
-    struct nameidata           nd;
-    struct vattr               vattr;
+    kauth_cred_t               cred = p->p_ucred;      /* XXX */
+    struct vnode_attr          va;
+    struct vfs_context         context;
     struct load_command                *cmd;
     struct mach_header         *orig_mh, *mh;
     struct segment_command     *orig_ds, *orig_ts, *orig_le, *sg;
@@ -90,9 +99,9 @@ static int output_kernel_symbols(struct proc *p)
     struct nlist               *sym;
     vm_size_t                  orig_mhsize, orig_st_size;
     vm_offset_t                        header;
-    vm_size_t                  header_size;
+    vm_size_t                  header_size = 0; /* out: protected by header */
     int                                error, error1;
-    int                                i, j;
+    unsigned int               i, j;
     caddr_t                    addr;
     vm_offset_t                        offset;
     int                                rc_mh, rc_sc;
@@ -107,38 +116,39 @@ static int output_kernel_symbols(struct proc *p)
     // Dispose of unnecessary gumf, the booter doesn't need to load these
     rc_mh = IODTGetLoaderInfo("Kernel-__HEADER",
                                (void **)&orig_mh, &orig_mhsize);
-    if (rc_mh && orig_mh)
+    if (rc_mh == 0 && orig_mh)
        IODTFreeLoaderInfo("Kernel-__HEADER",
-                           (void *)orig_mh, round_page(orig_mhsize));
+                           (void *)orig_mh, round_page_32(orig_mhsize));
 
     rc_sc = IODTGetLoaderInfo("Kernel-__SYMTAB",
                                (void **) &orig_st, &orig_st_size);
-    if (rc_sc && orig_st)
+    if (rc_sc == 0 && orig_st)
        IODTFreeLoaderInfo("Kernel-__SYMTAB",
-                           (void *)orig_st, round_page(orig_st_size));
+                           (void *)orig_st, round_page_32(orig_st_size));
 
-    if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid)
+    if (cred->cr_svuid != cred->cr_ruid || cred->cr_svgid != cred->cr_rgid)
        goto out;
 
     // Check to see if the root is 'e' or 'n', is this a test for network?
     if (rootdevice[0] == 'e' && rootdevice[1] == 'n')
        goto out;
 
-    NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "mach.sym", p);
-    if((error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IRGRP | S_IROTH))) goto out;
+    context.vc_proc = p;
+    context.vc_ucred = cred;
+
+    if ((error = vnode_open("mach.sym", (O_CREAT | FWRITE), (S_IRUSR | S_IRGRP | S_IROTH), 0, &vp, &context)))
+        goto out;
 
-    vp = nd.ni_vp;
-    
     /* Don't dump to non-regular files or files with links. */
     error = EFAULT;
-    if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p)
-    ||  vattr.va_nlink != 1)
+    VATTR_INIT(&va);
+    VATTR_WANTED(&va, va_nlink);
+    if ((vp->v_type != VREG) || vnode_getattr(vp, &va, &context) || (va.va_nlink != 1))
        goto out;
 
-    VATTR_NULL(&vattr);
-    vattr.va_size = 0;
-    VOP_LEASE(vp, p, cred, LEASE_WRITE);
-    VOP_SETATTR(vp, &vattr, cred, p);
+    VATTR_INIT(&va);                   /* better to do it here than waste more stack in vnode_getsize */
+    VATTR_SET(&va, va_data_size, 0);
+    vnode_setattr(vp, &va, &context);
     p->p_acflag |= ACORE;
 
     // If the file type is MH_EXECUTE then this must be a kernel
@@ -149,14 +159,14 @@ static int output_kernel_symbols(struct proc *p)
     cmd = (struct load_command *) &orig_mh[1];
     for (i = 0; i < orig_mh->ncmds; i++) {
        if (cmd->cmd == LC_SEGMENT) {
-           struct segment_command *sg = (struct segment_command *) cmd;
+           struct segment_command *orig_sg = (struct segment_command *) cmd;
     
-           if (!strcmp(SEG_TEXT, sg->segname))
-               orig_ts = sg;
-           else if (!strcmp(SEG_DATA, sg->segname))
-               orig_ds = sg;
-           else if (!strcmp(SEG_LINKEDIT, sg->segname))
-               orig_le = sg;
+           if (!strcmp(SEG_TEXT, orig_sg->segname))
+               orig_ts = orig_sg;
+           else if (!strcmp(SEG_DATA, orig_sg->segname))
+               orig_ds = orig_sg;
+           else if (!strcmp(SEG_LINKEDIT, orig_sg->segname))
+               orig_le = orig_sg;
        }
        else if (cmd->cmd == LC_SYMTAB)
            orig_st = (struct symtab_command *) cmd;
@@ -183,7 +193,7 @@ static int output_kernel_symbols(struct proc *p)
                    + orig_ds->cmdsize
                    + sizeof(struct symtab_command);
 
-    (void) kmem_alloc_wired(kernel_map,
+    (void) kmem_alloc(kernel_map,
                            (vm_offset_t *) &header,
                            (vm_size_t) header_size);
     if (header)
@@ -234,7 +244,7 @@ static int output_kernel_symbols(struct proc *p)
            const_text = se;
        }
     }
-    offset = round_page((vm_address_t) offset);
+    offset = round_page(offset);
 
     // Now copy of the __DATA segment load command, the image need
     // not be stored to disk nobody needs it, yet!
@@ -285,7 +295,7 @@ static int output_kernel_symbols(struct proc *p)
      * Write out the load commands at the beginning of the file.
      */
     error = vn_rdwr(UIO_WRITE, vp, (caddr_t) mh, header_size, (off_t) 0,
-                   UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
+                   UIO_SYSSPACE32, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
     if (error)
        goto out;
 
@@ -294,7 +304,7 @@ static int output_kernel_symbols(struct proc *p)
      */
     error = vn_rdwr(UIO_WRITE, vp, (caddr_t) const_text->addr,
                    const_text->size, const_text->offset,
-                   UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
+                   UIO_SYSSPACE32, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
     if (error)
        goto out;
 
@@ -304,17 +314,13 @@ static int output_kernel_symbols(struct proc *p)
     offset = st->nsyms * sizeof(struct nlist) + st->strsize;   // symtab size
     error = vn_rdwr(UIO_WRITE, vp,
                   (caddr_t) orig_le->vmaddr, offset, st->symoff,
-                   UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
-    if (error)
-       goto out;
-
+                   UIO_SYSSPACE32, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
 out:
     if (header)
        kmem_free(kernel_map, header, header_size);
 
     if (vp) {
-       VOP_UNLOCK(vp, 0, p);
-       error1 = vn_close(vp, FWRITE, cred, p);
+       error1 = vnode_close(vp, FWRITE, &context);
        if (!error) error = error1;
     }
 
@@ -334,3 +340,4 @@ int get_kernel_symfile(struct proc *p, char **symfile)
 
     return error_code;
 }
+