1 /*- 2 * Copyright (c) 1992, 1993, 2019 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#) Copyright (c) 1992, 1993 The Regents of the University of California. All rights reserved. 30 * @(#)gcore.c 8.2 (Berkeley) 9/23/93 31 * $FreeBSD: src/usr.bin/gcore/gcore.c,v 1.15.2.2 2001/08/17 20:56:22 mikeh Exp $ 32 */ 33 34 /* 35 * Originally written by Eric Cooper in Fall 1981. 36 * Inspired by a version 6 program by Len Levin, 1978. 37 * Several pieces of code lifted from Bill Joy's 4BSD ps. 38 * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne, 39 * Lawrence Berkeley Laboratory. 40 * 41 * Portions of this software were developed by the Computer Systems 42 * Engineering group at Lawrence Berkeley Laboratory under DARPA 43 * contract BG 91-66 and contributed to Berkeley. 44 */ 45 #include <sys/user.h> 46 #include <sys/param.h> 47 #include <sys/time.h> 48 #include <sys/stat.h> 49 #include <sys/sysctl.h> 50 #include <machine/elf.h> 51 52 #include <machine/vmparam.h> 53 54 #include <a.out.h> 55 #include <err.h> 56 #include <fcntl.h> 57 #include <kvm.h> 58 #include <limits.h> 59 #include <signal.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #include <unistd.h> 64 65 #include "extern.h" 66 67 static void killed(int); 68 static void restart_target(void); 69 static void usage(void) __dead2; 70 71 kvm_t *kd; 72 73 static pid_t pid; 74 ssize_t gcore_seg_limit = -1; 75 int gcore_verbose; 76 77 int 78 main(int argc, char **argv) 79 { 80 struct exec exec; 81 int ch, cnt, efd, fd, sflag; 82 char *binfile, *corefile; 83 char *eptr; 84 char fname[MAXPATHLEN + 1]; 85 86 sflag = 0; 87 corefile = NULL; 88 while ((ch = getopt(argc, argv, "c:l:sv")) != -1) { 89 switch (ch) { 90 case 'c': 91 corefile = optarg; 92 break; 93 case 'l': 94 gcore_seg_limit = strtol(optarg, &eptr, 0); 95 switch(*eptr) { 96 case 0: 97 break; 98 case 't': 99 case 'T': 100 gcore_seg_limit *= 1024; 101 /* fall through */ 102 case 'g': 103 case 'G': 104 gcore_seg_limit *= 1024; 105 /* fall through */ 106 case 'm': 107 case 'M': 108 gcore_seg_limit *= 1024; 109 /* fall through */ 110 case 'k': 111 case 'K': 112 gcore_seg_limit *= 1024; 113 break; 114 default: 115 usage(); 116 break; 117 } 118 break; 119 case 's': 120 sflag = 1; 121 break; 122 case 'v': 123 gcore_verbose = 1; 124 break; 125 default: 126 usage(); 127 break; 128 } 129 } 130 argv += optind; 131 argc -= optind; 132 133 /* XXX we should check that the pid argument is really a number */ 134 switch (argc) { 135 case 1: 136 pid = atoi(argv[0]); 137 asprintf(&binfile, "/proc/%d/file", pid); 138 if (binfile == NULL) 139 errx(1, "allocation failure"); 140 break; 141 case 2: 142 pid = atoi(argv[1]); 143 binfile = argv[0]; 144 break; 145 default: 146 usage(); 147 } 148 149 efd = open(binfile, O_RDONLY, 0); 150 if (efd < 0) 151 err(1, "%s", binfile); 152 153 cnt = read(efd, &exec, sizeof(exec)); 154 if (cnt != sizeof(exec)) 155 errx(1, "%s exec header: %s", 156 binfile, cnt > 0 ? strerror(EIO) : strerror(errno)); 157 if (IS_ELF(*(Elf_Ehdr *)&exec)) { 158 close(efd); 159 } else 160 errx(1, "Invalid executable file"); 161 162 if (corefile == NULL) { 163 snprintf(fname, sizeof(fname), "core.%d", pid); 164 corefile = fname; 165 } 166 fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE); 167 if (fd < 0) 168 err(1, "%s", corefile); 169 170 if (sflag) { 171 signal(SIGHUP, killed); 172 signal(SIGINT, killed); 173 signal(SIGTERM, killed); 174 if (kill(pid, SIGSTOP) == -1) 175 err(1, "%d: stop signal", pid); 176 atexit(restart_target); 177 } 178 179 elf_coredump(fd, pid); 180 181 close(fd); 182 exit(0); 183 } 184 185 static void 186 killed(int sig) 187 { 188 restart_target(); 189 signal(sig, SIG_DFL); 190 kill(getpid(), sig); 191 } 192 193 static void 194 restart_target(void) 195 { 196 kill(pid, SIGCONT); 197 } 198 199 void 200 usage(void) 201 { 202 fprintf(stderr, 203 "usage: gcore [-sv] [-c core] [-l seglimit] [executable] pid\n"); 204 exit(1); 205 } 206