1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #ifndef lint
33 static const char copyright[] =
34 "@(#) Copyright (c) 1992, 1993\n\
35 The Regents of the University of California. All rights reserved.\n";
36 #endif /* not lint */
37
38 #if 0
39 #ifndef lint
40 static char sccsid[] = "@(#)gcore.c 8.2 (Berkeley) 9/23/93";
41 #endif /* not lint */
42 #endif
43 #include <sys/cdefs.h>
44 /*
45 * Originally written by Eric Cooper in Fall 1981.
46 * Inspired by a version 6 program by Len Levin, 1978.
47 * Several pieces of code lifted from Bill Joy's 4BSD ps.
48 * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
49 * Lawrence Berkeley Laboratory.
50 *
51 * Portions of this software were developed by the Computer Systems
52 * Engineering group at Lawrence Berkeley Laboratory under DARPA
53 * contract BG 91-66 and contributed to Berkeley.
54 */
55
56 #include <sys/param.h>
57 #include <sys/ptrace.h>
58 #include <sys/time.h>
59 #include <sys/stat.h>
60 #include <sys/linker_set.h>
61 #include <sys/sysctl.h>
62 #include <sys/wait.h>
63
64 #include <err.h>
65 #include <fcntl.h>
66 #include <stdbool.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71
72 #include "extern.h"
73 int pflags;
74
75 static void killed(int);
76 static void usage(void) __dead2;
77
78 static pid_t pid;
79 static bool kflag = false;
80
81 SET_DECLARE(dumpset, struct dumpers);
82
83 static int
open_corefile(char * corefile)84 open_corefile(char *corefile)
85 {
86 char fname[MAXPATHLEN];
87 int fd;
88
89 if (corefile == NULL) {
90 (void)snprintf(fname, sizeof(fname), "core.%d", pid);
91 corefile = fname;
92 }
93 fd = open(corefile, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
94 if (fd < 0)
95 err(1, "%s", corefile);
96 return (fd);
97 }
98
99 static void
kcoredump(int fd,pid_t pid)100 kcoredump(int fd, pid_t pid)
101 {
102 struct ptrace_coredump pc;
103 int error, res, ret, waited;
104
105 error = ptrace(PT_ATTACH, pid, NULL, 0);
106 if (error != 0)
107 err(1, "attach");
108
109 waited = waitpid(pid, &res, 0);
110 if (waited == -1)
111 err(1, "wait for STOP");
112
113 ret = 0;
114 memset(&pc, 0, sizeof(pc));
115 pc.pc_fd = fd;
116 pc.pc_flags = (pflags & PFLAGS_FULL) != 0 ? PC_ALL : 0;
117 error = ptrace(PT_COREDUMP, pid, (void *)&pc, sizeof(pc));
118 if (error == -1) {
119 warn("coredump");
120 ret = 1;
121 }
122
123 waited = waitpid(pid, &res, WNOHANG);
124 if (waited == -1) {
125 warn("wait after coredump");
126 ret = 1;
127 }
128
129 error = ptrace(PT_DETACH, pid, NULL, 0);
130 if (error == -1) {
131 warn("detach failed, check process status");
132 ret = 1;
133 }
134
135 exit(ret);
136 }
137
138 int
main(int argc,char * argv[])139 main(int argc, char *argv[])
140 {
141 int ch, efd, fd, name[4];
142 char *binfile, *corefile;
143 char passpath[MAXPATHLEN];
144 struct dumpers **d, *dumper;
145 size_t len;
146
147 pflags = 0;
148 corefile = NULL;
149 while ((ch = getopt(argc, argv, "c:fk")) != -1) {
150 switch (ch) {
151 case 'c':
152 corefile = optarg;
153 break;
154 case 'f':
155 pflags |= PFLAGS_FULL;
156 break;
157 case 'k':
158 kflag = true;
159 break;
160 default:
161 usage();
162 break;
163 }
164 }
165 argv += optind;
166 argc -= optind;
167
168 /* XXX we should check that the pid argument is really a number */
169 switch (argc) {
170 case 1:
171 pid = atoi(argv[0]);
172 break;
173 case 2:
174 binfile = argv[0];
175 pid = atoi(argv[1]);
176 break;
177 default:
178 usage();
179 }
180
181 if (kflag) {
182 fd = open_corefile(corefile);
183 kcoredump(fd, pid);
184 }
185
186 if (argc == 1) {
187 name[0] = CTL_KERN;
188 name[1] = KERN_PROC;
189 name[2] = KERN_PROC_PATHNAME;
190 name[3] = pid;
191 len = sizeof(passpath);
192 if (sysctl(name, 4, passpath, &len, NULL, 0) == -1)
193 errx(1, "kern.proc.pathname failure");
194 binfile = passpath;
195 }
196 efd = open(binfile, O_RDONLY, 0);
197 if (efd < 0)
198 err(1, "%s", binfile);
199 dumper = NULL;
200 SET_FOREACH(d, dumpset) {
201 lseek(efd, 0, SEEK_SET);
202 if (((*d)->ident)(efd, pid, binfile)) {
203 dumper = (*d);
204 lseek(efd, 0, SEEK_SET);
205 break;
206 }
207 }
208 if (dumper == NULL)
209 errx(1, "Invalid executable file");
210 fd = open_corefile(corefile);
211
212 dumper->dump(efd, fd, pid);
213 (void)close(fd);
214 (void)close(efd);
215 exit(0);
216 }
217
218 void
usage(void)219 usage(void)
220 {
221
222 (void)fprintf(stderr,
223 "usage: gcore [-kf] [-c core] [executable] pid\n");
224 exit(1);
225 }
226