Annotation of 43BSDTahoe/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.3 (Berkeley) 3/30/87";
                     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("Warning: process exiting.\n");
                    157:                if (p->p_flag & SSYS) {
                    158:                        printf("System process.\n");
                    159:                        /* i.e. swapper or pagedaemon */
                    160:                        continue;
                    161:                }
                    162:                sprintf(coref, "core.%d", pid);
                    163:                if ((cor = creat(coref, 0666)) < 0) {
                    164:                        perror(coref);
                    165:                        exit(1);
                    166:                }
                    167:                core(p);
                    168:                close(cor);
                    169:                printf("%s dumped\n", coref);
                    170:        }
                    171: }
                    172: 
                    173: getw(loc)
                    174:        off_t loc;
                    175: {
                    176:        int word;
                    177: 
                    178:        Get(kmem, loc, &word, sizeof(int));
                    179:        return (word);
                    180: }
                    181: 
                    182: openfiles()
                    183: {
                    184:        kmem = open(KMEM, 0);
                    185:        if (kmem < 0) {
                    186:                perror(KMEM);
                    187:                exit(1);
                    188:        }
                    189:        mem = open(MEM, 0);
                    190:        if (mem < 0) {
                    191:                perror(MEM);
                    192:                exit(1);
                    193:        }
                    194:        swap = open(SWAP, 0);
                    195:        if (swap < 0) {
                    196:                perror(SWAP);
                    197:                exit(1);
                    198:        }
                    199: }
                    200: 
                    201: getkvars()
                    202: {
                    203:        nlist(NLIST, nl);
                    204:        if (nl[0].n_type == 0) {
                    205:                printf("%s: No namelist\n", NLIST);
                    206:                exit(1);
                    207:        }
                    208:        Usrptmap = (struct pte *) nl[X_USRPTMA].n_value;
                    209:        usrpt = (struct pte *) nl[X_USRPT].n_value;
                    210: }
                    211: 
                    212: /*
                    213:  * Get the system page table entries (mapping the user page table).
                    214:  * These are the entries Usrptmap[i .. i + szpt],
                    215:  * where i = btokmx(p->p_p0br) and szpt = p->p_szpt.
                    216:  * For our purposes, we can skip over the ptes mapping
                    217:  * the text segment ptes.
                    218:  */
                    219: struct pte     *syspt;         /* pte's from Usrptmap */
                    220: int            nsysptes;
                    221: 
                    222: getsyspt(p)
                    223:        register struct proc *p;
                    224: {
                    225:        nsysptes = p->p_szpt - (p->p_tsize / NPTEPG);
                    226:        syspt = (struct pte *) malloc(nsysptes * sizeof(struct pte));
                    227:        if (syspt == NULL)
                    228:                panic("can't alloc %d page table entries", nsysptes);
                    229:        Get(kmem, &Usrptmap[btokmx(p->p_p0br) + (p->p_tsize / NPTEPG)],
                    230:                syspt, nsysptes * sizeof(struct pte));
                    231: }
                    232: 
                    233: /*
                    234:  * Get the user page table for a segment.
                    235:  * seg 0 = p0 (not including text)
                    236:  * seg 1 = p1 (stack and u area)
                    237:  * The system pt is consulted to find each page of user ptes.
                    238:  */
                    239: struct pte *
                    240: getpt(p, seg)
                    241:        register struct proc *p;
                    242:        int seg;
                    243: {
                    244:        register int i;
                    245:        register struct pte *spt;
                    246:        struct pte *pt;
                    247:        int nptes, offset, n;
                    248: 
                    249:        if (seg == 0) {
                    250:                nptes = p->p_dsize;
                    251:                spt = syspt;
                    252:                offset = p->p_tsize % NPTEPG;
                    253:        } else {
                    254:                nptes = p->p_ssize + UPAGES;
                    255:                spt = syspt + (nsysptes - ctopt(nptes));
                    256:                offset = -nptes % NPTEPG;
                    257:                if (offset < 0)
                    258:                        offset += NPTEPG;
                    259:        }
                    260:        pt = (struct pte *) malloc(nptes * sizeof(struct pte));
                    261:        if (pt == NULL)
                    262:                panic("can't alloc %d page table entries", nptes);
                    263:        for (i = 0; i < nptes; i += n) {
                    264:                n = min(NPTEPG - offset, nptes - i);
                    265:                Get(mem, ctob(spt->pg_pfnum) + offset * sizeof(struct pte),
                    266:                     pt + i, n * sizeof(struct pte));
                    267:                spt++;
                    268:                offset = 0;
                    269:        }
                    270:        return (pt);
                    271: }
                    272: 
                    273: /*
                    274:  * Build the core file.
                    275:  */
                    276: core(p)
                    277:        register struct proc *p;
                    278: {
                    279:        register struct pte *p0, *p1;
                    280: 
                    281:        if (p->p_flag & SLOAD) {                /* page tables are resident */
                    282:                getsyspt(p);
                    283:                p0 = getpt(p, 0);
                    284:                p1 = getpt(p, 1);
                    285: #ifdef DEBUG
                    286:                showpt(syspt, nsysptes, "system");
                    287:                showpt(p0, p->p_dsize, "p0");
                    288:                showpt(p1, p->p_ssize + UPAGES, "p1");
                    289: #endif
                    290:        }
                    291:        getu(p, &p1[p->p_ssize]);                       /* u area */
                    292:        getseg(p, p->p_dsize, p0, &u.u_dmap, 0);        /* data */
                    293:        getseg(p, p->p_ssize, p1, &u.u_smap, 1);        /* stack */
                    294:        if (p->p_flag & SLOAD) {
                    295:                free((char *) syspt);
                    296:                free((char *) p0);
                    297:                free((char *) p1);
                    298:        }
                    299: }
                    300: 
                    301: /*
                    302:  * Get the u area.
                    303:  * Keeps around the u structure for later use
                    304:  * (the data and stack disk map structures).
                    305:  */
                    306: getu(p, pages)
                    307:        register struct proc *p;
                    308:        register struct pte *pages;
                    309: {
                    310:        register int i;
                    311: 
                    312:        if ((p->p_flag & SLOAD) == 0) {
                    313:                Get(swap, ctob(p->p_swaddr), uarea, ctob(UPAGES));
                    314:                write(cor, uarea, ctob(UPAGES));
                    315:                return;
                    316:        }
                    317:        for (i = 0; i < UPAGES; i += CLSIZE) {
                    318:                Get(mem, ctob(pages[i].pg_pfnum), uarea[i], ctob(CLSIZE));
                    319:                write(cor, uarea[i], ctob(CLSIZE));
                    320:        }
                    321: }
                    322: 
                    323: /*
                    324:  * Copy a segment to the core file.
                    325:  * The segment is described by its size in clicks,
                    326:  * its page table, its disk map, and whether or not
                    327:  * it grows backwards.
                    328:  * Note that the page table address is allowed to be meaningless
                    329:  * if the process is swapped out.
                    330:  */
                    331: getseg(p, segsize, pages, map, rev)
                    332:        register struct proc *p;
                    333:        int segsize;
                    334:        register struct pte *pages;
                    335:        struct dmap *map;
                    336: {
                    337:        register int i;
                    338:        struct dblock db;
                    339:        int size;
                    340:        char buf[ctob(CLSIZE)];
                    341: 
                    342:        for (i = 0; i < segsize; i += CLSIZE) {
                    343:                size = min(CLSIZE, segsize - i);
                    344:                if ((p->p_flag & SLOAD) == 0 || pages[i].pg_fod ||
                    345:                    pages[i].pg_pfnum == 0) {
                    346:                        vstodb(i, size, map, &db, rev);
                    347:                        Get(swap, ctob(db.db_base), buf, ctob(size));
                    348:                        write(cor, buf, ctob(size));
                    349:                } else {
                    350:                        Get(mem, ctob(pages[i].pg_pfnum), buf, ctob(size));
                    351:                        write(cor, buf, ctob(size));
                    352:                }
                    353:        }
                    354: }
                    355: 
                    356: /*
                    357:  * Given a base/size pair in virtual swap area,
                    358:  * return a physical base/size pair which is the
                    359:  * (largest) initial, physically contiguous block.
                    360:  */
                    361: vstodb(vsbase, vssize, dmp, dbp, rev)
                    362:        register int vsbase;
                    363:        int vssize;
                    364:        struct dmap *dmp;
                    365:        register struct dblock *dbp;
                    366: {
                    367:        register int blk = dmmin;
                    368:        register swblk_t *ip = dmp->dm_map;
                    369: 
                    370:        if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
                    371:                panic("can't make sense out of virtual memory (gcore probably needs to be recompiled)");
                    372:        while (vsbase >= blk) {
                    373:                vsbase -= blk;
                    374:                if (blk < dmmax)
                    375:                        blk *= 2;
                    376:                ip++;
                    377:        }
                    378:        if (*ip <= 0 || *ip + blk > nswap)
                    379:                panic("vstodb *ip");
                    380:        dbp->db_size = MIN(vssize, blk - vsbase);
                    381:        dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
                    382: }
                    383: 
                    384: /*VARARGS1*/
                    385: panic(cp, a, b, c, d)
                    386:        char *cp;
                    387: {
                    388:        printf(cp, a, b, c, d);
                    389:        printf("\n");
                    390:        longjmp(cont_frame, 1);
                    391: }
                    392: 
                    393: /* 
                    394:  * Debugging routine to print out page table.
                    395:  */
                    396: #ifdef DEBUG
                    397: showpt(pt, n, s)
                    398:        struct pte *pt;
                    399:        int n;
                    400:        char *s;
                    401: {
                    402:        register struct pte *p;
                    403:        register int i;
                    404: 
                    405:        printf("*** %s page table\n", s);
                    406:        for (i = 0, p = pt; i < n; i++, p++)
                    407:                if (! p->pg_fod)
                    408:                        printf("%d: %x\n", i, p->pg_pfnum);
                    409: }
                    410: #endif

unix.superglobalmegacorp.com

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