Annotation of 43BSD/ucb/gcore.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)gcore.c    5.2 (Berkeley) 5/31/85";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * gcore - get core images of running processes
                     19:  *
                     20:  * Author: Eric Cooper
                     21:  * Written: Fall 1981.
                     22:  *
                     23:  * Inspired by a version 6 program by Len Levin, 1978.
                     24:  * Several pieces of code lifted from Bill Joy's 4BSD ps.
                     25:  *
                     26:  * Permission to copy or modify this program in whole or in part is hereby
                     27:  * granted, provided that the above credits are preserved.
                     28:  *
                     29:  * This code performs a simple simulation of the virtual memory system in user
                     30:  * code.  If the virtual memory system changes, this program must be modified
                     31:  * accordingly.  It must also be recompiled whenever system data structures
                     32:  * change.
                     33:  */
                     34: #include <stdio.h>
                     35: #include <nlist.h>
                     36: #include <sys/param.h>
                     37: #include <sys/dir.h>
                     38: #include <sys/user.h>
                     39: #include <sys/proc.h>
                     40: #include <machine/pte.h>
                     41: #include <sys/vm.h>
                     42: #include <setjmp.h>
                     43: 
                     44: /* Various macros for efficiency. */
                     45: 
                     46: #define        min(a, b)       (a < b ? a : b)
                     47: 
                     48: #define        Seek(f, pos) {\
                     49:        if (lseek(f, (long) (pos), 0) != (long) (pos)) \
                     50:                panic("seek error"); \
                     51: }
                     52: 
                     53: #define        Read(f, addr, n) {\
                     54:        if (read(f, (char *) (addr), (int) (n)) != (int) (n)) \
                     55:                panic("read error"); \
                     56: }
                     57: 
                     58: #define        Get(f, pos, addr, n) {\
                     59:        Seek(f, pos); \
                     60:        Read(f, addr, n); \
                     61: }
                     62: 
                     63: struct nlist nl[] = {
                     64:        { "_proc" },
                     65: #define        X_PROC          0
                     66:        { "_Usrptmap" },
                     67: #define        X_USRPTMA       1
                     68:        { "_usrpt" },
                     69: #define        X_USRPT         2
                     70:        { "_nswap" },
                     71: #define        X_NSWAP         3
                     72:        { "_nproc" },
                     73: #define        X_NPROC         4
                     74:        { "_dmmin" },
                     75: #define        X_DMMIN         5
                     76:        { "_dmmax" },
                     77: #define        X_DMMAX         6
                     78:        { 0 },
                     79: };
                     80: 
                     81: #define FEW    20              /* for fewer system calls */
                     82: struct proc proc[FEW];
                     83: 
                     84: union {
                     85:        struct user user;
                     86:        char upages[UPAGES][NBPG];
                     87: } user;
                     88: #define u      user.user
                     89: #define uarea  user.upages
                     90: 
                     91: #define NLIST  "/vmunix"
                     92: #define KMEM   "/dev/kmem"
                     93: #define MEM    "/dev/mem"
                     94: #define SWAP   "/dev/drum"     /* "/dev/swap" on some systems */
                     95: 
                     96: int    nproc;
                     97: int    nswap;
                     98: int    dmmin, dmmax;
                     99: struct pte *Usrptmap, *usrpt;
                    100: char   coref[20];
                    101: int    kmem, mem, swap, cor;
                    102: jmp_buf        cont_frame;
                    103: 
                    104: main(argc, argv)
                    105:        int argc;
                    106:        char **argv;
                    107: {
                    108:        register int i, j;
                    109:        register struct proc *p;
                    110:        off_t procbase, procp;
                    111:        int pid, uid;
                    112:        char c;
                    113: 
                    114:        if (argc < 2) {
                    115:                printf("Usage: %s pid ...\n", argv[0]);
                    116:                exit(1);
                    117:        }
                    118:        openfiles();
                    119:        getkvars();
                    120:        procbase = getw(nl[X_PROC].n_value);
                    121:        nproc = getw(nl[X_NPROC].n_value);
                    122:        nswap = getw(nl[X_NSWAP].n_value);
                    123:        dmmin = getw(nl[X_DMMIN].n_value);
                    124:        dmmax = getw(nl[X_DMMAX].n_value);
                    125:        while (--argc > 0) {
                    126:                if ((pid = atoi(*++argv)) <= 0 || setjmp(cont_frame))
                    127:                        continue;
                    128:                printf("%d: ", pid);
                    129:                procp = procbase;
                    130:                for (i = 0; i < nproc; i += FEW) {
                    131:                        Seek(kmem, procp);
                    132:                        j = nproc - i;
                    133:                        if (j > FEW)
                    134:                                j = FEW;
                    135:                        j *= sizeof(struct proc);
                    136:                        Read(kmem, (char *) proc, j);
                    137:                        procp += j;
                    138:                        for (j = j / sizeof(struct proc) - 1; j >= 0; j--) {
                    139:                                p = &proc[j];
                    140:                                if (p->p_pid == pid)
                    141:                                        goto found;
                    142:                        }
                    143:                }
                    144:                printf("Process not found.\n");
                    145:                continue;
                    146:        found:
                    147:                if (p->p_uid != (uid = getuid()) && uid != 0) {
                    148:                        printf("Not owner.\n");
                    149:                        continue;
                    150:                }
                    151:                if (p->p_stat == SZOMB) {
                    152:                        printf("Zombie.\n");
                    153:                        continue;
                    154:                }
                    155:                if (p->p_flag & SWEXIT) {
                    156:                        printf("Process exiting.\n");
                    157:                        continue;
                    158:                }
                    159:                if (p->p_flag & SSYS) {
                    160:                        printf("System process.\n");
                    161:                        /* i.e. swapper or pagedaemon */
                    162:                        continue;
                    163:                }
                    164:                sprintf(coref, "core.%d", pid);
                    165:                if ((cor = creat(coref, 0666)) < 0) {
                    166:                        perror(coref);
                    167:                        exit(1);
                    168:                }
                    169:                core(p);
                    170:                close(cor);
                    171:                printf("%s dumped\n", coref);
                    172:        }
                    173: }
                    174: 
                    175: getw(loc)
                    176:        off_t loc;
                    177: {
                    178:        int word;
                    179: 
                    180:        Get(kmem, loc, &word, sizeof(int));
                    181:        return (word);
                    182: }
                    183: 
                    184: openfiles()
                    185: {
                    186:        kmem = open(KMEM, 0);
                    187:        if (kmem < 0) {
                    188:                perror(KMEM);
                    189:                exit(1);
                    190:        }
                    191:        mem = open(MEM, 0);
                    192:        if (mem < 0) {
                    193:                perror(MEM);
                    194:                exit(1);
                    195:        }
                    196:        swap = open(SWAP, 0);
                    197:        if (swap < 0) {
                    198:                perror(SWAP);
                    199:                exit(1);
                    200:        }
                    201: }
                    202: 
                    203: getkvars()
                    204: {
                    205:        nlist(NLIST, nl);
                    206:        if (nl[0].n_type == 0) {
                    207:                printf("%s: No namelist\n", NLIST);
                    208:                exit(1);
                    209:        }
                    210:        Usrptmap = (struct pte *) nl[X_USRPTMA].n_value;
                    211:        usrpt = (struct pte *) nl[X_USRPT].n_value;
                    212: }
                    213: 
                    214: /*
                    215:  * Get the system page table entries (mapping the user page table).
                    216:  * These are the entries Usrptmap[i .. i + szpt],
                    217:  * where i = btokmx(p->p_p0br) and szpt = p->p_szpt.
                    218:  * For our purposes, we can skip over the ptes mapping
                    219:  * the text segment ptes.
                    220:  */
                    221: struct pte     *syspt;         /* pte's from Usrptmap */
                    222: int            nsysptes;
                    223: 
                    224: getsyspt(p)
                    225:        register struct proc *p;
                    226: {
                    227:        nsysptes = p->p_szpt - (p->p_tsize / NPTEPG);
                    228:        syspt = (struct pte *) malloc(nsysptes * sizeof(struct pte));
                    229:        if (syspt == NULL)
                    230:                panic("can't alloc %d page table entries", nsysptes);
                    231:        Get(kmem, &Usrptmap[btokmx(p->p_p0br) + (p->p_tsize / NPTEPG)],
                    232:                syspt, nsysptes * sizeof(struct pte));
                    233: }
                    234: 
                    235: /*
                    236:  * Get the user page table for a segment.
                    237:  * seg 0 = p0 (not including text)
                    238:  * seg 1 = p1 (stack and u area)
                    239:  * The system pt is consulted to find each page of user ptes.
                    240:  */
                    241: struct pte *
                    242: getpt(p, seg)
                    243:        register struct proc *p;
                    244:        int seg;
                    245: {
                    246:        register int i;
                    247:        register struct pte *spt;
                    248:        struct pte *pt;
                    249:        int nptes, offset, n;
                    250: 
                    251:        if (seg == 0) {
                    252:                nptes = p->p_dsize;
                    253:                spt = syspt;
                    254:                offset = p->p_tsize % NPTEPG;
                    255:        } else {
                    256:                nptes = p->p_ssize + UPAGES;
                    257:                spt = syspt + (nsysptes - ctopt(nptes));
                    258:                offset = -nptes % NPTEPG;
                    259:                if (offset < 0)
                    260:                        offset += NPTEPG;
                    261:        }
                    262:        pt = (struct pte *) malloc(nptes * sizeof(struct pte));
                    263:        if (pt == NULL)
                    264:                panic("can't alloc %d page table entries", nptes);
                    265:        for (i = 0; i < nptes; i += n) {
                    266:                n = min(NPTEPG - offset, nptes - i);
                    267:                Get(mem, ctob(spt->pg_pfnum) + offset * sizeof(struct pte),
                    268:                     pt + i, n * sizeof(struct pte));
                    269:                spt++;
                    270:                offset = 0;
                    271:        }
                    272:        return (pt);
                    273: }
                    274: 
                    275: /*
                    276:  * Build the core file.
                    277:  */
                    278: core(p)
                    279:        register struct proc *p;
                    280: {
                    281:        register struct pte *p0, *p1;
                    282: 
                    283:        if (p->p_flag & SLOAD) {                /* page tables are resident */
                    284:                getsyspt(p);
                    285:                p0 = getpt(p, 0);
                    286:                p1 = getpt(p, 1);
                    287: #ifdef DEBUG
                    288:                showpt(syspt, nsysptes, "system");
                    289:                showpt(p0, p->p_dsize, "p0");
                    290:                showpt(p1, p->p_ssize + UPAGES, "p1");
                    291: #endif
                    292:        }
                    293:        getu(p, &p1[p->p_ssize]);                       /* u area */
                    294:        getseg(p, p->p_dsize, p0, &u.u_dmap, 0);        /* data */
                    295:        getseg(p, p->p_ssize, p1, &u.u_smap, 1);        /* stack */
                    296:        if (p->p_flag & SLOAD) {
                    297:                free((char *) syspt);
                    298:                free((char *) p0);
                    299:                free((char *) p1);
                    300:        }
                    301: }
                    302: 
                    303: /*
                    304:  * Get the u area.
                    305:  * Keeps around the u structure for later use
                    306:  * (the data and stack disk map structures).
                    307:  */
                    308: getu(p, pages)
                    309:        register struct proc *p;
                    310:        register struct pte *pages;
                    311: {
                    312:        register int i;
                    313: 
                    314:        if ((p->p_flag & SLOAD) == 0) {
                    315:                Get(swap, ctob(p->p_swaddr), uarea, ctob(UPAGES));
                    316:                write(cor, uarea, ctob(UPAGES));
                    317:                return;
                    318:        }
                    319:        for (i = 0; i < UPAGES; i += CLSIZE) {
                    320:                Get(mem, ctob(pages[i].pg_pfnum), uarea[i], ctob(CLSIZE));
                    321:                write(cor, uarea[i], ctob(CLSIZE));
                    322:        }
                    323: }
                    324: 
                    325: /*
                    326:  * Copy a segment to the core file.
                    327:  * The segment is described by its size in clicks,
                    328:  * its page table, its disk map, and whether or not
                    329:  * it grows backwards.
                    330:  * Note that the page table address is allowed to be meaningless
                    331:  * if the process is swapped out.
                    332:  */
                    333: getseg(p, segsize, pages, map, rev)
                    334:        register struct proc *p;
                    335:        int segsize;
                    336:        register struct pte *pages;
                    337:        struct dmap *map;
                    338: {
                    339:        register int i;
                    340:        struct dblock db;
                    341:        int size;
                    342:        char buf[ctob(CLSIZE)];
                    343: 
                    344:        for (i = 0; i < segsize; i += CLSIZE) {
                    345:                size = min(CLSIZE, segsize - i);
                    346:                if ((p->p_flag & SLOAD) == 0 || pages[i].pg_fod ||
                    347:                    pages[i].pg_pfnum == 0) {
                    348:                        vstodb(i, size, map, &db, rev);
                    349:                        Get(swap, ctob(db.db_base), buf, ctob(size));
                    350:                        write(cor, buf, ctob(size));
                    351:                } else {
                    352:                        Get(mem, ctob(pages[i].pg_pfnum), buf, ctob(size));
                    353:                        write(cor, buf, ctob(size));
                    354:                }
                    355:        }
                    356: }
                    357: 
                    358: /*
                    359:  * Given a base/size pair in virtual swap area,
                    360:  * return a physical base/size pair which is the
                    361:  * (largest) initial, physically contiguous block.
                    362:  */
                    363: vstodb(vsbase, vssize, dmp, dbp, rev)
                    364:        register int vsbase;
                    365:        int vssize;
                    366:        struct dmap *dmp;
                    367:        register struct dblock *dbp;
                    368: {
                    369:        register int blk = dmmin;
                    370:        register swblk_t *ip = dmp->dm_map;
                    371: 
                    372:        if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
                    373:                panic("can't make sense out of virtual memory (gcore probably needs to be recompiled)");
                    374:        while (vsbase >= blk) {
                    375:                vsbase -= blk;
                    376:                if (blk < dmmax)
                    377:                        blk *= 2;
                    378:                ip++;
                    379:        }
                    380:        if (*ip <= 0 || *ip + blk > nswap)
                    381:                panic("vstodb *ip");
                    382:        dbp->db_size = MIN(vssize, blk - vsbase);
                    383:        dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
                    384: }
                    385: 
                    386: /*VARARGS1*/
                    387: panic(cp, a, b, c, d)
                    388:        char *cp;
                    389: {
                    390:        printf(cp, a, b, c, d);
                    391:        printf("\n");
                    392:        longjmp(cont_frame, 1);
                    393: }
                    394: 
                    395: /* 
                    396:  * Debugging routine to print out page table.
                    397:  */
                    398: #ifdef DEBUG
                    399: showpt(pt, n, s)
                    400:        struct pte *pt;
                    401:        int n;
                    402:        char *s;
                    403: {
                    404:        register struct pte *p;
                    405:        register int i;
                    406: 
                    407:        printf("*** %s page table\n", s);
                    408:        for (i = 0, p = pt; i < n; i++, p++)
                    409:                if (! p->pg_fod)
                    410:                        printf("%d: %x\n", i, p->pg_pfnum);
                    411: }
                    412: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.