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