[BACK]Return to gcore.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / gcore

Annotation of src/usr.bin/gcore/gcore.c, Revision 1.1.1.1

1.1       deraadt     1: /*      $NetBSD: gcore.c,v 1.2 1995/09/05 02:51:00 tls Exp $      */
                      2:
                      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. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #ifndef lint
                     37: static char copyright[] =
                     38: "@(#) Copyright (c) 1992, 1993\n\
                     39:        The Regents of the University of California.  All rights reserved.\n";
                     40: #endif /* not lint */
                     41:
                     42: #ifndef lint
                     43: #if 0
                     44: static char sccsid[] = "@(#)gcore.c    8.2 (Berkeley) 9/23/93";
                     45: #else
                     46: static char rcsid[] = "$NetBSD: gcore.c,v 1.2 1995/09/05 02:51:00 tls Exp $";
                     47: #endif
                     48: #endif /* not lint */
                     49:
                     50: /*
                     51:  * Originally written by Eric Cooper in Fall 1981.
                     52:  * Inspired by a version 6 program by Len Levin, 1978.
                     53:  * Several pieces of code lifted from Bill Joy's 4BSD ps.
                     54:  * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
                     55:  * Lawrence Berkeley Laboratory.
                     56:  *
                     57:  * Portions of this software were developed by the Computer Systems
                     58:  * Engineering group at Lawrence Berkeley Laboratory under DARPA
                     59:  * contract BG 91-66 and contributed to Berkeley.
                     60:  */
                     61: #include <sys/param.h>
                     62: #include <sys/time.h>
                     63: #include <sys/stat.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/user.h>
                     66: #include <sys/sysctl.h>
                     67:
                     68: #include <machine/vmparam.h>
                     69:
                     70: #include <a.out.h>
                     71: #include <fcntl.h>
                     72: #include <kvm.h>
                     73: #include <limits.h>
                     74: #include <signal.h>
                     75: #include <stdio.h>
                     76: #include <stdlib.h>
                     77: #include <string.h>
                     78: #include <unistd.h>
                     79:
                     80: #include "extern.h"
                     81:
                     82: void   core __P((int, int, struct kinfo_proc *));
                     83: void   datadump __P((int, int, struct proc *, u_long, int));
                     84: void   usage __P((void));
                     85: void   userdump __P((int, struct proc *, u_long, int));
                     86:
                     87: kvm_t *kd;
                     88: /* XXX undocumented routine, should be in kvm.h? */
                     89: ssize_t kvm_uread __P((kvm_t *, struct proc *, u_long, char *, size_t));
                     90:
                     91: static int data_offset;
                     92:
                     93: int
                     94: main(argc, argv)
                     95:        int argc;
                     96:        char *argv[];
                     97: {
                     98:        register struct proc *p;
                     99:        struct kinfo_proc *ki;
                    100:        struct exec exec;
                    101:        int ch, cnt, efd, fd, pid, sflag, uid;
                    102:        char *corefile, errbuf[_POSIX2_LINE_MAX], fname[MAXPATHLEN + 1];
                    103:
                    104:        sflag = 0;
                    105:        corefile = NULL;
                    106:         while ((ch = getopt(argc, argv, "c:s")) != EOF) {
                    107:                 switch (ch) {
                    108:                 case 'c':
                    109:                        corefile = optarg;
                    110:                         break;
                    111:                case 's':
                    112:                        sflag = 1;
                    113:                        break;
                    114:                default:
                    115:                        usage();
                    116:                        break;
                    117:                }
                    118:        }
                    119:        argv += optind;
                    120:        argc -= optind;
                    121:
                    122:        if (argc != 2)
                    123:                usage();
                    124:
                    125:        kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
                    126:        if (kd == NULL)
                    127:                err(1, "%s", errbuf);
                    128:
                    129:        uid = getuid();
                    130:        pid = atoi(argv[1]);
                    131:
                    132:        ki = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt);
                    133:        if (ki == NULL || cnt != 1)
                    134:                err(1, "%d: not found", pid);
                    135:
                    136:        p = &ki->kp_proc;
                    137:        if (ki->kp_eproc.e_pcred.p_ruid != uid && uid != 0)
                    138:                err(1, "%d: not owner", pid);
                    139:
                    140:        if (p->p_stat == SZOMB)
                    141:                err(1, "%d: zombie", pid);
                    142:
                    143:        if (p->p_flag & P_WEXIT)
                    144:                err(0, "process exiting");
                    145:        if (p->p_flag & P_SYSTEM)       /* Swapper or pagedaemon. */
                    146:                err(1, "%d: system process");
                    147:
                    148:        if (corefile == NULL) {
                    149:                (void)snprintf(fname, sizeof(fname), "core.%d", pid);
                    150:                corefile = fname;
                    151:        }
                    152:        fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
                    153:        if (fd < 0)
                    154:                err(1, "%s: %s\n", corefile, strerror(errno));
                    155:
                    156:        efd = open(argv[0], O_RDONLY, 0);
                    157:        if (efd < 0)
                    158:                err(1, "%s: %s\n", argv[0], strerror(errno));
                    159:
                    160:        cnt = read(efd, &exec, sizeof(exec));
                    161:        if (cnt != sizeof(exec))
                    162:                err(1, "%s exec header: %s",
                    163:                    argv[0], cnt > 0 ? strerror(EIO) : strerror(errno));
                    164:
                    165:        data_offset = N_DATOFF(exec);
                    166:
                    167:        if (sflag && kill(pid, SIGSTOP) < 0)
                    168:                err(0, "%d: stop signal: %s", pid, strerror(errno));
                    169:
                    170:        core(efd, fd, ki);
                    171:
                    172:        if (sflag && kill(pid, SIGCONT) < 0)
                    173:                err(0, "%d: continue signal: %s", pid, strerror(errno));
                    174:        (void)close(fd);
                    175:
                    176:        exit(0);
                    177: }
                    178:
                    179: /*
                    180:  * core --
                    181:  *     Build the core file.
                    182:  */
                    183: void
                    184: core(efd, fd, ki)
                    185:        int efd;
                    186:        int fd;
                    187:        struct kinfo_proc *ki;
                    188: {
                    189:        union {
                    190:                struct user user;
                    191:                char ubytes[ctob(UPAGES)];
                    192:        } uarea;
                    193:        struct proc *p = &ki->kp_proc;
                    194:        int tsize = ki->kp_eproc.e_vm.vm_tsize;
                    195:        int dsize = ki->kp_eproc.e_vm.vm_dsize;
                    196:        int ssize = ki->kp_eproc.e_vm.vm_ssize;
                    197:        int cnt;
                    198:
                    199:        /* Read in user struct */
                    200:        cnt = kvm_read(kd, (u_long)p->p_addr, &uarea, sizeof(uarea));
                    201:        if (cnt != sizeof(uarea))
                    202:                err(1, "read user structure: %s",
                    203:                    cnt > 0 ? strerror(EIO) : strerror(errno));
                    204:
                    205:        /*
                    206:         * Fill in the eproc vm parameters, since these are garbage unless
                    207:         * the kernel is dumping core or something.
                    208:         */
                    209:        uarea.user.u_kproc = *ki;
                    210:
                    211:        /* Dump user area */
                    212:        cnt = write(fd, &uarea, sizeof(uarea));
                    213:        if (cnt != sizeof(uarea))
                    214:                err(1, "write user structure: %s",
                    215:                    cnt > 0 ? strerror(EIO) : strerror(errno));
                    216:
                    217:        /* Dump data segment */
                    218:        datadump(efd, fd, p, USRTEXT + ctob(tsize), dsize);
                    219:
                    220:        /* Dump stack segment */
                    221:        userdump(fd, p, USRSTACK - ctob(ssize), ssize);
                    222:
                    223:        /* Dump machine dependent portions of the core. */
                    224:        md_core(kd, fd, ki);
                    225: }
                    226:
                    227: void
                    228: datadump(efd, fd, p, addr, npage)
                    229:        register int efd;
                    230:        register int fd;
                    231:        struct proc *p;
                    232:        register u_long addr;
                    233:        register int npage;
                    234: {
                    235:        register int cc, delta;
                    236:        char buffer[NBPG];
                    237:
                    238:        delta = data_offset - addr;
                    239:        while (--npage >= 0) {
                    240:                cc = kvm_uread(kd, p, addr, buffer, NBPG);
                    241:                if (cc != NBPG) {
                    242:                        /* Try to read the page from the executable. */
                    243:                        if (lseek(efd, (off_t)addr + delta, SEEK_SET) == -1)
                    244:                                err(1, "seek executable: %s", strerror(errno));
                    245:                        cc = read(efd, buffer, sizeof(buffer));
                    246:                        if (cc != sizeof(buffer))
                    247:                                if (cc < 0)
                    248:                                        err(1, "read executable: %s",
                    249:                                            strerror(errno));
                    250:                                else    /* Assume untouched bss page. */
                    251:                                        bzero(buffer, sizeof(buffer));
                    252:                }
                    253:                cc = write(fd, buffer, NBPG);
                    254:                if (cc != NBPG)
                    255:                        err(1, "write data segment: %s",
                    256:                            cc > 0 ? strerror(EIO) : strerror(errno));
                    257:                addr += NBPG;
                    258:        }
                    259: }
                    260:
                    261: void
                    262: userdump(fd, p, addr, npage)
                    263:        register int fd;
                    264:        struct proc *p;
                    265:        register u_long addr;
                    266:        register int npage;
                    267: {
                    268:        register int cc;
                    269:        char buffer[NBPG];
                    270:
                    271:        while (--npage >= 0) {
                    272:                cc = kvm_uread(kd, p, addr, buffer, NBPG);
                    273:                if (cc != NBPG)
                    274:                        /* Could be an untouched fill-with-zero page. */
                    275:                        bzero(buffer, NBPG);
                    276:                cc = write(fd, buffer, NBPG);
                    277:                if (cc != NBPG)
                    278:                        err(1, "write stack segment: %s",
                    279:                            cc > 0 ? strerror(EIO) : strerror(errno));
                    280:                addr += NBPG;
                    281:        }
                    282: }
                    283:
                    284: void
                    285: usage()
                    286: {
                    287:        (void)fprintf(stderr, "usage: gcore [-s] [-c core] executable pid\n");
                    288:        exit(1);
                    289: }
                    290:
                    291: #if __STDC__
                    292: #include <stdarg.h>
                    293: #else
                    294: #include <varargs.h>
                    295: #endif
                    296:
                    297: void
                    298: #if __STDC__
                    299: err(int fatal, const char *fmt, ...)
                    300: #else
                    301: err(fatal, fmt, va_alist)
                    302:        int fatal;
                    303:        char *fmt;
                    304:         va_dcl
                    305: #endif
                    306: {
                    307:        va_list ap;
                    308: #if __STDC__
                    309:        va_start(ap, fmt);
                    310: #else
                    311:        va_start(ap);
                    312: #endif
                    313:        (void)fprintf(stderr, "gcore: ");
                    314:        (void)vfprintf(stderr, fmt, ap);
                    315:        va_end(ap);
                    316:        (void)fprintf(stderr, "\n");
                    317:        exit(1);
                    318:        /* NOTREACHED */
                    319: }