|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.