1 /*- 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 */ 11 12 /* 13 * gcore - get core images of running processes 14 */ 15 #include <stdio.h> 16 #include <limits.h> 17 #include <kvm.h> 18 #include <a.out.h> 19 #include <sys/param.h> 20 #include <sys/time.h> 21 #include <sys/file.h> 22 #include <sys/proc.h> 23 #include <sys/user.h> 24 #include <sys/kinfo.h> 25 #include <sys/kinfo_proc.h> 26 #include <machine/vmparam.h> 27 28 kvm_t *kd; 29 30 extern int getopt(); 31 extern int optind, opterr; 32 extern char *optarg; 33 34 static int data_offset; 35 36 main(argc, argv) 37 int argc; 38 char **argv; 39 { 40 register struct proc *p; 41 off_t procbase, procp; 42 int pid, uid, fd, cnt, i, op, efd; 43 struct kinfo_proc *ki; 44 char *corefile = 0; 45 int err; 46 int sflag = 0; 47 struct exec exec; 48 char errbuf[_POSIX2_LINE_MAX]; 49 char fname[64]; 50 51 setprog(argv[0]); 52 53 opterr = 0; 54 while ((op = getopt(argc, argv, "c:s")) != EOF) { 55 switch (op) { 56 57 case 'c': 58 corefile = optarg; 59 break; 60 61 case 's': 62 ++sflag; 63 break; 64 65 default: 66 usage(); 67 break; 68 } 69 } 70 argv += optind; 71 argc -= optind; 72 if (argc != 2) 73 usage(); 74 75 kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf); 76 if (kd == 0) 77 error("%s", errbuf); 78 79 uid = getuid(); 80 pid = atoi(argv[1]); 81 82 ki = kvm_getprocs(kd, KINFO_PROC_PID, pid, &cnt); 83 if (ki == 0 || cnt != 1) 84 error("%d: not found", pid); 85 86 p = &ki->kp_proc; 87 if (ki->kp_eproc.e_pcred.p_ruid != uid && uid != 0) 88 error("%d: not owner", pid); 89 90 if (p->p_stat == SZOMB) 91 error("%d: zombie", pid); 92 93 if (p->p_flag & SWEXIT) 94 warning("process exiting"); 95 if (p->p_flag & SSYS) 96 /* i.e. swapper or pagedaemon */ 97 error("%d: system process"); 98 99 if (corefile == 0) { 100 sprintf(fname, "core.%d", pid); 101 corefile = fname; 102 } 103 fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, 0666); 104 if (fd < 0) { 105 perror(corefile); 106 exit(1); 107 } 108 efd = open(argv[0], O_RDONLY); 109 if (efd < 0) { 110 perror(argv[0]); 111 exit(1); 112 } 113 if (read(efd, &exec, sizeof(exec)) != sizeof(exec)) 114 error("cannot read exec header of %s", argv[0]); 115 116 data_offset = N_DATOFF(exec); 117 118 if (sflag && kill(pid, SIGSTOP) < 0) 119 warning("%d: could not deliver stop signal", pid); 120 121 err = core(efd, fd, p); 122 if (err == 0) 123 err = md_core(kd, fd, p); 124 125 if (sflag && kill(pid, SIGCONT) < 0) 126 warning("%d: could not deliver continue signal", pid); 127 close(fd); 128 129 exit(0); 130 } 131 132 int 133 userdump(fd, p, addr, npage) 134 register int fd; 135 struct proc *p; 136 register u_long addr; 137 register int npage; 138 { 139 register int cc; 140 char buffer[NBPG]; 141 142 while (--npage >= 0) { 143 cc = kvm_uread(kd, p, addr, buffer, NBPG); 144 if (cc != NBPG) 145 return (-1); 146 (void)write(fd, buffer, NBPG); 147 addr += NBPG; 148 } 149 return (0); 150 } 151 152 int 153 datadump(efd, fd, p, addr, npage) 154 register int efd; 155 register int fd; 156 struct proc *p; 157 register u_long addr; 158 register int npage; 159 { 160 register int cc, delta; 161 char buffer[NBPG]; 162 163 delta = data_offset - addr; 164 while (--npage >= 0) { 165 cc = kvm_uread(kd, p, addr, buffer, NBPG); 166 if (cc != NBPG) { 167 /* 168 * Try to read page from executable. 169 */ 170 if (lseek(efd, addr + delta, SEEK_SET) == -1) 171 return (-1); 172 if (read(efd, buffer, sizeof(buffer)) < 0) 173 return (-1); 174 } 175 (void)write(fd, buffer, NBPG); 176 addr += NBPG; 177 } 178 return (0); 179 } 180 181 /* 182 * Build the core file. 183 */ 184 int 185 core(efd, fd, ki) 186 int efd; 187 int fd; 188 struct kinfo_proc *ki; 189 { 190 struct user user; 191 192 int tsize = ki->kp_eproc.e_vm.vm_tsize; 193 int dsize = ki->kp_eproc.e_vm.vm_dsize; 194 int ssize = ki->kp_eproc.e_vm.vm_ssize; 195 struct proc *p = &ki->kp_proc; 196 197 /* Read in user struct */ 198 if (kvm_read(kd, (u_long)p->p_addr, (void *)&user, sizeof(user)) 199 != sizeof(user)) 200 error("could not read user structure"); 201 202 /* 203 * Fill in the eproc vm parameters, since these are garbage unless 204 * the kernel is dumping core or something. 205 */ 206 user.u_kproc.kp_eproc.e_vm.vm_tsize = tsize; 207 user.u_kproc.kp_eproc.e_vm.vm_dsize = dsize; 208 user.u_kproc.kp_eproc.e_vm.vm_ssize = ssize; 209 /* write out the user struct and leave the right amount of space */ 210 (void)write(fd, (char *)&user, sizeof(user)); 211 (void)lseek(fd, UPAGES * NBPG, SEEK_SET); 212 213 /* Dump data segment */ 214 if (datadump(efd, fd, p, USRTEXT + ctob(tsize), dsize) < 0) 215 error("could not dump data segment"); 216 217 /* Dump stack segment */ 218 if (userdump(fd, p, USRSTACK - ctob(ssize), ssize) < 0) 219 error("could not dump stack segment"); 220 221 return (0); 222 } 223