The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_symfile.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
   26  *
   27  *      File:   bsd/kern/kern_symfile.c
   28  *
   29  *      This file contains creates a dummy symbol file for mach_kernel based on
   30  *      the symbol table information passed by the SecondaryLoader/PlatformExpert.
   31  *      This allows us to correctly link other executables (drivers, etc) against the 
   32  *      the kernel in cases where the kernel image on the root device does not match
   33  *      the live kernel. This can occur during net-booting where the actual kernel
   34  *      image is obtained from the network via tftp rather than the root
   35  *      device.
   36  *
   37  *      If a symbol table is available, then the file /mach.sym will be created
   38  *      containing a Mach Header and a LC_SYMTAB load command followed by the
   39  *      the symbol table data for mach_kernel.
   40  *
   41  * HISTORY
   42  * 
   43  *      .
   44  */
   45 
   46 #include <mach/vm_param.h>
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/signalvar.h>
   51 #include <sys/resourcevar.h>
   52 #include <sys/namei.h>
   53 #include <sys/vnode.h>
   54 #include <sys/proc.h>
   55 #include <sys/timeb.h>
   56 #include <sys/times.h>
   57 #include <sys/buf.h>
   58 #include <sys/acct.h>
   59 #include <sys/file.h>
   60 #include <sys/uio.h>
   61 #include <sys/kernel.h>
   62 #include <sys/stat.h>
   63 
   64 #include <mach-o/loader.h>
   65 #include <mach-o/nlist.h>
   66 
   67 #include <vm/vm_kern.h>
   68 
   69 extern unsigned char    rootdevice[];
   70 extern struct mach_header _mh_execute_header;
   71 
   72 static int kernel_symfile_opened = 0;
   73 static int error_code = 0;
   74 
   75 extern int  IODTGetLoaderInfo(char *key, void **infoAddr, int *infoSize);
   76 extern void IODTFreeLoaderInfo(char *key, void *infoAddr, int infoSize);
   77 
   78 /*
   79  * 
   80  */
   81 static int output_kernel_symbols(struct proc *p)
   82 {
   83     struct vnode                *vp;
   84     struct pcred                *pcred = p->p_cred;
   85     struct ucred                *cred = pcred->pc_ucred;
   86     struct nameidata            nd;
   87     struct vattr                vattr;
   88     struct load_command         *cmd;
   89     struct mach_header          *orig_mh, *mh;
   90     struct segment_command      *orig_ds, *orig_ts, *orig_le, *sg;
   91     struct section              *se, *const_text;
   92     struct symtab_command       *st, *orig_st;
   93     struct nlist                *sym;
   94     vm_size_t                   orig_mhsize, orig_st_size;
   95     vm_offset_t                 header;
   96     vm_size_t                   header_size;
   97     int                         error, error1;
   98     int                         i, j;
   99     caddr_t                     addr;
  100     vm_offset_t                 offset;
  101     int                         rc_mh, rc_sc;
  102 
  103     error = EFAULT;
  104 
  105     vp          = NULL;
  106     header      = NULL;
  107     orig_mh     = NULL;
  108     orig_st     = NULL;
  109     
  110     // Dispose of unnecessary gumf, the booter doesn't need to load these
  111     rc_mh = IODTGetLoaderInfo("Kernel-__HEADER",
  112                                 (void **)&orig_mh, &orig_mhsize);
  113     if (rc_mh == 0 && orig_mh)
  114         IODTFreeLoaderInfo("Kernel-__HEADER",
  115                             (void *)orig_mh, round_page_32(orig_mhsize));
  116 
  117     rc_sc = IODTGetLoaderInfo("Kernel-__SYMTAB",
  118                                 (void **) &orig_st, &orig_st_size);
  119     if (rc_sc == 0 && orig_st)
  120         IODTFreeLoaderInfo("Kernel-__SYMTAB",
  121                             (void *)orig_st, round_page_32(orig_st_size));
  122 
  123     if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid)
  124         goto out;
  125 
  126     // Check to see if the root is 'e' or 'n', is this a test for network?
  127     if (rootdevice[0] == 'e' && rootdevice[1] == 'n')
  128         goto out;
  129 
  130     NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "mach.sym", p);
  131     if((error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IRGRP | S_IROTH))) goto out;
  132 
  133     vp = nd.ni_vp;
  134     
  135     /* Don't dump to non-regular files or files with links. */
  136     error = EFAULT;
  137     if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p)
  138     ||  vattr.va_nlink != 1)
  139         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     // If the file type is MH_EXECUTE then this must be a kernel
  148     // as all Kernel extensions must be of type MH_OBJECT
  149     orig_ds = orig_ts = orig_le = NULL;
  150     orig_st = NULL;
  151     orig_mh = &_mh_execute_header;
  152     cmd = (struct load_command *) &orig_mh[1];
  153     for (i = 0; i < orig_mh->ncmds; i++) {
  154         if (cmd->cmd == LC_SEGMENT) {
  155             struct segment_command *sg = (struct segment_command *) cmd;
  156     
  157             if (!strcmp(SEG_TEXT, sg->segname))
  158                 orig_ts = sg;
  159             else if (!strcmp(SEG_DATA, sg->segname))
  160                 orig_ds = sg;
  161             else if (!strcmp(SEG_LINKEDIT, sg->segname))
  162                 orig_le = sg;
  163         }
  164         else if (cmd->cmd == LC_SYMTAB)
  165             orig_st = (struct symtab_command *) cmd;
  166     
  167         cmd = (struct load_command *) ((caddr_t) cmd + cmd->cmdsize);
  168     }
  169 
  170     if (!orig_ts || !orig_ds || !orig_le || !orig_st) 
  171         goto out;
  172 
  173     const_text = NULL;
  174     se = (struct section *) &orig_ts[1];
  175     for (i = 0; i < orig_ts->nsects; i++, se++) {
  176         if (!strcmp("__const", se->sectname)) {
  177             const_text = se;
  178             break;
  179         }
  180     }
  181     if (!const_text)
  182         goto out;
  183 
  184     header_size =   sizeof(struct mach_header) 
  185                     + orig_ts->cmdsize
  186                     + orig_ds->cmdsize
  187                     + sizeof(struct symtab_command);
  188 
  189     (void) kmem_alloc_wired(kernel_map,
  190                             (vm_offset_t *) &header,
  191                             (vm_size_t) header_size);
  192     if (header)
  193         bzero((void *) header, header_size);
  194     else
  195         goto out;
  196 
  197     /*
  198      *  Set up Mach-O header.
  199      */
  200     mh = (struct mach_header *) header;
  201     mh->magic      = orig_mh->magic;
  202     mh->cputype    = orig_mh->cputype;
  203     mh->cpusubtype = orig_mh->cpusubtype;
  204     mh->filetype   = orig_mh->filetype;
  205     mh->ncmds      = 3;
  206     mh->sizeofcmds = header_size - sizeof(struct mach_header);
  207     mh->flags      = orig_mh->flags;
  208 
  209     // Initialise the current file offset and addr
  210     offset = round_page_32(header_size);
  211     addr = (caddr_t) const_text->addr;  // Load address of __TEXT,__const
  212 
  213     /*
  214      * Construct a TEXT segment load command
  215      * the only part of the TEXT segment we keep is the __TEXT,__const
  216      * which contains the kernel vtables. 
  217      */
  218     sg = (struct segment_command *) &mh[1];
  219     bcopy(orig_ts, sg, orig_ts->cmdsize);
  220     sg->vmaddr   = (unsigned long) addr;
  221     sg->vmsize   = const_text->size;
  222     sg->fileoff  = 0;
  223     sg->filesize = const_text->size + round_page_32(header_size);
  224     sg->maxprot  = 0;
  225     sg->initprot = 0;
  226     sg->flags    = 0;
  227     se = (struct section *)(sg+1);
  228     for ( j = 0; j < sg->nsects; j++, se++ ) {
  229         se->addr  = (unsigned long) addr;
  230         se->size  = 0;
  231         se->offset = offset;
  232         se->nreloc = 0;
  233         if (!strcmp("__const", se->sectname)) {
  234             se->size = const_text->size;
  235             addr    += const_text->size;
  236             offset  += const_text->size;
  237             const_text = se;
  238         }
  239     }
  240     offset = round_page_32((vm_address_t) offset);
  241 
  242     // Now copy of the __DATA segment load command, the image need
  243     // not be stored to disk nobody needs it, yet!
  244     sg = (struct segment_command *)((int)sg + sg->cmdsize);
  245     bcopy(orig_ds, sg, orig_ds->cmdsize);
  246 
  247     sg->vmaddr   = (unsigned long) addr;
  248     sg->vmsize   = 0x1000;      // One page for some reason?
  249     sg->fileoff  = offset;
  250     sg->filesize = 0;
  251     sg->maxprot  = 0;
  252     sg->initprot = 0;
  253     sg->flags    = 0;
  254     se = (struct section *)(sg+1);
  255     for ( j = 0; j < sg->nsects; j++, se++ ) {
  256         se->addr  = (unsigned long) addr;
  257         se->size  = 0;
  258         se->offset = offset;
  259         se->nreloc = 0;
  260     }
  261     offset = round_page_32(offset);
  262 
  263 
  264     /*
  265      *  Set up LC_SYMTAB command
  266      */
  267     st          = (struct symtab_command *)((int)sg + sg->cmdsize);
  268     st->cmd     = LC_SYMTAB;
  269     st->cmdsize = sizeof(struct symtab_command);
  270     st->symoff  = offset;
  271     st->nsyms   = orig_st->nsyms;
  272     st->strsize = orig_st->strsize;
  273     st->stroff =  offset + st->nsyms * sizeof(struct nlist);    
  274 
  275     /*
  276      * Convert the symbol table in place from section references
  277      * to absolute references.
  278      */
  279     sym = (struct nlist *) orig_le->vmaddr;
  280     for (i = 0; i < st->nsyms; i++, sym++ ) {
  281         if ( (sym->n_type & N_TYPE) == N_SECT) {
  282             sym->n_sect = NO_SECT;
  283             sym->n_type = (sym->n_type & ~N_TYPE) | N_ABS;
  284         }
  285     }
  286 
  287     /*
  288      *  Write out the load commands at the beginning of the file.
  289      */
  290     error = vn_rdwr(UIO_WRITE, vp, (caddr_t) mh, header_size, (off_t) 0,
  291                     UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
  292     if (error)
  293         goto out;
  294 
  295     /*
  296      *  Write out the __TEXT,__const data segment.
  297      */
  298     error = vn_rdwr(UIO_WRITE, vp, (caddr_t) const_text->addr,
  299                     const_text->size, const_text->offset,
  300                     UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
  301     if (error)
  302         goto out;
  303 
  304     /*
  305      *  Write out kernel symbols
  306      */
  307     offset = st->nsyms * sizeof(struct nlist) + st->strsize;    // symtab size
  308     error = vn_rdwr(UIO_WRITE, vp,
  309                    (caddr_t) orig_le->vmaddr, offset, st->symoff,
  310                     UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
  311     if (error)
  312         goto out;
  313 
  314 out:
  315     if (header)
  316         kmem_free(kernel_map, header, header_size);
  317 
  318     if (vp) {
  319         VOP_UNLOCK(vp, 0, p);
  320         error1 = vn_close(vp, FWRITE, cred, p);
  321         if (!error) error = error1;
  322     }
  323 
  324     return(error);
  325 }
  326 /*
  327  * 
  328  */
  329 int get_kernel_symfile(struct proc *p, char **symfile)
  330 {
  331     if (!kernel_symfile_opened) {
  332         kernel_symfile_opened = 1;
  333         error_code = output_kernel_symbols(p);
  334     }
  335     if (!error_code)
  336         *symfile = "\\mach.sym";
  337 
  338     return error_code;
  339 }

Cache object: 45079e1c7d7eff1ea0af04d4daa17c45


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.