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