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