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