xref: /freebsd/usr.bin/gcore/gcore.c (revision 73e8f06ac523ee4b530e17d50cc580dc366f7ad8)
19b50d902SRodney W. Grimes /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
49b50d902SRodney W. Grimes  * Copyright (c) 1992, 1993
59b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
69b50d902SRodney W. Grimes  *
79b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
89b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
99b50d902SRodney W. Grimes  * are met:
109b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
119b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
129b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
139b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
149b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
169b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
179b50d902SRodney W. Grimes  *    without specific prior written permission.
189b50d902SRodney W. Grimes  *
199b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299b50d902SRodney W. Grimes  * SUCH DAMAGE.
309b50d902SRodney W. Grimes  */
319b50d902SRodney W. Grimes 
329b50d902SRodney W. Grimes #ifndef lint
33a5bf6586SPhilippe Charnier static const char copyright[] =
349b50d902SRodney W. Grimes "@(#) Copyright (c) 1992, 1993\n\
359b50d902SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
369b50d902SRodney W. Grimes #endif /* not lint */
379b50d902SRodney W. Grimes 
38a5bf6586SPhilippe Charnier #if 0
3964567a41SDavid E. O'Brien #ifndef lint
409b50d902SRodney W. Grimes static char sccsid[] = "@(#)gcore.c	8.2 (Berkeley) 9/23/93";
4164567a41SDavid E. O'Brien #endif /* not lint */
42a5bf6586SPhilippe Charnier #endif
435bf3fd2bSPhilippe Charnier #include <sys/cdefs.h>
445bf3fd2bSPhilippe Charnier __FBSDID("$FreeBSD$");
455bf3fd2bSPhilippe Charnier 
469b50d902SRodney W. Grimes /*
479b50d902SRodney W. Grimes  * Originally written by Eric Cooper in Fall 1981.
489b50d902SRodney W. Grimes  * Inspired by a version 6 program by Len Levin, 1978.
499b50d902SRodney W. Grimes  * Several pieces of code lifted from Bill Joy's 4BSD ps.
509b50d902SRodney W. Grimes  * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
519b50d902SRodney W. Grimes  * Lawrence Berkeley Laboratory.
529b50d902SRodney W. Grimes  *
539b50d902SRodney W. Grimes  * Portions of this software were developed by the Computer Systems
549b50d902SRodney W. Grimes  * Engineering group at Lawrence Berkeley Laboratory under DARPA
559b50d902SRodney W. Grimes  * contract BG 91-66 and contributed to Berkeley.
569b50d902SRodney W. Grimes  */
575bf3fd2bSPhilippe Charnier 
589b50d902SRodney W. Grimes #include <sys/param.h>
59*73e8f06aSKonstantin Belousov #include <sys/ptrace.h>
609b50d902SRodney W. Grimes #include <sys/time.h>
619b50d902SRodney W. Grimes #include <sys/stat.h>
62e0491636SPeter Wemm #include <sys/linker_set.h>
632e7ecbfbSAttilio Rao #include <sys/sysctl.h>
64*73e8f06aSKonstantin Belousov #include <sys/wait.h>
659b50d902SRodney W. Grimes 
66a5bf6586SPhilippe Charnier #include <err.h>
679b50d902SRodney W. Grimes #include <fcntl.h>
68*73e8f06aSKonstantin Belousov #include <stdbool.h>
699b50d902SRodney W. Grimes #include <stdio.h>
709b50d902SRodney W. Grimes #include <stdlib.h>
71821df508SXin LI #include <string.h>
729b50d902SRodney W. Grimes #include <unistd.h>
739b50d902SRodney W. Grimes 
749b50d902SRodney W. Grimes #include "extern.h"
751d73ef97SAttilio Rao int pflags;
769b50d902SRodney W. Grimes 
77f1bb2cd2SWarner Losh static void	killed(int);
78f1bb2cd2SWarner Losh static void	usage(void) __dead2;
799b50d902SRodney W. Grimes 
80283c2d5aSJohn Polstra static pid_t pid;
81*73e8f06aSKonstantin Belousov static bool kflag = false;
829b50d902SRodney W. Grimes 
83e0491636SPeter Wemm SET_DECLARE(dumpset, struct dumpers);
84e0491636SPeter Wemm 
85c192228bSKonstantin Belousov static int
86c192228bSKonstantin Belousov open_corefile(char *corefile)
87c192228bSKonstantin Belousov {
88c192228bSKonstantin Belousov 	char fname[MAXPATHLEN];
89*73e8f06aSKonstantin Belousov 	int fd;
90c192228bSKonstantin Belousov 
91c192228bSKonstantin Belousov 	if (corefile == NULL) {
92c192228bSKonstantin Belousov 		(void)snprintf(fname, sizeof(fname), "core.%d", pid);
93c192228bSKonstantin Belousov 		corefile = fname;
94c192228bSKonstantin Belousov 	}
95c192228bSKonstantin Belousov 	fd = open(corefile, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
96c192228bSKonstantin Belousov 	if (fd < 0)
97c192228bSKonstantin Belousov 		err(1, "%s", corefile);
98c192228bSKonstantin Belousov 	return (fd);
99c192228bSKonstantin Belousov }
100c192228bSKonstantin Belousov 
101*73e8f06aSKonstantin Belousov static void
102*73e8f06aSKonstantin Belousov kcoredump(int fd, pid_t pid)
103*73e8f06aSKonstantin Belousov {
104*73e8f06aSKonstantin Belousov 	struct ptrace_coredump pc;
105*73e8f06aSKonstantin Belousov 	int error, res, ret, waited;
106*73e8f06aSKonstantin Belousov 
107*73e8f06aSKonstantin Belousov 	error = ptrace(PT_ATTACH, pid, NULL, 0);
108*73e8f06aSKonstantin Belousov 	if (error != 0)
109*73e8f06aSKonstantin Belousov 		err(1, "attach");
110*73e8f06aSKonstantin Belousov 
111*73e8f06aSKonstantin Belousov 	waited = waitpid(pid, &res, 0);
112*73e8f06aSKonstantin Belousov 	if (waited == -1)
113*73e8f06aSKonstantin Belousov 		err(1, "wait for STOP");
114*73e8f06aSKonstantin Belousov 
115*73e8f06aSKonstantin Belousov 	ret = 0;
116*73e8f06aSKonstantin Belousov 	memset(&pc, 0, sizeof(pc));
117*73e8f06aSKonstantin Belousov 	pc.pc_fd = fd;
118*73e8f06aSKonstantin Belousov 	pc.pc_flags = (pflags & PFLAGS_FULL) != 0 ? PC_ALL : 0;
119*73e8f06aSKonstantin Belousov 	error = ptrace(PT_COREDUMP, pid, (void *)&pc, sizeof(pc));
120*73e8f06aSKonstantin Belousov 	if (error == -1) {
121*73e8f06aSKonstantin Belousov 		warn("coredump");
122*73e8f06aSKonstantin Belousov 		ret = 1;
123*73e8f06aSKonstantin Belousov 	}
124*73e8f06aSKonstantin Belousov 
125*73e8f06aSKonstantin Belousov 	waited = waitpid(pid, &res, WNOHANG);
126*73e8f06aSKonstantin Belousov 	if (waited == -1) {
127*73e8f06aSKonstantin Belousov 		warn("wait after coredump");
128*73e8f06aSKonstantin Belousov 		ret = 1;
129*73e8f06aSKonstantin Belousov 	}
130*73e8f06aSKonstantin Belousov 
131*73e8f06aSKonstantin Belousov 	error = ptrace(PT_DETACH, pid, NULL, 0);
132*73e8f06aSKonstantin Belousov 	if (error == -1) {
133*73e8f06aSKonstantin Belousov 		warn("detach failed, check process status");
134*73e8f06aSKonstantin Belousov 		ret = 1;
135*73e8f06aSKonstantin Belousov 	}
136*73e8f06aSKonstantin Belousov 
137*73e8f06aSKonstantin Belousov 	exit(ret);
138*73e8f06aSKonstantin Belousov }
139*73e8f06aSKonstantin Belousov 
1409b50d902SRodney W. Grimes int
141e0491636SPeter Wemm main(int argc, char *argv[])
1429b50d902SRodney W. Grimes {
143adaa8f14SMatt Jacob 	int ch, efd, fd, name[4];
14449ee7af6SDag-Erling Smørgrav 	char *binfile, *corefile;
145c192228bSKonstantin Belousov 	char passpath[MAXPATHLEN];
146e0491636SPeter Wemm 	struct dumpers **d, *dumper;
1472e7ecbfbSAttilio Rao 	size_t len;
1489b50d902SRodney W. Grimes 
1491d73ef97SAttilio Rao 	pflags = 0;
1509b50d902SRodney W. Grimes 	corefile = NULL;
151*73e8f06aSKonstantin Belousov         while ((ch = getopt(argc, argv, "c:fk")) != -1) {
1529b50d902SRodney W. Grimes                 switch (ch) {
1539b50d902SRodney W. Grimes                 case 'c':
1549b50d902SRodney W. Grimes 			corefile = optarg;
1559b50d902SRodney W. Grimes                         break;
1561d73ef97SAttilio Rao 		case 'f':
1571d73ef97SAttilio Rao 			pflags |= PFLAGS_FULL;
1581d73ef97SAttilio Rao 			break;
159*73e8f06aSKonstantin Belousov 		case 'k':
160*73e8f06aSKonstantin Belousov 			kflag = true;
161*73e8f06aSKonstantin Belousov 			break;
1629b50d902SRodney W. Grimes 		default:
1639b50d902SRodney W. Grimes 			usage();
1649b50d902SRodney W. Grimes 			break;
1659b50d902SRodney W. Grimes 		}
1669b50d902SRodney W. Grimes 	}
1679b50d902SRodney W. Grimes 	argv += optind;
1689b50d902SRodney W. Grimes 	argc -= optind;
169*73e8f06aSKonstantin Belousov 
17049ee7af6SDag-Erling Smørgrav 	/* XXX we should check that the pid argument is really a number */
17149ee7af6SDag-Erling Smørgrav 	switch (argc) {
17249ee7af6SDag-Erling Smørgrav 	case 1:
17349ee7af6SDag-Erling Smørgrav 		pid = atoi(argv[0]);
174*73e8f06aSKonstantin Belousov 		break;
175*73e8f06aSKonstantin Belousov 	case 2:
176*73e8f06aSKonstantin Belousov 		binfile = argv[0];
177*73e8f06aSKonstantin Belousov 		pid = atoi(argv[1]);
178*73e8f06aSKonstantin Belousov 		break;
179*73e8f06aSKonstantin Belousov 	default:
180*73e8f06aSKonstantin Belousov 		usage();
181*73e8f06aSKonstantin Belousov 	}
182*73e8f06aSKonstantin Belousov 
183*73e8f06aSKonstantin Belousov 	if (kflag) {
184*73e8f06aSKonstantin Belousov 		fd = open_corefile(corefile);
185*73e8f06aSKonstantin Belousov 		kcoredump(fd, pid);
186*73e8f06aSKonstantin Belousov 	}
187*73e8f06aSKonstantin Belousov 
188*73e8f06aSKonstantin Belousov 	if (argc == 1) {
1892e7ecbfbSAttilio Rao 		name[0] = CTL_KERN;
1902e7ecbfbSAttilio Rao 		name[1] = KERN_PROC;
1912e7ecbfbSAttilio Rao 		name[2] = KERN_PROC_PATHNAME;
1922e7ecbfbSAttilio Rao 		name[3] = pid;
1932e7ecbfbSAttilio Rao 		len = sizeof(passpath);
1942e7ecbfbSAttilio Rao 		if (sysctl(name, 4, passpath, &len, NULL, 0) == -1)
1952e7ecbfbSAttilio Rao 			errx(1, "kern.proc.pathname failure");
1962e7ecbfbSAttilio Rao 		binfile = passpath;
19749ee7af6SDag-Erling Smørgrav 	}
19852e7cc0aSJohn Polstra 	efd = open(binfile, O_RDONLY, 0);
19952e7cc0aSJohn Polstra 	if (efd < 0)
20052e7cc0aSJohn Polstra 		err(1, "%s", binfile);
201e0491636SPeter Wemm 	dumper = NULL;
202e0491636SPeter Wemm 	SET_FOREACH(d, dumpset) {
203e0491636SPeter Wemm 		lseek(efd, 0, SEEK_SET);
204e0491636SPeter Wemm 		if (((*d)->ident)(efd, pid, binfile)) {
205e0491636SPeter Wemm 			dumper = (*d);
206e0491636SPeter Wemm 			lseek(efd, 0, SEEK_SET);
207e0491636SPeter Wemm 			break;
208e0491636SPeter Wemm 		}
209e0491636SPeter Wemm 	}
210e0491636SPeter Wemm 	if (dumper == NULL)
21152e7cc0aSJohn Polstra 		errx(1, "Invalid executable file");
212c192228bSKonstantin Belousov 	fd = open_corefile(corefile);
213adaa8f14SMatt Jacob 
214e0491636SPeter Wemm 	dumper->dump(efd, fd, pid);
2159b50d902SRodney W. Grimes 	(void)close(fd);
216e0491636SPeter Wemm 	(void)close(efd);
2179b50d902SRodney W. Grimes 	exit(0);
2189b50d902SRodney W. Grimes }
2199b50d902SRodney W. Grimes 
2209b50d902SRodney W. Grimes void
221e0491636SPeter Wemm usage(void)
2229b50d902SRodney W. Grimes {
2239b50d902SRodney W. Grimes 
224*73e8f06aSKonstantin Belousov 	(void)fprintf(stderr,
225*73e8f06aSKonstantin Belousov 	    "usage: gcore [-kf] [-c core] [executable] pid\n");
2269b50d902SRodney W. Grimes 	exit(1);
2279b50d902SRodney W. Grimes }
228