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 #endif 40 #include <sys/cdefs.h> 41 /* 42 * Originally written by Eric Cooper in Fall 1981. 43 * Inspired by a version 6 program by Len Levin, 1978. 44 * Several pieces of code lifted from Bill Joy's 4BSD ps. 45 * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne, 46 * Lawrence Berkeley Laboratory. 47 * 48 * Portions of this software were developed by the Computer Systems 49 * Engineering group at Lawrence Berkeley Laboratory under DARPA 50 * contract BG 91-66 and contributed to Berkeley. 51 */ 52 53 #include <sys/param.h> 54 #include <sys/ptrace.h> 55 #include <sys/time.h> 56 #include <sys/stat.h> 57 #include <sys/linker_set.h> 58 #include <sys/sysctl.h> 59 #include <sys/wait.h> 60 61 #include <err.h> 62 #include <fcntl.h> 63 #include <stdbool.h> 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 #include <unistd.h> 68 69 #include "extern.h" 70 int pflags; 71 72 static void killed(int); 73 static void usage(void) __dead2; 74 75 static pid_t pid; 76 static bool kflag = false; 77 78 SET_DECLARE(dumpset, struct dumpers); 79 80 static int 81 open_corefile(char *corefile) 82 { 83 char fname[MAXPATHLEN]; 84 int fd; 85 86 if (corefile == NULL) { 87 (void)snprintf(fname, sizeof(fname), "core.%d", pid); 88 corefile = fname; 89 } 90 fd = open(corefile, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE); 91 if (fd < 0) 92 err(1, "%s", corefile); 93 return (fd); 94 } 95 96 static void 97 kcoredump(int fd, pid_t pid) 98 { 99 struct ptrace_coredump pc; 100 int error, res, ret, waited; 101 102 error = ptrace(PT_ATTACH, pid, NULL, 0); 103 if (error != 0) 104 err(1, "attach"); 105 106 waited = waitpid(pid, &res, 0); 107 if (waited == -1) 108 err(1, "wait for STOP"); 109 110 ret = 0; 111 memset(&pc, 0, sizeof(pc)); 112 pc.pc_fd = fd; 113 pc.pc_flags = (pflags & PFLAGS_FULL) != 0 ? PC_ALL : 0; 114 error = ptrace(PT_COREDUMP, pid, (void *)&pc, sizeof(pc)); 115 if (error == -1) { 116 warn("coredump"); 117 ret = 1; 118 } 119 120 waited = waitpid(pid, &res, WNOHANG); 121 if (waited == -1) { 122 warn("wait after coredump"); 123 ret = 1; 124 } 125 126 error = ptrace(PT_DETACH, pid, NULL, 0); 127 if (error == -1) { 128 warn("detach failed, check process status"); 129 ret = 1; 130 } 131 132 exit(ret); 133 } 134 135 int 136 main(int argc, char *argv[]) 137 { 138 int ch, efd, fd, name[4]; 139 char *binfile, *corefile; 140 char passpath[MAXPATHLEN]; 141 struct dumpers **d, *dumper; 142 size_t len; 143 144 pflags = 0; 145 corefile = NULL; 146 while ((ch = getopt(argc, argv, "c:fk")) != -1) { 147 switch (ch) { 148 case 'c': 149 corefile = optarg; 150 break; 151 case 'f': 152 pflags |= PFLAGS_FULL; 153 break; 154 case 'k': 155 kflag = true; 156 break; 157 default: 158 usage(); 159 break; 160 } 161 } 162 argv += optind; 163 argc -= optind; 164 165 /* XXX we should check that the pid argument is really a number */ 166 switch (argc) { 167 case 1: 168 pid = atoi(argv[0]); 169 break; 170 case 2: 171 binfile = argv[0]; 172 pid = atoi(argv[1]); 173 break; 174 default: 175 usage(); 176 } 177 178 if (kflag) { 179 fd = open_corefile(corefile); 180 kcoredump(fd, pid); 181 } 182 183 if (argc == 1) { 184 name[0] = CTL_KERN; 185 name[1] = KERN_PROC; 186 name[2] = KERN_PROC_PATHNAME; 187 name[3] = pid; 188 len = sizeof(passpath); 189 if (sysctl(name, 4, passpath, &len, NULL, 0) == -1) 190 errx(1, "kern.proc.pathname failure"); 191 binfile = passpath; 192 } 193 efd = open(binfile, O_RDONLY, 0); 194 if (efd < 0) 195 err(1, "%s", binfile); 196 dumper = NULL; 197 SET_FOREACH(d, dumpset) { 198 lseek(efd, 0, SEEK_SET); 199 if (((*d)->ident)(efd, pid, binfile)) { 200 dumper = (*d); 201 lseek(efd, 0, SEEK_SET); 202 break; 203 } 204 } 205 if (dumper == NULL) 206 errx(1, "Invalid executable file"); 207 fd = open_corefile(corefile); 208 209 dumper->dump(efd, fd, pid); 210 (void)close(fd); 211 (void)close(efd); 212 exit(0); 213 } 214 215 void 216 usage(void) 217 { 218 219 (void)fprintf(stderr, 220 "usage: gcore [-kf] [-c core] [executable] pid\n"); 221 exit(1); 222 } 223