|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.