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