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

Defined functions

core defined in line 278; used 1 times
getkvars defined in line 203; used 1 times
getpt defined in line 241; used 2 times
getseg defined in line 333; used 2 times
getsyspt defined in line 224; used 1 times
getu defined in line 308; used 1 times
getw defined in line 175; used 5 times
main defined in line 104; never used
openfiles defined in line 184; used 1 times
panic defined in line 387; used 6 times
showpt defined in line 399; used 3 times
vstodb defined in line 363; used 1 times

Defined variables

Usrptmap defined in line 99; used 2 times
cont_frame defined in line 102; used 2 times
copyright defined in line 8; never used
cor defined in line 101; used 6 times
coref defined in line 100; used 4 times
dmmax defined in line 98; used 2 times
dmmin defined in line 98; used 2 times
kmem defined in line 101; used 6 times
mem defined in line 101; used 5 times
nl defined in line 63; used 9 times
nproc defined in line 96; used 3 times
nswap defined in line 97; used 2 times
nsysptes defined in line 222; used 6 times
proc defined in line 82; used 2 times
sccsid defined in line 14; never used
swap defined in line 101; used 4 times
syspt defined in line 221; used 7 times
usrpt defined in line 99; used 1 times

Defined macros

FEW defined in line 81; used 4 times
Get defined in line 58; used 7 times
KMEM defined in line 92; used 2 times
MEM defined in line 93; used 2 times
NLIST defined in line 91; used 2 times
Read defined in line 53; used 2 times
SWAP defined in line 94; used 2 times
Seek defined in line 48; used 2 times
X_DMMAX defined in line 77; used 1 times
X_DMMIN defined in line 75; used 1 times
X_NPROC defined in line 73; used 1 times
X_NSWAP defined in line 71; used 1 times
X_PROC defined in line 65; used 1 times
X_USRPT defined in line 69; used 1 times
X_USRPTMA defined in line 67; used 1 times
min defined in line 46; used 2 times
u defined in line 88; used 2 times
uarea defined in line 89; used 4 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1916
Valid CSS Valid XHTML 1.0 Strict