Annotation of kernel/bsd/kern/kern_core.c, revision 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.