Annotation of src/usr.bin/gcore/gcore.c, Revision 1.1.1.1
1.1 deraadt 1: /* $NetBSD: gcore.c,v 1.2 1995/09/05 02:51:00 tls Exp $ */
2:
3: /*-
4: * Copyright (c) 1992, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: static char copyright[] =
38: "@(#) Copyright (c) 1992, 1993\n\
39: The Regents of the University of California. All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: #if 0
44: static char sccsid[] = "@(#)gcore.c 8.2 (Berkeley) 9/23/93";
45: #else
46: static char rcsid[] = "$NetBSD: gcore.c,v 1.2 1995/09/05 02:51:00 tls Exp $";
47: #endif
48: #endif /* not lint */
49:
50: /*
51: * Originally written by Eric Cooper in Fall 1981.
52: * Inspired by a version 6 program by Len Levin, 1978.
53: * Several pieces of code lifted from Bill Joy's 4BSD ps.
54: * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
55: * Lawrence Berkeley Laboratory.
56: *
57: * Portions of this software were developed by the Computer Systems
58: * Engineering group at Lawrence Berkeley Laboratory under DARPA
59: * contract BG 91-66 and contributed to Berkeley.
60: */
61: #include <sys/param.h>
62: #include <sys/time.h>
63: #include <sys/stat.h>
64: #include <sys/proc.h>
65: #include <sys/user.h>
66: #include <sys/sysctl.h>
67:
68: #include <machine/vmparam.h>
69:
70: #include <a.out.h>
71: #include <fcntl.h>
72: #include <kvm.h>
73: #include <limits.h>
74: #include <signal.h>
75: #include <stdio.h>
76: #include <stdlib.h>
77: #include <string.h>
78: #include <unistd.h>
79:
80: #include "extern.h"
81:
82: void core __P((int, int, struct kinfo_proc *));
83: void datadump __P((int, int, struct proc *, u_long, int));
84: void usage __P((void));
85: void userdump __P((int, struct proc *, u_long, int));
86:
87: kvm_t *kd;
88: /* XXX undocumented routine, should be in kvm.h? */
89: ssize_t kvm_uread __P((kvm_t *, struct proc *, u_long, char *, size_t));
90:
91: static int data_offset;
92:
93: int
94: main(argc, argv)
95: int argc;
96: char *argv[];
97: {
98: register struct proc *p;
99: struct kinfo_proc *ki;
100: struct exec exec;
101: int ch, cnt, efd, fd, pid, sflag, uid;
102: char *corefile, errbuf[_POSIX2_LINE_MAX], fname[MAXPATHLEN + 1];
103:
104: sflag = 0;
105: corefile = NULL;
106: while ((ch = getopt(argc, argv, "c:s")) != EOF) {
107: switch (ch) {
108: case 'c':
109: corefile = optarg;
110: break;
111: case 's':
112: sflag = 1;
113: break;
114: default:
115: usage();
116: break;
117: }
118: }
119: argv += optind;
120: argc -= optind;
121:
122: if (argc != 2)
123: usage();
124:
125: kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
126: if (kd == NULL)
127: err(1, "%s", errbuf);
128:
129: uid = getuid();
130: pid = atoi(argv[1]);
131:
132: ki = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt);
133: if (ki == NULL || cnt != 1)
134: err(1, "%d: not found", pid);
135:
136: p = &ki->kp_proc;
137: if (ki->kp_eproc.e_pcred.p_ruid != uid && uid != 0)
138: err(1, "%d: not owner", pid);
139:
140: if (p->p_stat == SZOMB)
141: err(1, "%d: zombie", pid);
142:
143: if (p->p_flag & P_WEXIT)
144: err(0, "process exiting");
145: if (p->p_flag & P_SYSTEM) /* Swapper or pagedaemon. */
146: err(1, "%d: system process");
147:
148: if (corefile == NULL) {
149: (void)snprintf(fname, sizeof(fname), "core.%d", pid);
150: corefile = fname;
151: }
152: fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
153: if (fd < 0)
154: err(1, "%s: %s\n", corefile, strerror(errno));
155:
156: efd = open(argv[0], O_RDONLY, 0);
157: if (efd < 0)
158: err(1, "%s: %s\n", argv[0], strerror(errno));
159:
160: cnt = read(efd, &exec, sizeof(exec));
161: if (cnt != sizeof(exec))
162: err(1, "%s exec header: %s",
163: argv[0], cnt > 0 ? strerror(EIO) : strerror(errno));
164:
165: data_offset = N_DATOFF(exec);
166:
167: if (sflag && kill(pid, SIGSTOP) < 0)
168: err(0, "%d: stop signal: %s", pid, strerror(errno));
169:
170: core(efd, fd, ki);
171:
172: if (sflag && kill(pid, SIGCONT) < 0)
173: err(0, "%d: continue signal: %s", pid, strerror(errno));
174: (void)close(fd);
175:
176: exit(0);
177: }
178:
179: /*
180: * core --
181: * Build the core file.
182: */
183: void
184: core(efd, fd, ki)
185: int efd;
186: int fd;
187: struct kinfo_proc *ki;
188: {
189: union {
190: struct user user;
191: char ubytes[ctob(UPAGES)];
192: } uarea;
193: struct proc *p = &ki->kp_proc;
194: int tsize = ki->kp_eproc.e_vm.vm_tsize;
195: int dsize = ki->kp_eproc.e_vm.vm_dsize;
196: int ssize = ki->kp_eproc.e_vm.vm_ssize;
197: int cnt;
198:
199: /* Read in user struct */
200: cnt = kvm_read(kd, (u_long)p->p_addr, &uarea, sizeof(uarea));
201: if (cnt != sizeof(uarea))
202: err(1, "read user structure: %s",
203: cnt > 0 ? strerror(EIO) : strerror(errno));
204:
205: /*
206: * Fill in the eproc vm parameters, since these are garbage unless
207: * the kernel is dumping core or something.
208: */
209: uarea.user.u_kproc = *ki;
210:
211: /* Dump user area */
212: cnt = write(fd, &uarea, sizeof(uarea));
213: if (cnt != sizeof(uarea))
214: err(1, "write user structure: %s",
215: cnt > 0 ? strerror(EIO) : strerror(errno));
216:
217: /* Dump data segment */
218: datadump(efd, fd, p, USRTEXT + ctob(tsize), dsize);
219:
220: /* Dump stack segment */
221: userdump(fd, p, USRSTACK - ctob(ssize), ssize);
222:
223: /* Dump machine dependent portions of the core. */
224: md_core(kd, fd, ki);
225: }
226:
227: void
228: datadump(efd, fd, p, addr, npage)
229: register int efd;
230: register int fd;
231: struct proc *p;
232: register u_long addr;
233: register int npage;
234: {
235: register int cc, delta;
236: char buffer[NBPG];
237:
238: delta = data_offset - addr;
239: while (--npage >= 0) {
240: cc = kvm_uread(kd, p, addr, buffer, NBPG);
241: if (cc != NBPG) {
242: /* Try to read the page from the executable. */
243: if (lseek(efd, (off_t)addr + delta, SEEK_SET) == -1)
244: err(1, "seek executable: %s", strerror(errno));
245: cc = read(efd, buffer, sizeof(buffer));
246: if (cc != sizeof(buffer))
247: if (cc < 0)
248: err(1, "read executable: %s",
249: strerror(errno));
250: else /* Assume untouched bss page. */
251: bzero(buffer, sizeof(buffer));
252: }
253: cc = write(fd, buffer, NBPG);
254: if (cc != NBPG)
255: err(1, "write data segment: %s",
256: cc > 0 ? strerror(EIO) : strerror(errno));
257: addr += NBPG;
258: }
259: }
260:
261: void
262: userdump(fd, p, addr, npage)
263: register int fd;
264: struct proc *p;
265: register u_long addr;
266: register int npage;
267: {
268: register int cc;
269: char buffer[NBPG];
270:
271: while (--npage >= 0) {
272: cc = kvm_uread(kd, p, addr, buffer, NBPG);
273: if (cc != NBPG)
274: /* Could be an untouched fill-with-zero page. */
275: bzero(buffer, NBPG);
276: cc = write(fd, buffer, NBPG);
277: if (cc != NBPG)
278: err(1, "write stack segment: %s",
279: cc > 0 ? strerror(EIO) : strerror(errno));
280: addr += NBPG;
281: }
282: }
283:
284: void
285: usage()
286: {
287: (void)fprintf(stderr, "usage: gcore [-s] [-c core] executable pid\n");
288: exit(1);
289: }
290:
291: #if __STDC__
292: #include <stdarg.h>
293: #else
294: #include <varargs.h>
295: #endif
296:
297: void
298: #if __STDC__
299: err(int fatal, const char *fmt, ...)
300: #else
301: err(fatal, fmt, va_alist)
302: int fatal;
303: char *fmt;
304: va_dcl
305: #endif
306: {
307: va_list ap;
308: #if __STDC__
309: va_start(ap, fmt);
310: #else
311: va_start(ap);
312: #endif
313: (void)fprintf(stderr, "gcore: ");
314: (void)vfprintf(stderr, fmt, ap);
315: va_end(ap);
316: (void)fprintf(stderr, "\n");
317: exit(1);
318: /* NOTREACHED */
319: }