|
|
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.