Deleted Added
full compact
gcore.c (102944) gcore.c (103299)
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 29 unchanged lines hidden (view full) ---

38#endif /* not lint */
39
40#if 0
41#ifndef lint
42static char sccsid[] = "@(#)gcore.c 8.2 (Berkeley) 9/23/93";
43#endif /* not lint */
44#endif
45#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 29 unchanged lines hidden (view full) ---

38#endif /* not lint */
39
40#if 0
41#ifndef lint
42static char sccsid[] = "@(#)gcore.c 8.2 (Berkeley) 9/23/93";
43#endif /* not lint */
44#endif
45#include <sys/cdefs.h>
46__FBSDID("$FreeBSD: head/usr.bin/gcore/gcore.c 102944 2002-09-04 23:29:10Z dwmalone $");
46__FBSDID("$FreeBSD: head/usr.bin/gcore/gcore.c 103299 2002-09-13 16:33:35Z peter $");
47
48/*
49 * Originally written by Eric Cooper in Fall 1981.
50 * Inspired by a version 6 program by Len Levin, 1978.
51 * Several pieces of code lifted from Bill Joy's 4BSD ps.
52 * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
53 * Lawrence Berkeley Laboratory.
54 *
55 * Portions of this software were developed by the Computer Systems
56 * Engineering group at Lawrence Berkeley Laboratory under DARPA
57 * contract BG 91-66 and contributed to Berkeley.
58 */
59
60#include <sys/param.h>
61#include <sys/time.h>
62#include <sys/stat.h>
47
48/*
49 * Originally written by Eric Cooper in Fall 1981.
50 * Inspired by a version 6 program by Len Levin, 1978.
51 * Several pieces of code lifted from Bill Joy's 4BSD ps.
52 * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
53 * Lawrence Berkeley Laboratory.
54 *
55 * Portions of this software were developed by the Computer Systems
56 * Engineering group at Lawrence Berkeley Laboratory under DARPA
57 * contract BG 91-66 and contributed to Berkeley.
58 */
59
60#include <sys/param.h>
61#include <sys/time.h>
62#include <sys/stat.h>
63#include <sys/proc.h>
64#include <sys/user.h>
65#include <sys/sysctl.h>
63#include <sys/linker_set.h>
66
64
67#include <arpa/inet.h>
68#include <machine/elf.h>
69#include <machine/vmparam.h>
70
71#include <a.out.h>
72#include <err.h>
73#include <fcntl.h>
65#include <err.h>
66#include <fcntl.h>
74#include <kvm.h>
75#include <limits.h>
76#include <signal.h>
77#include <stdio.h>
78#include <stdlib.h>
79#include <string.h>
80#include <unistd.h>
81
82#include "extern.h"
83
67#include <signal.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71#include <unistd.h>
72
73#include "extern.h"
74
84static void core(int, int, struct kinfo_proc *);
85static void datadump(int, int, struct kinfo_proc *, u_long, int);
86static void killed(int);
87static void restart_target(void);
88static void usage(void) __dead2;
75static void killed(int);
76static void restart_target(void);
77static void usage(void) __dead2;
89static void userdump(int, struct kinfo_proc *, u_long, int);
90
78
91kvm_t *kd;
92
93static int data_offset;
94static pid_t pid;
95
79static pid_t pid;
80
81SET_DECLARE(dumpset, struct dumpers);
82
96int
83int
97main(argc, argv)
98 int argc;
99 char *argv[];
84main(int argc, char *argv[])
100{
85{
101 struct kinfo_proc *ki = NULL;
102 struct exec exec;
103 int ch, cnt, efd, fd, sflag;
86 int ch, cnt, efd, fd, sflag;
104 uid_t uid;
105 char *binfile, *corefile;
87 char *binfile, *corefile;
106 char errbuf[_POSIX2_LINE_MAX], fname[MAXPATHLEN];
107 int is_aout;
88 char fname[MAXPATHLEN];
89 struct dumpers **d, *dumper;
108
109 sflag = 0;
110 corefile = NULL;
111 while ((ch = getopt(argc, argv, "c:s")) != -1) {
112 switch (ch) {
113 case 'c':
114 corefile = optarg;
115 break;
116 case 's':
117 sflag = 1;
118 break;
119 default:
120 usage();
121 break;
122 }
123 }
124 argv += optind;
125 argc -= optind;
90
91 sflag = 0;
92 corefile = NULL;
93 while ((ch = getopt(argc, argv, "c:s")) != -1) {
94 switch (ch) {
95 case 'c':
96 corefile = optarg;
97 break;
98 case 's':
99 sflag = 1;
100 break;
101 default:
102 usage();
103 break;
104 }
105 }
106 argv += optind;
107 argc -= optind;
126
127 /* XXX we should check that the pid argument is really a number */
128 switch (argc) {
129 case 1:
130 pid = atoi(argv[0]);
131 asprintf(&binfile, "/proc/%d/file", pid);
132 if (binfile == NULL)
133 errx(1, "allocation failure");
134 break;
135 case 2:
136 pid = atoi(argv[1]);
137 binfile = argv[0];
138 break;
139 default:
140 usage();
141 }
108 /* XXX we should check that the pid argument is really a number */
109 switch (argc) {
110 case 1:
111 pid = atoi(argv[0]);
112 asprintf(&binfile, "/proc/%d/file", pid);
113 if (binfile == NULL)
114 errx(1, "allocation failure");
115 break;
116 case 2:
117 pid = atoi(argv[1]);
118 binfile = argv[0];
119 break;
120 default:
121 usage();
122 }
142
143 efd = open(binfile, O_RDONLY, 0);
144 if (efd < 0)
145 err(1, "%s", binfile);
123 efd = open(binfile, O_RDONLY, 0);
124 if (efd < 0)
125 err(1, "%s", binfile);
146
147 cnt = read(efd, &exec, sizeof(exec));
148 if (cnt != sizeof(exec))
149 errx(1, "%s exec header: %s",
150 binfile, cnt > 0 ? strerror(EIO) : strerror(errno));
151 if (!N_BADMAG(exec)) {
152 is_aout = 1;
153 /*
154 * This legacy a.out support uses the kvm interface instead
155 * of procfs.
156 */
157 kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
158 if (kd == NULL)
159 errx(1, "%s", errbuf);
160
161 uid = getuid();
162
163 ki = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt);
164 if (ki == NULL || cnt != 1)
165 errx(1, "%d: not found", pid);
166
167 if (ki->ki_ruid != uid && uid != 0)
168 errx(1, "%d: not owner", pid);
169
170 if (ki->ki_stat == SZOMB)
171 errx(1, "%d: zombie", pid);
172
173 if (ki->ki_flag & P_WEXIT)
174 errx(1, "%d: process exiting", pid);
175 if (ki->ki_flag & P_SYSTEM) /* Swapper or pagedaemon. */
176 errx(1, "%d: system process", pid);
177 if (exec.a_text != ptoa(ki->ki_tsize))
178 errx(1, "The executable %s does not belong to"
179 " process %d!\n"
180 "Text segment size (in bytes): executable %ld,"
181 " process %d", binfile, pid, exec.a_text,
182 ptoa(ki->ki_tsize));
183 data_offset = N_DATOFF(exec);
184 } else if (IS_ELF(*(Elf_Ehdr *)&exec)) {
185 is_aout = 0;
186 close(efd);
187 } else
126 dumper = NULL;
127 SET_FOREACH(d, dumpset) {
128 lseek(efd, 0, SEEK_SET);
129 if (((*d)->ident)(efd, pid, binfile)) {
130 dumper = (*d);
131 lseek(efd, 0, SEEK_SET);
132 break;
133 }
134 }
135 if (dumper == NULL)
188 errx(1, "Invalid executable file");
136 errx(1, "Invalid executable file");
189
190 if (corefile == NULL) {
191 (void)snprintf(fname, sizeof(fname), "core.%d", pid);
192 corefile = fname;
193 }
194 fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
195 if (fd < 0)
196 err(1, "%s", corefile);
137 if (corefile == NULL) {
138 (void)snprintf(fname, sizeof(fname), "core.%d", pid);
139 corefile = fname;
140 }
141 fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
142 if (fd < 0)
143 err(1, "%s", corefile);
197
198 if (sflag) {
199 signal(SIGHUP, killed);
200 signal(SIGINT, killed);
201 signal(SIGTERM, killed);
202 if (kill(pid, SIGSTOP) == -1)
203 err(1, "%d: stop signal", pid);
204 atexit(restart_target);
205 }
144 if (sflag) {
145 signal(SIGHUP, killed);
146 signal(SIGINT, killed);
147 signal(SIGTERM, killed);
148 if (kill(pid, SIGSTOP) == -1)
149 err(1, "%d: stop signal", pid);
150 atexit(restart_target);
151 }
206
207 if (is_aout)
208 core(efd, fd, ki);
209 else
210 elf_coredump(fd, pid);
211
152 dumper->dump(efd, fd, pid);
212 (void)close(fd);
153 (void)close(fd);
154 (void)close(efd);
213 exit(0);
214}
215
155 exit(0);
156}
157
216/*
217 * core --
218 * Build the core file.
219 */
220void
221core(efd, fd, ki)
222 int efd;
223 int fd;
224 struct kinfo_proc *ki;
225{
226 union {
227 struct user user;
228 struct {
229 char uabytes[ctob(UAREA_PAGES)];
230 char ksbytes[ctob(KSTACK_PAGES)];
231 } bytes;
232 } uarea;
233 int tsize = ki->ki_tsize;
234 int dsize = ki->ki_dsize;
235 int ssize = ki->ki_ssize;
236 int cnt;
237
238 /* Read in user struct */
239 cnt = kvm_read(kd, (u_long)ki->ki_addr, uarea.bytes.uabytes,
240 ctob(UAREA_PAGES));
241 if (cnt != ctob(UAREA_PAGES))
242 errx(1, "read upages structure: %s",
243 cnt > 0 ? strerror(EIO) : strerror(errno));
244
245 cnt = kvm_read(kd, (u_long)ki->ki_kstack, uarea.bytes.ksbytes,
246 ctob(KSTACK_PAGES));
247 if (cnt != ctob(KSTACK_PAGES))
248 errx(1, "read kstack structure: %s",
249 cnt > 0 ? strerror(EIO) : strerror(errno));
250
251 /*
252 * Fill in the eproc vm parameters, since these are garbage unless
253 * the kernel is dumping core or something.
254 */
255 uarea.user.u_kproc = *ki;
256
257 /* Dump user area */
258 cnt = write(fd, &uarea, sizeof(uarea));
259 if (cnt != sizeof(uarea))
260 errx(1, "write user structure: %s",
261 cnt > 0 ? strerror(EIO) : strerror(errno));
262
263 /* Dump data segment */
264 datadump(efd, fd, ki, USRTEXT + ctob(tsize), dsize);
265
266 /* Dump stack segment */
267 userdump(fd, ki, USRSTACK - ctob(ssize), ssize);
268
269 /* Dump machine dependent portions of the core. */
270 md_core(kd, fd, ki);
271}
272
273void
274datadump(efd, fd, kp, addr, npage)
275 register int efd;
276 register int fd;
277 struct kinfo_proc *kp;
278 register u_long addr;
279 register int npage;
280{
281 register int cc, delta;
282 char buffer[PAGE_SIZE];
283
284 delta = data_offset - addr;
285 while (--npage >= 0) {
286 cc = kvm_uread(kd, kp, addr, buffer, PAGE_SIZE);
287 if (cc != PAGE_SIZE) {
288 /* Try to read the page from the executable. */
289 if (lseek(efd, (off_t)addr + delta, SEEK_SET) == -1)
290 err(1, "seek executable");
291 cc = read(efd, buffer, sizeof(buffer));
292 if (cc != sizeof(buffer)) {
293 if (cc < 0)
294 err(1, "read executable");
295 else /* Assume untouched bss page. */
296 bzero(buffer, sizeof(buffer));
297 }
298 }
299 cc = write(fd, buffer, PAGE_SIZE);
300 if (cc != PAGE_SIZE)
301 errx(1, "write data segment: %s",
302 cc > 0 ? strerror(EIO) : strerror(errno));
303 addr += PAGE_SIZE;
304 }
305}
306
307static void
158static void
308killed(sig)
309 int sig;
159killed(int sig)
310{
160{
161
311 restart_target();
312 signal(sig, SIG_DFL);
313 kill(getpid(), sig);
314}
315
316static void
162 restart_target();
163 signal(sig, SIG_DFL);
164 kill(getpid(), sig);
165}
166
167static void
317restart_target()
168restart_target(void)
318{
169{
170
319 kill(pid, SIGCONT);
320}
321
322void
171 kill(pid, SIGCONT);
172}
173
174void
323userdump(fd, kp, addr, npage)
324 register int fd;
325 struct kinfo_proc *kp;
326 register u_long addr;
327 register int npage;
175usage(void)
328{
176{
329 register int cc;
330 char buffer[PAGE_SIZE];
331
177
332 while (--npage >= 0) {
333 cc = kvm_uread(kd, kp, addr, buffer, PAGE_SIZE);
334 if (cc != PAGE_SIZE)
335 /* Could be an untouched fill-with-zero page. */
336 bzero(buffer, PAGE_SIZE);
337 cc = write(fd, buffer, PAGE_SIZE);
338 if (cc != PAGE_SIZE)
339 errx(1, "write stack segment: %s",
340 cc > 0 ? strerror(EIO) : strerror(errno));
341 addr += PAGE_SIZE;
342 }
343}
344
345void
346usage()
347{
348 (void)fprintf(stderr, "usage: gcore [-s] [-c core] [executable] pid\n");
349 exit(1);
350}
178 (void)fprintf(stderr, "usage: gcore [-s] [-c core] [executable] pid\n");
179 exit(1);
180}