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_core.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-2002 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) 1991 NeXT Computer, Inc.  All rights reserved.
   26  *
   27  *      File:   bsd/kern/kern_core.c
   28  *
   29  *      This file contains machine independent code for performing core dumps.
   30  *
   31  */
   32 
   33 #include <mach/vm_param.h>
   34 #include <mach/thread_status.h>
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/signalvar.h>
   39 #include <sys/resourcevar.h>
   40 #include <sys/namei.h>
   41 #include <sys/vnode.h>
   42 #include <sys/proc.h>
   43 #include <sys/timeb.h>
   44 #include <sys/times.h>
   45 #include <sys/buf.h>
   46 #include <sys/acct.h>
   47 #include <sys/file.h>
   48 #include <sys/uio.h>
   49 #include <sys/kernel.h>
   50 #include <sys/stat.h>
   51 
   52 #include <mach-o/loader.h>
   53 #include <mach/vm_region.h>
   54 #include <mach/vm_statistics.h>
   55 
   56 #include <vm/vm_kern.h>
   57 
   58 typedef struct {
   59         int     flavor;                 /* the number for this flavor */
   60         int     count;                  /* count of ints in this flavor */
   61 } mythread_state_flavor_t;
   62 
   63 #if defined (__ppc__)
   64 
   65 mythread_state_flavor_t thread_flavor_array[]={
   66                 {PPC_THREAD_STATE , PPC_THREAD_STATE_COUNT},
   67                 {PPC_FLOAT_STATE, PPC_FLOAT_STATE_COUNT}, 
   68                 {PPC_EXCEPTION_STATE, PPC_EXCEPTION_STATE_COUNT},
   69                 {PPC_VECTOR_STATE, PPC_VECTOR_STATE_COUNT}
   70                 };
   71 int mynum_flavors=4;
   72 #elif defined (__i386__)
   73 mythread_state_flavor_t thread_flavor_array [] = { 
   74                 {i386_THREAD_STATE, i386_THREAD_STATE_COUNT},
   75                 {i386_THREAD_FPSTATE, i386_THREAD_FPSTATE_COUNT},
   76                 {i386_THREAD_EXCEPTSTATE, i386_THREAD_EXCEPTSTATE_COUNT},
   77                 {i386_THREAD_CTHREADSTATE, i386_THREAD_CTHREADSTATE_COUNT},
   78                 {i386_NEW_THREAD_STATE, i386_NEW_THREAD_STATE_COUNT},
   79                 {i386_FLOAT_STATE, i386_FLOAT_STATE_COUNT},
   80                 {i386_ISA_PORT_MAP_STATE, i386_ISA_PORT_MAP_STATE_COUNT},
   81                 {i386_V86_ASSIST_STATE, i386_V86_ASSIST_STATE_COUNT},
   82                 {THREAD_SYSCALL_STATE, i386_THREAD_SYSCALL_STATE_COUNT}
   83                 };
   84 int mynum_flavors=9;
   85 
   86 #else
   87 #error architecture not supported
   88 #endif
   89 
   90 
   91 typedef struct {
   92         vm_offset_t header; 
   93         int  hoffset;
   94         mythread_state_flavor_t *flavors;
   95         int tstate_size;
   96 } tir_t;
   97 
   98 void
   99 collectth_state(thread_act_t th_act, tir_t *t)
  100 {
  101         vm_offset_t     header;
  102         int  hoffset, i ;
  103         mythread_state_flavor_t *flavors;
  104         struct thread_command   *tc;
  105                 /*
  106                  *      Fill in thread command structure.
  107                  */
  108                 header = t->header;
  109                 hoffset = t->hoffset;
  110                 flavors = t->flavors;
  111         
  112                 tc = (struct thread_command *) (header + hoffset);
  113                 tc->cmd = LC_THREAD;
  114                 tc->cmdsize = sizeof(struct thread_command)
  115                                 + t->tstate_size;
  116                 hoffset += sizeof(struct thread_command);
  117                 /*
  118                  * Follow with a struct thread_state_flavor and
  119                  * the appropriate thread state struct for each
  120                  * thread state flavor.
  121                  */
  122                 for (i = 0; i < mynum_flavors; i++) {
  123                         *(mythread_state_flavor_t *)(header+hoffset) =
  124                           flavors[i];
  125                         hoffset += sizeof(mythread_state_flavor_t);
  126                         thread_getstatus(th_act, flavors[i].flavor,
  127                                         (thread_state_t *)(header+hoffset),
  128                                         &flavors[i].count);
  129                         hoffset += flavors[i].count*sizeof(int);
  130                 }
  131 
  132                 t->hoffset = hoffset;
  133 }
  134 /*
  135  * Create a core image on the file "core".
  136  */
  137 #define MAX_TSTATE_FLAVORS      10
  138 int
  139 coredump(p)
  140         register struct proc *p;
  141 {
  142         int error=0;
  143         register struct pcred *pcred = p->p_cred;
  144         register struct ucred *cred = pcred->pc_ucred;
  145         struct nameidata nd;
  146         struct vattr    vattr;
  147         vm_map_t        map;
  148         int             thread_count, segment_count;
  149         int             command_size, header_size, tstate_size;
  150         int             hoffset, foffset, vmoffset;
  151         vm_offset_t     header;
  152         struct machine_slot     *ms;
  153         struct mach_header      *mh;
  154         struct segment_command  *sc;
  155         struct thread_command   *tc;
  156         vm_size_t       size;
  157         vm_prot_t       prot;
  158         vm_prot_t       maxprot;
  159         vm_inherit_t    inherit;
  160         vm_offset_t     offset;
  161         int             error1;
  162         task_t          task;
  163         char            core_name[MAXCOMLEN+6];
  164         mythread_state_flavor_t flavors[MAX_TSTATE_FLAVORS];
  165         vm_size_t       nflavors,mapsize;
  166         int             i;
  167         int nesting_depth = 0;
  168         kern_return_t   kret;
  169         struct vm_region_submap_info_64 vbr;
  170         int vbrcount=0;
  171         tir_t tir1;
  172         struct vnode * vp;
  173         extern boolean_t coredumpok(vm_map_t map, vm_offset_t va);  /* temp fix */
  174         extern task_t current_task();   /* XXX */
  175 
  176         if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid)
  177                 return (EFAULT);
  178 
  179         task = current_task();
  180         map = current_map();
  181         mapsize = get_vmmap_size(map);
  182 
  183         if (mapsize >=  p->p_rlimit[RLIMIT_CORE].rlim_cur)
  184                 return (EFAULT);
  185         (void) task_suspend(task);
  186 
  187         sprintf(core_name, "/cores/core.%d", p->p_pid);
  188         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, core_name, p);
  189         if(error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR ))
  190                 return (error);
  191         vp = nd.ni_vp;
  192         
  193         /* Don't dump to non-regular files or files with links. */
  194         if (vp->v_type != VREG ||
  195             VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
  196                 error = EFAULT;
  197                 goto out;
  198         }
  199 
  200         VATTR_NULL(&vattr);
  201         vattr.va_size = 0;
  202         VOP_LEASE(vp, p, cred, LEASE_WRITE);
  203         VOP_SETATTR(vp, &vattr, cred, p);
  204         p->p_acflag |= ACORE;
  205 
  206         /*
  207          *      If the task is modified while dumping the file
  208          *      (e.g., changes in threads or VM, the resulting
  209          *      file will not necessarily be correct.
  210          */
  211 
  212         thread_count = get_task_numacts(task);
  213         segment_count = get_vmmap_entries(map); /* XXX */
  214         /*
  215          * nflavors here is really the number of ints in flavors
  216          * to meet the thread_getstatus() calling convention
  217          */
  218         nflavors = mynum_flavors;
  219         bcopy(thread_flavor_array,flavors,sizeof(thread_flavor_array));
  220         tstate_size = 0;
  221         for (i = 0; i < nflavors; i++)
  222                 tstate_size += sizeof(mythread_state_flavor_t) +
  223                   (flavors[i].count * sizeof(int));
  224 
  225         command_size = segment_count*sizeof(struct segment_command) +
  226           thread_count*sizeof(struct thread_command) +
  227           tstate_size*thread_count;
  228 
  229         header_size = command_size + sizeof(struct mach_header);
  230 
  231         (void) kmem_alloc_wired(kernel_map,
  232                                     (vm_offset_t *)&header,
  233                                     (vm_size_t)header_size);
  234 
  235         /*
  236          *      Set up Mach-O header.
  237          */
  238         mh = (struct mach_header *) header;
  239         ms = &machine_slot[cpu_number()];
  240         mh->magic = MH_MAGIC;
  241         mh->cputype = ms->cpu_type;
  242         mh->cpusubtype = ms->cpu_subtype;
  243         mh->filetype = MH_CORE;
  244         mh->ncmds = segment_count + thread_count;
  245         mh->sizeofcmds = command_size;
  246 
  247         hoffset = sizeof(struct mach_header);   /* offset into header */
  248         foffset = round_page_32(header_size);   /* offset into file */
  249         vmoffset = VM_MIN_ADDRESS;              /* offset into VM */
  250         /*
  251          * We use to check for an error, here, now we try and get 
  252          * as much as we can
  253          */
  254         while (segment_count > 0){
  255                 /*
  256                  *      Get region information for next region.
  257                  */
  258                 
  259                 while (1) {
  260                         vbrcount = VM_REGION_SUBMAP_INFO_COUNT_64;
  261                         if((kret = vm_region_recurse_64(map, 
  262                                         &vmoffset, &size, &nesting_depth, 
  263                                         &vbr, &vbrcount)) != KERN_SUCCESS) {
  264                                 break;
  265                         }
  266                         if(vbr.is_submap) {
  267                                 nesting_depth++;
  268                                 continue;
  269                         } else {
  270                                 break;
  271                         }
  272                 }
  273                 if(kret != KERN_SUCCESS)
  274                         break;
  275 
  276                 prot = vbr.protection;
  277                 maxprot = vbr.max_protection;
  278                 inherit = vbr.inheritance;
  279                 /*
  280                  *      Fill in segment command structure.
  281                  */
  282                 sc = (struct segment_command *) (header + hoffset);
  283                 sc->cmd = LC_SEGMENT;
  284                 sc->cmdsize = sizeof(struct segment_command);
  285                 /* segment name is zerod by kmem_alloc */
  286                 sc->segname[0] = 0;
  287                 sc->vmaddr = vmoffset;
  288                 sc->vmsize = size;
  289                 sc->fileoff = foffset;
  290                 sc->filesize = size;
  291                 sc->maxprot = maxprot;
  292                 sc->initprot = prot;
  293                 sc->nsects = 0;
  294 
  295                 /*
  296                  *      Write segment out.  Try as hard as possible to
  297                  *      get read access to the data.
  298                  */
  299                 if ((prot & VM_PROT_READ) == 0) {
  300                         vm_protect(map, vmoffset, size, FALSE,
  301                                    prot|VM_PROT_READ);
  302                 }
  303                 /*
  304                  *      Only actually perform write if we can read.
  305                  *      Note: if we can't read, then we end up with
  306                  *      a hole in the file.
  307                  */
  308                 if ((maxprot & VM_PROT_READ) == VM_PROT_READ
  309                         && vbr.user_tag != VM_MEMORY_IOKIT
  310                         && coredumpok(map,vmoffset)) {
  311                         error = vn_rdwr(UIO_WRITE, vp, (caddr_t)vmoffset, size, foffset,
  312                                 UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
  313                 }
  314 
  315                 hoffset += sizeof(struct segment_command);
  316                 foffset += size;
  317                 vmoffset += size;
  318                 segment_count--;
  319         }
  320 
  321         tir1.header = header;
  322         tir1.hoffset = hoffset;
  323         tir1.flavors = flavors;
  324         tir1.tstate_size = tstate_size;
  325         task_act_iterate_wth_args(task, collectth_state,&tir1);
  326 
  327         /*
  328          *      Write out the Mach header at the beginning of the
  329          *      file.
  330          */
  331         error = vn_rdwr(UIO_WRITE, vp, (caddr_t)header, header_size, (off_t)0,
  332                         UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
  333         kmem_free(kernel_map, header, header_size);
  334 out:
  335         VOP_UNLOCK(vp, 0, p);
  336         error1 = vn_close(vp, FWRITE, cred, p);
  337         if (error == 0)
  338                 error = error1;
  339         return (error);
  340 }

Cache object: 3b886688ab5289be0abbc316b3e406d7


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