Annotation of kernel/bsd/kern/kern_core.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     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:  * HISTORY
                     32:  * 16-Feb-91  Mike DeMoney ([email protected])
                     33:  *     Massaged into MI form from m68k/core.c.
                     34:  */
                     35: #import <cputypes.h>
                     36: #import <mach_host.h>
                     37: 
                     38: #import <mach/vm_param.h>
                     39: #import <mach/thread_status.h>
                     40: 
                     41: #import <machine/spl.h>
                     42: #import <machine/cpu.h>
                     43: #import <machine/reg.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: #import <mach-o/loader.h>
                     62: 
                     63: #import <kern/sched.h>
                     64: #import <kern/thread.h>
                     65: #import <kern/parallel.h>
                     66: #import <kern/sched_prim.h>
                     67: #import <kern/task.h>
                     68: #import <vm/vm_kern.h>
                     69: 
                     70: /*
                     71:  * Create a core image on the file "core".
                     72:  */
                     73: #define        MAX_TSTATE_FLAVORS      10
                     74: int
                     75: coredump(p)
                     76:        register struct proc *p;
                     77: {
                     78:        register struct vnode   *vp;
                     79:        register struct pcred *pcred = p->p_cred;
                     80:        register struct ucred *cred = pcred->pc_ucred;
                     81:        struct nameidata nd;
                     82:        struct vattr    vattr;
                     83:        vm_map_t        map;
                     84:        int             thread_count, segment_count;
                     85:        int             command_size, header_size, tstate_size;
                     86:        int             hoffset, foffset, vmoffset;
                     87:        vm_offset_t     header;
                     88:        struct machine_slot     *ms;
                     89:        struct mach_header      *mh;
                     90:        struct segment_command  *sc;
                     91:        struct thread_command   *tc;
                     92:        vm_size_t       size;
                     93:        vm_prot_t       prot;
                     94:        vm_prot_t       maxprot;
                     95:        vm_inherit_t    inherit;
                     96:        boolean_t       is_shared;
                     97:        port_t          name;
                     98:        vm_offset_t     offset;
                     99:        int             error, error1;
                    100:        task_t          task;
                    101:        thread_t        thread;
                    102:        char            core_name[MAXCOMLEN+6];
                    103:        struct thread_state_flavor flavors[MAX_TSTATE_FLAVORS];
                    104:        vm_size_t       nflavors;
                    105:        int             i;
                    106: 
                    107: 
                    108:        if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid)
                    109:                return (EFAULT);
                    110: 
                    111:        task = current_task();
                    112:        map = task->map;
                    113:        if (map->size >=  p->p_rlimit[RLIMIT_CORE].rlim_cur)
                    114:                return (EFAULT);
                    115:        (void) task_halt(task); /* stop this task, except for current thread */
                    116:        /*
                    117:         *      Make sure all registers, etc. are in pcb so they get
                    118:         *      into core file.
                    119:         */
                    120:        pcb_synch(current_thread());
                    121:        sprintf(core_name, "/cores/core.%d", p->p_pid);
                    122:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, core_name, p);
                    123:        if(error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR ))
                    124:                return (error);
                    125:        vp = nd.ni_vp;
                    126:        
                    127:        /* Don't dump to non-regular files or files with links. */
                    128:        if (vp->v_type != VREG ||
                    129:            VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
                    130:                error = EFAULT;
                    131:                goto out;
                    132:        }
                    133: 
                    134:        VATTR_NULL(&vattr);
                    135:        vattr.va_size = 0;
                    136:        VOP_LEASE(vp, p, cred, LEASE_WRITE);
                    137:        VOP_SETATTR(vp, &vattr, cred, p);
                    138:        p->p_acflag |= ACORE;
                    139: 
                    140:        /*
                    141:         *      If the task is modified while dumping the file
                    142:         *      (e.g., changes in threads or VM, the resulting
                    143:         *      file will not necessarily be correct.
                    144:         */
                    145: 
                    146:        thread_count = task->thread_count;
                    147:        segment_count = map->hdr.nentries;      /* XXX */
                    148:        /*
                    149:         * nflavors here is really the number of ints in flavors
                    150:         * to meet the thread_getstatus() calling convention
                    151:         */
                    152:        nflavors = sizeof(flavors)/sizeof(int);
                    153:        if (thread_getstatus(current_thread(), THREAD_STATE_FLAVOR_LIST,
                    154:                                (thread_state_t)(flavors),
                    155:                                 &nflavors) != KERN_SUCCESS)
                    156:            panic("core flavor list");
                    157:        /* now convert to number of flavors */
                    158:        nflavors /= sizeof(struct thread_state_flavor)/sizeof(int);
                    159: 
                    160:        tstate_size = 0;
                    161:        for (i = 0; i < nflavors; i++)
                    162:                tstate_size += sizeof(struct thread_state_flavor) +
                    163:                  (flavors[i].count * sizeof(int));
                    164: 
                    165:        command_size = segment_count*sizeof(struct segment_command) +
                    166:          thread_count*sizeof(struct thread_command) +
                    167:          tstate_size*thread_count;
                    168: 
                    169:        header_size = command_size + sizeof(struct mach_header);
                    170: 
                    171:        (void) kmem_alloc_wired(kernel_map,
                    172:                                    (vm_offset_t *)&header,
                    173:                                    (vm_size_t)header_size);
                    174: 
                    175:        /*
                    176:         *      Set up Mach-O header.
                    177:         */
                    178:        mh = (struct mach_header *) header;
                    179:        ms = &machine_slot[cpu_number()];
                    180:        mh->magic = MH_MAGIC;
                    181:        mh->cputype = ms->cpu_type;
                    182:        mh->cpusubtype = ms->cpu_subtype;
                    183:        mh->filetype = MH_CORE;
                    184:        mh->ncmds = segment_count + thread_count;
                    185:        mh->sizeofcmds = command_size;
                    186: 
                    187:        hoffset = sizeof(struct mach_header);   /* offset into header */
                    188:        foffset = round_page(header_size);      /* offset into file */
                    189:        vmoffset = VM_MIN_ADDRESS;              /* offset into VM */
                    190:        /* We use to check for an error, here, now we try and get 
                    191:         * as much as we can
                    192:         */
                    193:        while (segment_count > 0){
                    194:                /*
                    195:                 *      Get region information for next region.
                    196:                 */
                    197:                if (vm_region(map, &vmoffset, &size, &prot, &maxprot,
                    198:                          &inherit, &is_shared, &name, &offset)
                    199:                                        == KERN_NO_SPACE)
                    200:                        break;
                    201: 
                    202:                /*
                    203:                 *      Fill in segment command structure.
                    204:                 */
                    205:                sc = (struct segment_command *) (header + hoffset);
                    206:                sc->cmd = LC_SEGMENT;
                    207:                sc->cmdsize = sizeof(struct segment_command);
                    208:                /* segment name is zerod by kmem_alloc */
                    209:                sc->vmaddr = vmoffset;
                    210:                sc->vmsize = size;
                    211:                sc->fileoff = foffset;
                    212:                sc->filesize = size;
                    213:                sc->maxprot = maxprot;
                    214:                sc->initprot = prot;
                    215:                sc->nsects = 0;
                    216: 
                    217:                /*
                    218:                 *      Write segment out.  Try as hard as possible to
                    219:                 *      get read access to the data.
                    220:                 */
                    221:                if ((prot & VM_PROT_READ) == 0) {
                    222:                        vm_protect(map, vmoffset, size, FALSE,
                    223:                                   prot|VM_PROT_READ);
                    224:                }
                    225:                /*
                    226:                 *      Only actually perform write if we can read.
                    227:                 *      Note: if we can't read, then we end up with
                    228:                 *      a hole in the file.
                    229:                 */
                    230:                if ((maxprot & VM_PROT_READ) == VM_PROT_READ) {
                    231:                        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)vmoffset, size, foffset,
                    232:                                UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
                    233:                }
                    234: 
                    235:                hoffset += sizeof(struct segment_command);
                    236:                foffset += size;
                    237:                vmoffset += size;
                    238:                segment_count--;
                    239:        }
                    240:        task_lock(task);
                    241:        thread = (thread_t) queue_first(&task->thread_list);
                    242:        while (thread_count > 0) {
                    243:                /*
                    244:                 *      Fill in thread command structure.
                    245:                 */
                    246:                tc = (struct thread_command *) (header + hoffset);
                    247:                tc->cmd = LC_THREAD;
                    248:                tc->cmdsize = sizeof(struct thread_command)
                    249:                                + tstate_size;
                    250:                hoffset += sizeof(struct thread_command);
                    251:                /*
                    252:                 * Follow with a struct thread_state_flavor and
                    253:                 * the appropriate thread state struct for each
                    254:                 * thread state flavor.
                    255:                 */
                    256:                for (i = 0; i < nflavors; i++) {
                    257:                        *(struct thread_state_flavor *)(header+hoffset) =
                    258:                          flavors[i];
                    259:                        hoffset += sizeof(struct thread_state_flavor);
                    260:                        thread_getstatus(thread, flavors[i].flavor,
                    261:                                        (thread_state_t *)(header+hoffset),
                    262:                                        &flavors[i].count);
                    263:                        hoffset += flavors[i].count*sizeof(int);
                    264:                }
                    265:                thread = (thread_t) queue_next(&thread->thread_list);
                    266:                thread_count--;
                    267:        }
                    268:        task_unlock(task);
                    269: 
                    270:        /*
                    271:         *      Write out the Mach header at the beginning of the
                    272:         *      file.
                    273:         */
                    274:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)header, header_size, (off_t)0,
                    275:                        UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
                    276:        kmem_free(kernel_map, header, header_size);
                    277: out:
                    278:        VOP_UNLOCK(vp, 0, p);
                    279:        error1 = vn_close(vp, FWRITE, cred, p);
                    280:        if (error == 0)
                    281:                error = error1;
                    282:        return(error);
                    283: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.