xref: /freebsd/usr.bin/gcore/gcore.c (revision 0b8224d1cc9dc6c9778ba04a75b2c8d47e5d7481)
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 /*
339b50d902SRodney W. Grimes  * Originally written by Eric Cooper in Fall 1981.
349b50d902SRodney W. Grimes  * Inspired by a version 6 program by Len Levin, 1978.
359b50d902SRodney W. Grimes  * Several pieces of code lifted from Bill Joy's 4BSD ps.
369b50d902SRodney W. Grimes  * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
379b50d902SRodney W. Grimes  * Lawrence Berkeley Laboratory.
389b50d902SRodney W. Grimes  *
399b50d902SRodney W. Grimes  * Portions of this software were developed by the Computer Systems
409b50d902SRodney W. Grimes  * Engineering group at Lawrence Berkeley Laboratory under DARPA
419b50d902SRodney W. Grimes  * contract BG 91-66 and contributed to Berkeley.
429b50d902SRodney W. Grimes  */
435bf3fd2bSPhilippe Charnier 
449b50d902SRodney W. Grimes #include <sys/param.h>
45*73e8f06aSKonstantin Belousov #include <sys/ptrace.h>
469b50d902SRodney W. Grimes #include <sys/time.h>
479b50d902SRodney W. Grimes #include <sys/stat.h>
48e0491636SPeter Wemm #include <sys/linker_set.h>
492e7ecbfbSAttilio Rao #include <sys/sysctl.h>
50*73e8f06aSKonstantin Belousov #include <sys/wait.h>
519b50d902SRodney W. Grimes 
52a5bf6586SPhilippe Charnier #include <err.h>
539b50d902SRodney W. Grimes #include <fcntl.h>
54*73e8f06aSKonstantin Belousov #include <stdbool.h>
559b50d902SRodney W. Grimes #include <stdio.h>
569b50d902SRodney W. Grimes #include <stdlib.h>
57821df508SXin LI #include <string.h>
589b50d902SRodney W. Grimes #include <unistd.h>
599b50d902SRodney W. Grimes 
609b50d902SRodney W. Grimes #include "extern.h"
611d73ef97SAttilio Rao int pflags;
629b50d902SRodney W. Grimes 
63f1bb2cd2SWarner Losh static void	killed(int);
64f1bb2cd2SWarner Losh static void	usage(void) __dead2;
659b50d902SRodney W. Grimes 
66283c2d5aSJohn Polstra static pid_t pid;
67*73e8f06aSKonstantin Belousov static bool kflag = false;
689b50d902SRodney W. Grimes 
69e0491636SPeter Wemm SET_DECLARE(dumpset, struct dumpers);
70e0491636SPeter Wemm 
71c192228bSKonstantin Belousov static int
open_corefile(char * corefile)72c192228bSKonstantin Belousov open_corefile(char *corefile)
73c192228bSKonstantin Belousov {
74c192228bSKonstantin Belousov 	char fname[MAXPATHLEN];
75*73e8f06aSKonstantin Belousov 	int fd;
76c192228bSKonstantin Belousov 
77c192228bSKonstantin Belousov 	if (corefile == NULL) {
78c192228bSKonstantin Belousov 		(void)snprintf(fname, sizeof(fname), "core.%d", pid);
79c192228bSKonstantin Belousov 		corefile = fname;
80c192228bSKonstantin Belousov 	}
81c192228bSKonstantin Belousov 	fd = open(corefile, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
82c192228bSKonstantin Belousov 	if (fd < 0)
83c192228bSKonstantin Belousov 		err(1, "%s", corefile);
84c192228bSKonstantin Belousov 	return (fd);
85c192228bSKonstantin Belousov }
86c192228bSKonstantin Belousov 
87*73e8f06aSKonstantin Belousov static void
kcoredump(int fd,pid_t pid)88*73e8f06aSKonstantin Belousov kcoredump(int fd, pid_t pid)
89*73e8f06aSKonstantin Belousov {
90*73e8f06aSKonstantin Belousov 	struct ptrace_coredump pc;
91*73e8f06aSKonstantin Belousov 	int error, res, ret, waited;
92*73e8f06aSKonstantin Belousov 
93*73e8f06aSKonstantin Belousov 	error = ptrace(PT_ATTACH, pid, NULL, 0);
94*73e8f06aSKonstantin Belousov 	if (error != 0)
95*73e8f06aSKonstantin Belousov 		err(1, "attach");
96*73e8f06aSKonstantin Belousov 
97*73e8f06aSKonstantin Belousov 	waited = waitpid(pid, &res, 0);
98*73e8f06aSKonstantin Belousov 	if (waited == -1)
99*73e8f06aSKonstantin Belousov 		err(1, "wait for STOP");
100*73e8f06aSKonstantin Belousov 
101*73e8f06aSKonstantin Belousov 	ret = 0;
102*73e8f06aSKonstantin Belousov 	memset(&pc, 0, sizeof(pc));
103*73e8f06aSKonstantin Belousov 	pc.pc_fd = fd;
104*73e8f06aSKonstantin Belousov 	pc.pc_flags = (pflags & PFLAGS_FULL) != 0 ? PC_ALL : 0;
105*73e8f06aSKonstantin Belousov 	error = ptrace(PT_COREDUMP, pid, (void *)&pc, sizeof(pc));
106*73e8f06aSKonstantin Belousov 	if (error == -1) {
107*73e8f06aSKonstantin Belousov 		warn("coredump");
108*73e8f06aSKonstantin Belousov 		ret = 1;
109*73e8f06aSKonstantin Belousov 	}
110*73e8f06aSKonstantin Belousov 
111*73e8f06aSKonstantin Belousov 	waited = waitpid(pid, &res, WNOHANG);
112*73e8f06aSKonstantin Belousov 	if (waited == -1) {
113*73e8f06aSKonstantin Belousov 		warn("wait after coredump");
114*73e8f06aSKonstantin Belousov 		ret = 1;
115*73e8f06aSKonstantin Belousov 	}
116*73e8f06aSKonstantin Belousov 
117*73e8f06aSKonstantin Belousov 	error = ptrace(PT_DETACH, pid, NULL, 0);
118*73e8f06aSKonstantin Belousov 	if (error == -1) {
119*73e8f06aSKonstantin Belousov 		warn("detach failed, check process status");
120*73e8f06aSKonstantin Belousov 		ret = 1;
121*73e8f06aSKonstantin Belousov 	}
122*73e8f06aSKonstantin Belousov 
123*73e8f06aSKonstantin Belousov 	exit(ret);
124*73e8f06aSKonstantin Belousov }
125*73e8f06aSKonstantin Belousov 
1269b50d902SRodney W. Grimes int
main(int argc,char * argv[])127e0491636SPeter Wemm main(int argc, char *argv[])
1289b50d902SRodney W. Grimes {
129adaa8f14SMatt Jacob 	int ch, efd, fd, name[4];
13049ee7af6SDag-Erling Smørgrav 	char *binfile, *corefile;
131c192228bSKonstantin Belousov 	char passpath[MAXPATHLEN];
132e0491636SPeter Wemm 	struct dumpers **d, *dumper;
1332e7ecbfbSAttilio Rao 	size_t len;
1349b50d902SRodney W. Grimes 
1351d73ef97SAttilio Rao 	pflags = 0;
1369b50d902SRodney W. Grimes 	corefile = NULL;
137*73e8f06aSKonstantin Belousov         while ((ch = getopt(argc, argv, "c:fk")) != -1) {
1389b50d902SRodney W. Grimes                 switch (ch) {
1399b50d902SRodney W. Grimes                 case 'c':
1409b50d902SRodney W. Grimes 			corefile = optarg;
1419b50d902SRodney W. Grimes                         break;
1421d73ef97SAttilio Rao 		case 'f':
1431d73ef97SAttilio Rao 			pflags |= PFLAGS_FULL;
1441d73ef97SAttilio Rao 			break;
145*73e8f06aSKonstantin Belousov 		case 'k':
146*73e8f06aSKonstantin Belousov 			kflag = true;
147*73e8f06aSKonstantin Belousov 			break;
1489b50d902SRodney W. Grimes 		default:
1499b50d902SRodney W. Grimes 			usage();
1509b50d902SRodney W. Grimes 			break;
1519b50d902SRodney W. Grimes 		}
1529b50d902SRodney W. Grimes 	}
1539b50d902SRodney W. Grimes 	argv += optind;
1549b50d902SRodney W. Grimes 	argc -= optind;
155*73e8f06aSKonstantin Belousov 
15649ee7af6SDag-Erling Smørgrav 	/* XXX we should check that the pid argument is really a number */
15749ee7af6SDag-Erling Smørgrav 	switch (argc) {
15849ee7af6SDag-Erling Smørgrav 	case 1:
15949ee7af6SDag-Erling Smørgrav 		pid = atoi(argv[0]);
160*73e8f06aSKonstantin Belousov 		break;
161*73e8f06aSKonstantin Belousov 	case 2:
162*73e8f06aSKonstantin Belousov 		binfile = argv[0];
163*73e8f06aSKonstantin Belousov 		pid = atoi(argv[1]);
164*73e8f06aSKonstantin Belousov 		break;
165*73e8f06aSKonstantin Belousov 	default:
166*73e8f06aSKonstantin Belousov 		usage();
167*73e8f06aSKonstantin Belousov 	}
168*73e8f06aSKonstantin Belousov 
169*73e8f06aSKonstantin Belousov 	if (kflag) {
170*73e8f06aSKonstantin Belousov 		fd = open_corefile(corefile);
171*73e8f06aSKonstantin Belousov 		kcoredump(fd, pid);
172*73e8f06aSKonstantin Belousov 	}
173*73e8f06aSKonstantin Belousov 
174*73e8f06aSKonstantin Belousov 	if (argc == 1) {
1752e7ecbfbSAttilio Rao 		name[0] = CTL_KERN;
1762e7ecbfbSAttilio Rao 		name[1] = KERN_PROC;
1772e7ecbfbSAttilio Rao 		name[2] = KERN_PROC_PATHNAME;
1782e7ecbfbSAttilio Rao 		name[3] = pid;
1792e7ecbfbSAttilio Rao 		len = sizeof(passpath);
1802e7ecbfbSAttilio Rao 		if (sysctl(name, 4, passpath, &len, NULL, 0) == -1)
1812e7ecbfbSAttilio Rao 			errx(1, "kern.proc.pathname failure");
1822e7ecbfbSAttilio Rao 		binfile = passpath;
18349ee7af6SDag-Erling Smørgrav 	}
18452e7cc0aSJohn Polstra 	efd = open(binfile, O_RDONLY, 0);
18552e7cc0aSJohn Polstra 	if (efd < 0)
18652e7cc0aSJohn Polstra 		err(1, "%s", binfile);
187e0491636SPeter Wemm 	dumper = NULL;
188e0491636SPeter Wemm 	SET_FOREACH(d, dumpset) {
189e0491636SPeter Wemm 		lseek(efd, 0, SEEK_SET);
190e0491636SPeter Wemm 		if (((*d)->ident)(efd, pid, binfile)) {
191e0491636SPeter Wemm 			dumper = (*d);
192e0491636SPeter Wemm 			lseek(efd, 0, SEEK_SET);
193e0491636SPeter Wemm 			break;
194e0491636SPeter Wemm 		}
195e0491636SPeter Wemm 	}
196e0491636SPeter Wemm 	if (dumper == NULL)
19752e7cc0aSJohn Polstra 		errx(1, "Invalid executable file");
198c192228bSKonstantin Belousov 	fd = open_corefile(corefile);
199adaa8f14SMatt Jacob 
200e0491636SPeter Wemm 	dumper->dump(efd, fd, pid);
2019b50d902SRodney W. Grimes 	(void)close(fd);
202e0491636SPeter Wemm 	(void)close(efd);
2039b50d902SRodney W. Grimes 	exit(0);
2049b50d902SRodney W. Grimes }
2059b50d902SRodney W. Grimes 
2069b50d902SRodney W. Grimes void
usage(void)207e0491636SPeter Wemm usage(void)
2089b50d902SRodney W. Grimes {
2099b50d902SRodney W. Grimes 
210*73e8f06aSKonstantin Belousov 	(void)fprintf(stderr,
211*73e8f06aSKonstantin Belousov 	    "usage: gcore [-kf] [-c core] [executable] pid\n");
2129b50d902SRodney W. Grimes 	exit(1);
2139b50d902SRodney W. Grimes }
214