|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved. ! 23: * ! 24: * File: bsd/kern/kern_core.c ! 25: * ! 26: * This file contains machine independent code for performing core dumps. ! 27: * ! 28: * HISTORY ! 29: * 16-Feb-91 Mike DeMoney ([email protected]) ! 30: * Massaged into MI form from m68k/core.c. ! 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: ! 55: #include <vm/vm_kern.h> ! 56: ! 57: typedef struct { ! 58: int flavor; /* the number for this flavor */ ! 59: int count; /* count of ints in this flavor */ ! 60: } mythread_state_flavor_t; ! 61: ! 62: #if defined (__ppc__) ! 63: ! 64: mythread_state_flavor_t thread_flavor_array[]={ ! 65: {PPC_THREAD_STATE , PPC_THREAD_STATE_COUNT}, ! 66: {PPC_FLOAT_STATE, PPC_FLOAT_STATE_COUNT}, ! 67: {PPC_EXCEPTION_STATE, PPC_EXCEPTION_STATE_COUNT} ! 68: }; ! 69: int mynum_flavors=3; ! 70: #elif defined (__i386__) ! 71: mythread_state_flavor_t thread_flavor_array [] = { ! 72: {i386_THREAD_STATE, i386_THREAD_STATE_COUNT}, ! 73: {i386_THREAD_FPSTATE, i386_THREAD_FPSTATE_COUNT}, ! 74: {i386_THREAD_EXCEPTSTATE, i386_THREAD_EXCEPTSTATE_COUNT}, ! 75: {i386_THREAD_CTHREADSTATE, i386_THREAD_CTHREADSTATE_COUNT}, ! 76: {i386_NEW_THREAD_STATE, i386_NEW_THREAD_STATE_COUNT}, ! 77: {i386_FLOAT_STATE, i386_FLOAT_STATE_COUNT}, ! 78: {i386_ISA_PORT_MAP_STATE, i386_ISA_PORT_MAP_STATE_COUNT}, ! 79: {i386_V86_ASSIST_STATE, i386_V86_ASSIST_STATE_COUNT}, ! 80: {THREAD_SYSCALL_STATE, i386_THREAD_SYSCALL_STATE_COUNT} ! 81: }; ! 82: int mynum_flavors=9; ! 83: ! 84: #else ! 85: #error architecture not supported ! 86: #endif ! 87: ! 88: ! 89: typedef struct { ! 90: vm_offset_t header; ! 91: int hoffset; ! 92: mythread_state_flavor_t *flavors; ! 93: int tstate_size; ! 94: } tir_t; ! 95: ! 96: collectth_state(thread_act_t th_act, tir_t *t) ! 97: { ! 98: vm_offset_t header; ! 99: int hoffset, i ; ! 100: mythread_state_flavor_t *flavors; ! 101: struct thread_command *tc; ! 102: /* ! 103: * Fill in thread command structure. ! 104: */ ! 105: header = t->header; ! 106: hoffset = t->hoffset; ! 107: flavors = t->flavors; ! 108: ! 109: tc = (struct thread_command *) (header + hoffset); ! 110: tc->cmd = LC_THREAD; ! 111: tc->cmdsize = sizeof(struct thread_command) ! 112: + t->tstate_size; ! 113: hoffset += sizeof(struct thread_command); ! 114: /* ! 115: * Follow with a struct thread_state_flavor and ! 116: * the appropriate thread state struct for each ! 117: * thread state flavor. ! 118: */ ! 119: for (i = 0; i < mynum_flavors; i++) { ! 120: *(mythread_state_flavor_t *)(header+hoffset) = ! 121: flavors[i]; ! 122: hoffset += sizeof(mythread_state_flavor_t); ! 123: thread_getstatus(th_act, flavors[i].flavor, ! 124: (thread_state_t *)(header+hoffset), ! 125: &flavors[i].count); ! 126: hoffset += flavors[i].count*sizeof(int); ! 127: } ! 128: ! 129: t->hoffset = hoffset; ! 130: } ! 131: /* ! 132: * Create a core image on the file "core". ! 133: */ ! 134: #define MAX_TSTATE_FLAVORS 10 ! 135: int ! 136: coredump(p) ! 137: register struct proc *p; ! 138: { ! 139: int error=0; ! 140: register struct pcred *pcred = p->p_cred; ! 141: register struct ucred *cred = pcred->pc_ucred; ! 142: struct nameidata nd; ! 143: struct vattr vattr; ! 144: vm_map_t map; ! 145: int thread_count, segment_count; ! 146: int command_size, header_size, tstate_size; ! 147: int hoffset, foffset, vmoffset; ! 148: vm_offset_t header; ! 149: struct machine_slot *ms; ! 150: struct mach_header *mh; ! 151: struct segment_command *sc; ! 152: struct thread_command *tc; ! 153: vm_size_t size; ! 154: vm_prot_t prot; ! 155: vm_prot_t maxprot; ! 156: vm_inherit_t inherit; ! 157: boolean_t is_shared; ! 158: vm_offset_t offset; ! 159: int error1; ! 160: task_t task; ! 161: char core_name[MAXCOMLEN+6]; ! 162: mythread_state_flavor_t flavors[MAX_TSTATE_FLAVORS]; ! 163: vm_size_t nflavors,mapsize; ! 164: int i; ! 165: struct vm_region_basic_info vbr; ! 166: int vbrcount=0; ! 167: tir_t tir1; ! 168: struct vnode * vp; ! 169: ! 170: ! 171: if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid) ! 172: return (EFAULT); ! 173: ! 174: task = current_task(); ! 175: map = current_map(); ! 176: mapsize = get_vmmap_size(map); ! 177: ! 178: if (mapsize >= p->p_rlimit[RLIMIT_CORE].rlim_cur) ! 179: return (EFAULT); ! 180: (void) task_suspend(task); ! 181: ! 182: /* ! 183: * Make sure all registers, etc. are in pcb so they get ! 184: * into core file. ! 185: */ ! 186: #if defined (__ppc__) ! 187: fpu_save(); ! 188: #endif ! 189: sprintf(core_name, "/cores/core.%d", p->p_pid); ! 190: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, core_name, p); ! 191: if(error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR )) ! 192: return (error); ! 193: vp = nd.ni_vp; ! 194: ! 195: /* Don't dump to non-regular files or files with links. */ ! 196: if (vp->v_type != VREG || ! 197: VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { ! 198: error = EFAULT; ! 199: goto out; ! 200: } ! 201: ! 202: VATTR_NULL(&vattr); ! 203: vattr.va_size = 0; ! 204: VOP_LEASE(vp, p, cred, LEASE_WRITE); ! 205: VOP_SETATTR(vp, &vattr, cred, p); ! 206: p->p_acflag |= ACORE; ! 207: ! 208: /* ! 209: * If the task is modified while dumping the file ! 210: * (e.g., changes in threads or VM, the resulting ! 211: * file will not necessarily be correct. ! 212: */ ! 213: ! 214: thread_count = get_task_numacts(task); ! 215: segment_count = get_vmmap_entries(map); /* XXX */ ! 216: /* ! 217: * nflavors here is really the number of ints in flavors ! 218: * to meet the thread_getstatus() calling convention ! 219: */ ! 220: #if 0 ! 221: nflavors = sizeof(flavors)/sizeof(int); ! 222: if (thread_getstatus(current_thread(), THREAD_STATE_FLAVOR_LIST, ! 223: (thread_state_t)(flavors), ! 224: &nflavors) != KERN_SUCCESS) ! 225: panic("core flavor list"); ! 226: /* now convert to number of flavors */ ! 227: nflavors /= sizeof(mythread_state_flavor_t)/sizeof(int); ! 228: #else ! 229: nflavors = mynum_flavors; ! 230: bcopy(thread_flavor_array,flavors,sizeof(thread_flavor_array)); ! 231: #endif ! 232: tstate_size = 0; ! 233: for (i = 0; i < nflavors; i++) ! 234: tstate_size += sizeof(mythread_state_flavor_t) + ! 235: (flavors[i].count * sizeof(int)); ! 236: ! 237: command_size = segment_count*sizeof(struct segment_command) + ! 238: thread_count*sizeof(struct thread_command) + ! 239: tstate_size*thread_count; ! 240: ! 241: header_size = command_size + sizeof(struct mach_header); ! 242: ! 243: (void) kmem_alloc_wired(kernel_map, ! 244: (vm_offset_t *)&header, ! 245: (vm_size_t)header_size); ! 246: ! 247: /* ! 248: * Set up Mach-O header. ! 249: */ ! 250: mh = (struct mach_header *) header; ! 251: ms = &machine_slot[cpu_number()]; ! 252: mh->magic = MH_MAGIC; ! 253: mh->cputype = ms->cpu_type; ! 254: mh->cpusubtype = ms->cpu_subtype; ! 255: mh->filetype = MH_CORE; ! 256: mh->ncmds = segment_count + thread_count; ! 257: mh->sizeofcmds = command_size; ! 258: ! 259: hoffset = sizeof(struct mach_header); /* offset into header */ ! 260: foffset = round_page(header_size); /* offset into file */ ! 261: vmoffset = VM_MIN_ADDRESS; /* offset into VM */ ! 262: /* We use to check for an error, here, now we try and get ! 263: * as much as we can ! 264: */ ! 265: while (segment_count > 0){ ! 266: vbrcount = VM_REGION_BASIC_INFO_COUNT; ! 267: /* ! 268: * Get region information for next region. ! 269: */ ! 270: if (vm_region(map, &vmoffset, &size, VM_REGION_BASIC_INFO, &vbr, &vbrcount,0) != KERN_SUCCESS) ! 271: break; ! 272: prot = vbr.protection; ! 273: maxprot = vbr.max_protection; ! 274: inherit = vbr.inheritance; ! 275: is_shared = vbr.shared; ! 276: /* ! 277: * Fill in segment command structure. ! 278: */ ! 279: sc = (struct segment_command *) (header + hoffset); ! 280: sc->cmd = LC_SEGMENT; ! 281: sc->cmdsize = sizeof(struct segment_command); ! 282: /* segment name is zerod by kmem_alloc */ ! 283: sc->vmaddr = vmoffset; ! 284: sc->vmsize = size; ! 285: sc->fileoff = foffset; ! 286: sc->filesize = size; ! 287: sc->maxprot = maxprot; ! 288: sc->initprot = prot; ! 289: sc->nsects = 0; ! 290: ! 291: /* ! 292: * Write segment out. Try as hard as possible to ! 293: * get read access to the data. ! 294: */ ! 295: if ((prot & VM_PROT_READ) == 0) { ! 296: vm_protect(map, vmoffset, size, FALSE, ! 297: prot|VM_PROT_READ); ! 298: } ! 299: /* ! 300: * Only actually perform write if we can read. ! 301: * Note: if we can't read, then we end up with ! 302: * a hole in the file. ! 303: */ ! 304: if ((maxprot & VM_PROT_READ) == VM_PROT_READ) { ! 305: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)vmoffset, size, foffset, ! 306: UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); ! 307: } ! 308: ! 309: hoffset += sizeof(struct segment_command); ! 310: foffset += size; ! 311: vmoffset += size; ! 312: segment_count--; ! 313: } ! 314: ! 315: #if 0 /* [ */ ! 316: task_lock(task); ! 317: thread = (thread_t) queue_first(&task->thread_list); ! 318: while (thread_count > 0) { ! 319: /* ! 320: * Fill in thread command structure. ! 321: */ ! 322: tc = (struct thread_command *) (header + hoffset); ! 323: tc->cmd = LC_THREAD; ! 324: tc->cmdsize = sizeof(struct thread_command) ! 325: + tstate_size; ! 326: hoffset += sizeof(struct thread_command); ! 327: /* ! 328: * Follow with a struct thread_state_flavor and ! 329: * the appropriate thread state struct for each ! 330: * thread state flavor. ! 331: */ ! 332: for (i = 0; i < nflavors; i++) { ! 333: *(mythread_state_flavor_t *)(header+hoffset) = ! 334: flavors[i]; ! 335: hoffset += sizeof(mythread_state_flavor_t); ! 336: thread_getstatus(thread, flavors[i].flavor, ! 337: (thread_state_t *)(header+hoffset), ! 338: &flavors[i].count); ! 339: hoffset += flavors[i].count*sizeof(int); ! 340: } ! 341: thread = (thread_t) queue_next(&thread->thread_list); ! 342: thread_count--; ! 343: } ! 344: task_unlock(task); ! 345: #else /* /* 0 ][ */ ! 346: tir1.header = header; ! 347: tir1.hoffset = hoffset; ! 348: tir1.flavors = flavors; ! 349: tir1.tstate_size = tstate_size; ! 350: task_act_iterate_wth_args(task, collectth_state,&tir1); ! 351: ! 352: #endif /* 0 ] */ ! 353: /* ! 354: * Write out the Mach header at the beginning of the ! 355: * file. ! 356: */ ! 357: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)header, header_size, (off_t)0, ! 358: UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); ! 359: kmem_free(kernel_map, header, header_size); ! 360: out: ! 361: VOP_UNLOCK(vp, 0, p); ! 362: error1 = vn_close(vp, FWRITE, cred, p); ! 363: if (error == 0) ! 364: error = error1; ! 365: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.