|
|
1.1 root 1: /*
2: * Copyright (c) 1980 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) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif /* not lint */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)pstat.c 5.18 (Berkeley) 2/27/88";
15: #endif /* not lint */
16:
17: /*
18: * Print system stuff
19: */
20:
21: #include <sys/param.h>
22: #include <sys/dir.h>
23: #define KERNEL
24: #include <sys/file.h>
25: #undef KERNEL
26: #include <sys/user.h>
27: #include <sys/proc.h>
28: #include <sys/text.h>
29: #include <sys/inode.h>
30: #include <sys/map.h>
31: #include <sys/ioctl.h>
32: #include <sys/tty.h>
33: #include <sys/conf.h>
34: #include <sys/vm.h>
35: #include <nlist.h>
36: #include <machine/pte.h>
37: #include <stdio.h>
38:
39: #define mask(x) (x&0377)
40: #define clear(x) ((int)x &~ KERNBASE)
41:
42: char *fcore = "/dev/kmem";
43: char *fmem = "/dev/mem";
44: char *fnlist = "/vmunix";
45: int fc, fm;
46:
47: struct nlist nl[] = {
48: #define SINODE 0
49: { "_inode" },
50: #define STEXT 1
51: { "_text" },
52: #define SPROC 2
53: { "_proc" },
54: #define SCONS 3
55: { "_cons" },
56: #define SFIL 4
57: { "_file" },
58: #define USRPTMA 5
59: { "_Usrptmap" },
60: #define USRPT 6
61: { "_usrpt" },
62: #define SWAPMAP 7
63: { "_swapmap" },
64: #define SNPROC 8
65: { "_nproc" },
66: #define SNTEXT 9
67: { "_ntext" },
68: #define SNFILE 10
69: { "_nfile" },
70: #define SNINODE 11
71: { "_ninode" },
72: #define SNSWAPMAP 12
73: { "_nswapmap" },
74: #define SPTY 13
75: { "_pt_tty" },
76: #define SDMMIN 14
77: { "_dmmin" },
78: #define SDMMAX 15
79: { "_dmmax" },
80: #define SNSWDEV 16
81: { "_nswdev" },
82: #define SSWDEVT 17
83: { "_swdevt" },
84: #define SYSMAP 18
85: { "_Sysmap" },
86: #define SNPTY 19
87: { "_npty" },
88: #ifdef vax
89: #define SDZ (SNPTY+1)
90: { "_dz_tty" },
91: #define SNDZ (SNPTY+2)
92: { "_dz_cnt" },
93: #define SDMF (SNPTY+3)
94: { "_dmf_tty" },
95: #define SNDMF (SNPTY+4)
96: { "_ndmf" },
97: #define SDH (SNPTY+5)
98: { "_dh11" },
99: #define SNDH (SNPTY+6)
100: { "_ndh11" },
101: #define SDHU (SNPTY+7)
102: { "_dhu_tty" },
103: #define SNDHU (SNPTY+8)
104: { "_ndhu" },
105: #define SDMZ (SNPTY+9)
106: { "_dmz_tty" },
107: #define SNDMZ (SNPTY+10)
108: { "_ndmz" },
109: #define SQD (SNPTY+11)
110: { "_qd_tty" },
111: #define SNQD (SNPTY+12)
112: { "_nNQD" },
113: #endif
114: #ifdef tahoe
115: #define SVX (SNPTY+1)
116: { "_vx_tty" },
117: #define SNVX (SNPTY+2)
118: { "_nvx" },
119: #define SMP (SNPTY+3)
120: { "_mp_tty" },
121: #define SNMP (SNPTY+4)
122: { "_nmp" },
123: #endif
124: { "" }
125: };
126:
127: int inof;
128: int txtf;
129: int prcf;
130: int ttyf;
131: int usrf;
132: long ubase;
133: int filf;
134: int swpf;
135: int totflg;
136: char partab[1];
137: struct cdevsw cdevsw[1];
138: struct bdevsw bdevsw[1];
139: int allflg;
140: int kflg;
141: struct pte *Usrptma;
142: struct pte *usrpt;
143: u_long getword();
144: off_t mkphys();
145:
146: main(argc, argv)
147: int argc;
148: char **argv;
149: {
150: extern char *optarg;
151: extern int optind;
152: int ch;
153:
154: while ((ch = getopt(argc, argv, "Tafikptu:sx")) != EOF)
155: switch((char)ch) {
156: case 'T':
157: totflg++;
158: break;
159: case 'a':
160: allflg++;
161: /*FALLTHROUGH*/
162: case 'p':
163: prcf++;
164: break;
165: case 'f':
166: filf++;
167: break;
168: case 'i':
169: inof++;
170: break;
171: case 'k': /* undocumented */
172: kflg++;
173: fcore = fmem = "/vmcore";
174: break;
175: case 't':
176: ttyf++;
177: break;
178: case 'u':
179: usrf++;
180: sscanf(optarg, "%x", &ubase);
181: break;
182: case 's':
183: swpf++;
184: break;
185: case 'x':
186: txtf++;
187: break;
188: case '?':
189: default:
190: printf("usage: pstat -[Tafiptsx] [-u [ubase]] [system] [core]\n");
191: exit(1);
192: }
193: argc -= optind;
194: argv += optind;
195:
196: if (argc>1) {
197: fcore = fmem = argv[1];
198: kflg++;
199: }
200: if ((fc = open(fcore, O_RDONLY, 0)) < 0) {
201: perror(fcore);
202: exit(1);
203: }
204: if ((fm = open(fmem, O_RDONLY, 0)) < 0) {
205: perror(fmem);
206: exit(1);
207: }
208: if (argc>0)
209: fnlist = argv[0];
210: nlist(fnlist, nl);
211: if (nl[0].n_type == 0) {
212: printf("pstat: no namelist.\n");
213: exit(1);
214: }
215: usrpt = (struct pte *)nl[USRPT].n_value;
216: Usrptma = (struct pte *)nl[USRPTMA].n_value;
217: if (!(filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf)) {
218: printf("pstat: one or more of -[aixptfsu] is required\n");
219: exit(1);
220: }
221: if (filf||totflg)
222: dofile();
223: if (inof||totflg)
224: doinode();
225: if (prcf||totflg)
226: doproc();
227: if (txtf||totflg)
228: dotext();
229: if (ttyf)
230: dotty();
231: if (usrf)
232: dousr();
233: if (swpf||totflg)
234: doswap();
235: }
236:
237: doinode()
238: {
239: register struct inode *ip;
240: struct inode *xinode, *ainode;
241: register int nin;
242: int ninode;
243:
244: nin = 0;
245: ninode = getword(nl[SNINODE].n_value);
246: xinode = (struct inode *)calloc(ninode, sizeof (struct inode));
247: ainode = (struct inode *)getword(nl[SINODE].n_value);
248: if (ninode < 0 || ninode > 10000) {
249: fprintf(stderr, "number of inodes is preposterous (%d)\n",
250: ninode);
251: return;
252: }
253: if (xinode == NULL) {
254: fprintf(stderr, "can't allocate memory for inode table\n");
255: return;
256: }
257: lseek(fc, mkphys((off_t)ainode), 0);
258: read(fc, xinode, ninode * sizeof(struct inode));
259: for (ip = xinode; ip < &xinode[ninode]; ip++)
260: if (ip->i_count)
261: nin++;
262: if (totflg) {
263: printf("%3d/%3d inodes\n", nin, ninode);
264: return;
265: }
266: printf("%d/%d active inodes\n", nin, ninode);
267: printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n");
268: for (ip = xinode; ip < &xinode[ninode]; ip++) {
269: if (ip->i_count == 0)
270: continue;
271: printf("%8.1x ", ainode + (ip - xinode));
272: putf(ip->i_flag&ILOCKED, 'L');
273: putf(ip->i_flag&IUPD, 'U');
274: putf(ip->i_flag&IACC, 'A');
275: putf(ip->i_flag&IMOUNT, 'M');
276: putf(ip->i_flag&IWANT, 'W');
277: putf(ip->i_flag&ITEXT, 'T');
278: putf(ip->i_flag&ICHG, 'C');
279: putf(ip->i_flag&ISHLOCK, 'S');
280: putf(ip->i_flag&IEXLOCK, 'E');
281: putf(ip->i_flag&ILWAIT, 'Z');
282: printf("%4d", ip->i_count&0377);
283: printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev));
284: printf("%4d", ip->i_shlockc&0377);
285: printf("%4d", ip->i_exlockc&0377);
286: printf("%6d", ip->i_number);
287: printf("%6x", ip->i_mode & 0xffff);
288: printf("%4d", ip->i_nlink);
289: printf("%4d", ip->i_uid);
290: if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR)
291: printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev));
292: else
293: printf("%10ld", ip->i_size);
294: printf("\n");
295: }
296: free(xinode);
297: }
298:
299: u_long
300: getword(loc)
301: off_t loc;
302: {
303: u_long word;
304:
305: if (kflg)
306: loc = clear(loc);
307: lseek(fc, loc, 0);
308: read(fc, &word, sizeof (word));
309: return (word);
310: }
311:
312: putf(v, n)
313: {
314: if (v)
315: printf("%c", n);
316: else
317: printf(" ");
318: }
319:
320: dotext()
321: {
322: register struct text *xp;
323: int ntext;
324: struct text *xtext, *atext;
325: int ntx, ntxca;
326:
327: ntx = ntxca = 0;
328: ntext = getword(nl[SNTEXT].n_value);
329: xtext = (struct text *)calloc(ntext, sizeof (struct text));
330: atext = (struct text *)getword(nl[STEXT].n_value);
331: if (ntext < 0 || ntext > 10000) {
332: fprintf(stderr, "number of texts is preposterous (%d)\n",
333: ntext);
334: return;
335: }
336: if (xtext == NULL) {
337: fprintf(stderr, "can't allocate memory for text table\n");
338: return;
339: }
340: lseek(fc, mkphys((off_t)atext), 0);
341: read(fc, xtext, ntext * sizeof (struct text));
342: for (xp = xtext; xp < &xtext[ntext]; xp++) {
343: if (xp->x_iptr != NULL)
344: ntxca++;
345: if (xp->x_count != 0)
346: ntx++;
347: }
348: if (totflg) {
349: printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca);
350: return;
351: }
352: printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca);
353: printf("\
354: LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT FORW BACK\n");
355: for (xp = xtext; xp < &xtext[ntext]; xp++) {
356: if (xp->x_iptr == NULL)
357: continue;
358: printf("%8.1x", atext + (xp - xtext));
359: printf(" ");
360: putf(xp->x_flag&XPAGI, 'P');
361: putf(xp->x_flag&XTRC, 'T');
362: putf(xp->x_flag&XWRIT, 'W');
363: putf(xp->x_flag&XLOAD, 'L');
364: putf(xp->x_flag&XLOCK, 'K');
365: putf(xp->x_flag&XWANT, 'w');
366: printf("%5x", xp->x_daddr[0]);
367: printf("%10x", xp->x_caddr);
368: printf("%5d", xp->x_rssize);
369: printf("%5d", xp->x_size);
370: printf("%10.1x", xp->x_iptr);
371: printf("%5d", xp->x_count&0377);
372: printf("%5d", xp->x_ccount);
373: printf("%10x", xp->x_forw);
374: printf("%9x", xp->x_back);
375: printf("\n");
376: }
377: free(xtext);
378: }
379:
380: doproc()
381: {
382: struct proc *xproc, *aproc;
383: int nproc;
384: register struct proc *pp;
385: register loc, np;
386: struct pte apte;
387:
388: nproc = getword(nl[SNPROC].n_value);
389: xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
390: aproc = (struct proc *)getword(nl[SPROC].n_value);
391: if (nproc < 0 || nproc > 10000) {
392: fprintf(stderr, "number of procs is preposterous (%d)\n",
393: nproc);
394: return;
395: }
396: if (xproc == NULL) {
397: fprintf(stderr, "can't allocate memory for proc table\n");
398: return;
399: }
400: lseek(fc, mkphys((off_t)aproc), 0);
401: read(fc, xproc, nproc * sizeof (struct proc));
402: np = 0;
403: for (pp=xproc; pp < &xproc[nproc]; pp++)
404: if (pp->p_stat)
405: np++;
406: if (totflg) {
407: printf("%3d/%3d processes\n", np, nproc);
408: return;
409: }
410: printf("%d/%d processes\n", np, nproc);
411: printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n");
412: for (pp=xproc; pp<&xproc[nproc]; pp++) {
413: if (pp->p_stat==0 && allflg==0)
414: continue;
415: printf("%8x", aproc + (pp - xproc));
416: printf(" %2d", pp->p_stat);
417: printf(" %4x", pp->p_flag & 0xffff);
418: printf(" %4d", pp->p_poip);
419: printf(" %3d", pp->p_pri);
420: printf(" %8x", pp->p_sig);
421: printf(" %4d", pp->p_uid);
422: printf(" %3d", pp->p_slptime);
423: printf(" %3d", pp->p_time);
424: printf(" %4d", pp->p_cpu&0377);
425: printf(" %3d", pp->p_nice);
426: printf(" %6d", pp->p_pgrp);
427: printf(" %6d", pp->p_pid);
428: printf(" %6d", pp->p_ppid);
429: if (kflg)
430: pp->p_addr = (struct pte *)clear((int)pp->p_addr);
431: if (pp->p_flag & SLOAD) {
432: lseek(fc, (long)pp->p_addr, 0);
433: read(fc, &apte, sizeof(apte));
434: printf(" %8x", apte.pg_pfnum);
435: } else
436: printf(" %8x", pp->p_swaddr);
437: printf(" %4x", pp->p_rssize);
438: printf(" %4x", pp->p_swrss);
439: printf(" %5x", pp->p_dsize+pp->p_ssize);
440: printf(" %7x", clear(pp->p_wchan));
441: printf(" %7x", clear(pp->p_link));
442: printf(" %7x", clear(pp->p_textp));
443: printf("\n");
444: }
445: free(xproc);
446: }
447:
448: static char mesg[] =
449: " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n";
450: static int ttyspace = 128;
451: static struct tty *tty;
452:
453: dotty()
454: {
455: extern char *malloc();
456:
457: if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) {
458: printf("pstat: out of memory\n");
459: return;
460: }
461: printf("1 cons\n");
462: if (kflg)
463: nl[SCONS].n_value = clear(nl[SCONS].n_value);
464: lseek(fc, (long)nl[SCONS].n_value, 0);
465: read(fc, tty, sizeof(*tty));
466: printf(mesg);
467: ttyprt(&tty[0], 0);
468: #ifdef vax
469: if (nl[SNQD].n_type != 0)
470: doqdss();
471: if (nl[SNDZ].n_type != 0)
472: dottytype("dz", SDZ, SNDZ);
473: if (nl[SNDH].n_type != 0)
474: dottytype("dh", SDH, SNDH);
475: if (nl[SNDMF].n_type != 0)
476: dottytype("dmf", SDMF, SNDMF);
477: if (nl[SNDHU].n_type != 0)
478: dottytype("dhu", SDHU, SNDHU);
479: if (nl[SNDMZ].n_type != 0)
480: dottytype("dmz", SDMZ, SNDMZ);
481: #endif
482: #ifdef tahoe
483: if (nl[SNVX].n_type != 0)
484: dottytype("vx", SVX, SNVX);
485: if (nl[SNMP].n_type != 0)
486: dottytype("mp", SMP, SNMP);
487: #endif
488: if (nl[SNPTY].n_type != 0)
489: dottytype("pty", SPTY, SNPTY);
490: }
491:
492: /*
493: * Special case the qdss because there are 4 tty structs per qdss
494: * and only the first of each is used as a tty.
495: */
496: #ifdef vax
497: doqdss()
498: {
499: int nqd;
500: register struct tty *tp;
501:
502: if (kflg) {
503: nl[SNQD].n_value = clear(nl[SNQD].n_value);
504: nl[SQD].n_value = clear(nl[SQD].n_value);
505: }
506: lseek(fc, (long)nl[SNQD].n_value, 0);
507: read(fc, &nqd, sizeof(nqd));
508: printf("%d qd\n", nqd);
509: lseek(fc, (long)nl[SQD].n_value, 0);
510: read(fc, tty, nqd * sizeof(struct tty) * 4);
511: printf(mesg);
512: for (tp = tty; tp < &tty[nqd * 4]; tp += 4)
513: ttyprt(tp, tp - tty);
514: }
515: #endif
516:
517: dottytype(name, type, number)
518: char *name;
519: {
520: int ntty;
521: register struct tty *tp;
522: extern char *realloc();
523:
524: if (tty == (struct tty *)0)
525: return;
526: if (kflg) {
527: nl[number].n_value = clear(nl[number].n_value);
528: nl[type].n_value = clear(nl[type].n_value);
529: }
530: lseek(fc, (long)nl[number].n_value, 0);
531: read(fc, &ntty, sizeof(ntty));
532: printf("%d %s lines\n", ntty, name);
533: if (ntty > ttyspace) {
534: ttyspace = ntty;
535: if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) {
536: printf("pstat: out of memory\n");
537: return;
538: }
539: }
540: lseek(fc, (long)nl[type].n_value, 0);
541: read(fc, tty, ntty * sizeof(struct tty));
542: printf(mesg);
543: for (tp = tty; tp < &tty[ntty]; tp++)
544: ttyprt(tp, tp - tty);
545: }
546:
547: ttyprt(atp, line)
548: struct tty *atp;
549: {
550: register struct tty *tp;
551:
552: printf("%2d", line);
553: tp = atp;
554: switch (tp->t_line) {
555:
556: #ifdef notdef
557: case NETLDISC:
558: if (tp->t_rec)
559: printf("%4d%4d", 0, tp->t_inbuf);
560: else
561: printf("%4d%4d", tp->t_inbuf, 0);
562: break;
563: #endif
564:
565: default:
566: printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc);
567: }
568: printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags,
569: tp->t_addr, tp->t_delct, tp->t_col);
570: putf(tp->t_state&TS_TIMEOUT, 'T');
571: putf(tp->t_state&TS_WOPEN, 'W');
572: putf(tp->t_state&TS_ISOPEN, 'O');
573: putf(tp->t_state&TS_FLUSH, 'F');
574: putf(tp->t_state&TS_CARR_ON, 'C');
575: putf(tp->t_state&TS_BUSY, 'B');
576: putf(tp->t_state&TS_ASLEEP, 'A');
577: putf(tp->t_state&TS_XCLUDE, 'X');
578: putf(tp->t_state&TS_TTSTOP, 'S');
579: putf(tp->t_state&TS_HUPCLS, 'H');
580: printf("%6d", tp->t_pgrp);
581: switch (tp->t_line) {
582:
583: case OTTYDISC:
584: printf("\n");
585: break;
586:
587: case NTTYDISC:
588: printf(" ntty\n");
589: break;
590:
591: case NETLDISC:
592: printf(" berknet\n");
593: break;
594:
595: case TABLDISC:
596: printf(" tab\n");
597: break;
598:
599: case SLIPDISC:
600: printf(" slip\n");
601: break;
602:
603: default:
604: printf(" %d\n", tp->t_line);
605: }
606: }
607:
608: dousr()
609: {
610: struct user U;
611: register i, j, *ip;
612: register struct nameidata *nd = &U.u_nd;
613:
614: /* This wins only if CLBYTES >= sizeof (struct user) */
615: lseek(fm, ubase * NBPG, 0);
616: read(fm, &U, sizeof(U));
617: printf("pcb");
618: ip = (int *)&U.u_pcb;
619: while (ip < &U.u_arg[0]) {
620: if ((ip - (int *)&U.u_pcb) % 4 == 0)
621: printf("\t");
622: printf("%x ", *ip++);
623: if ((ip - (int *)&U.u_pcb) % 4 == 0)
624: printf("\n");
625: }
626: if ((ip - (int *)&U.u_pcb) % 4 != 0)
627: printf("\n");
628: printf("arg");
629: for (i=0; i<sizeof(U.u_arg)/sizeof(U.u_arg[0]); i++) {
630: if (i%5==0)
631: printf("\t");
632: printf(" %.1x", U.u_arg[i]);
633: if (i%5==4)
634: printf("\n");
635: }
636: if (i%5)
637: printf("\n");
638: printf("segflg\t%d\nerror %d\n", nd->ni_segflg, U.u_error);
639: printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid);
640: printf("procp\t%.1x\n", U.u_procp);
641: printf("ap\t%.1x\n", U.u_ap);
642: printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2);
643: printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base,
644: nd->ni_count, nd->ni_offset);
645: printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir);
646: printf("dirp %.1x\n", nd->ni_dirp);
647: printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name);
648: printf("pdir %.1o\n", nd->ni_pdir);
649: printf("file");
650: for (i=0; i<NOFILE; i++) {
651: if (i % 8 == 0)
652: printf("\t");
653: printf("%9.1x", U.u_ofile[i]);
654: if (i % 8 == 7)
655: printf("\n");
656: }
657: if (i % 8)
658: printf("\n");
659: printf("pofile");
660: for (i=0; i<NOFILE; i++) {
661: if (i % 8 == 0)
662: printf("\t");
663: printf("%9.1x", U.u_pofile[i]);
664: if (i % 8 == 7)
665: printf("\n");
666: }
667: if (i % 8)
668: printf("\n");
669: printf("ssave");
670: for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
671: if (i%5==0)
672: printf("\t");
673: printf("%9.1x", U.u_ssave.val[i]);
674: if (i%5==4)
675: printf("\n");
676: }
677: if (i%5)
678: printf("\n");
679: printf("sigs");
680: for (i=0; i<NSIG; i++) {
681: if (i % 8 == 0)
682: printf("\t");
683: printf("%.1x ", U.u_signal[i]);
684: if (i % 8 == 7)
685: printf("\n");
686: }
687: if (i % 8)
688: printf("\n");
689: printf("code\t%.1x\n", U.u_code);
690: printf("ar0\t%.1x\n", U.u_ar0);
691: printf("prof\t%x %x %x %x\n", U.u_prof.pr_base, U.u_prof.pr_size,
692: U.u_prof.pr_off, U.u_prof.pr_scale);
693: printf("\neosys\t%d\n", U.u_eosys);
694: printf("ttyp\t%.1x\n", U.u_ttyp);
695: printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd));
696: printf("comm %.14s\n", U.u_comm);
697: printf("start\t%ld\n", U.u_start.tv_sec);
698: printf("acflag\t%ld\n", U.u_acflag);
699: printf("cmask\t%ld\n", U.u_cmask);
700: printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize);
701: printf("ru\t");
702: ip = (int *)&U.u_ru;
703: for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++)
704: printf("%ld ", ip[i]);
705: printf("\n");
706: ip = (int *)&U.u_cru;
707: printf("cru\t");
708: for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++)
709: printf("%ld ", ip[i]);
710: printf("\n");
711: #ifdef notdef
712: i = U.u_stack - &U;
713: while (U[++i] == 0);
714: i &= ~07;
715: while (i < 512) {
716: printf("%x ", 0140000+2*i);
717: for (j=0; j<8; j++)
718: printf("%9x", U[i++]);
719: printf("\n");
720: }
721: #endif
722: }
723:
724: oatoi(s)
725: char *s;
726: {
727: register v;
728:
729: v = 0;
730: while (*s)
731: v = (v<<3) + *s++ - '0';
732: return(v);
733: }
734:
735: dofile()
736: {
737: int nfile;
738: struct file *xfile, *afile;
739: register struct file *fp;
740: register nf;
741: int loc;
742: static char *dtypes[] = { "???", "inode", "socket" };
743:
744: nf = 0;
745: nfile = getword(nl[SNFILE].n_value);
746: xfile = (struct file *)calloc(nfile, sizeof (struct file));
747: afile = (struct file *)getword(nl[SFIL].n_value);
748: if (nfile < 0 || nfile > 10000) {
749: fprintf(stderr, "number of files is preposterous (%d)\n",
750: nfile);
751: return;
752: }
753: if (xfile == NULL) {
754: fprintf(stderr, "can't allocate memory for file table\n");
755: return;
756: }
757: lseek(fc, mkphys((off_t)afile), 0);
758: read(fc, xfile, nfile * sizeof (struct file));
759: for (fp=xfile; fp < &xfile[nfile]; fp++)
760: if (fp->f_count)
761: nf++;
762: if (totflg) {
763: printf("%3d/%3d files\n", nf, nfile);
764: return;
765: }
766: printf("%d/%d open files\n", nf, nfile);
767: printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
768: for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
769: if (fp->f_count==0)
770: continue;
771: printf("%8x ", loc);
772: if (fp->f_type <= DTYPE_SOCKET)
773: printf("%-8.8s", dtypes[fp->f_type]);
774: else
775: printf("%8d", fp->f_type);
776: putf(fp->f_flag&FREAD, 'R');
777: putf(fp->f_flag&FWRITE, 'W');
778: putf(fp->f_flag&FAPPEND, 'A');
779: putf(fp->f_flag&FSHLOCK, 'S');
780: putf(fp->f_flag&FEXLOCK, 'X');
781: putf(fp->f_flag&FASYNC, 'I');
782: printf(" %3d", mask(fp->f_count));
783: printf(" %3d", mask(fp->f_msgcount));
784: printf(" %8.1x", fp->f_data);
785: if (fp->f_offset < 0)
786: printf(" %x\n", fp->f_offset);
787: else
788: printf(" %ld\n", fp->f_offset);
789: }
790: free(xfile);
791: }
792:
793: int dmmin, dmmax, nswdev;
794:
795: doswap()
796: {
797: struct proc *proc;
798: int nproc;
799: struct text *xtext;
800: int ntext;
801: struct map *swapmap;
802: int nswapmap;
803: struct swdevt *swdevt, *sw;
804: register struct proc *pp;
805: int nswap, used, tused, free, waste;
806: int db, sb;
807: register struct mapent *me;
808: register struct text *xp;
809: int i, j;
810: long rmalloc();
811:
812: nproc = getword(nl[SNPROC].n_value);
813: ntext = getword(nl[SNTEXT].n_value);
814: if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) {
815: fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n",
816: nproc, ntext);
817: return;
818: }
819: proc = (struct proc *)calloc(nproc, sizeof (struct proc));
820: if (proc == NULL) {
821: fprintf(stderr, "can't allocate memory for proc table\n");
822: exit(1);
823: }
824: xtext = (struct text *)calloc(ntext, sizeof (struct text));
825: if (xtext == NULL) {
826: fprintf(stderr, "can't allocate memory for text table\n");
827: exit(1);
828: }
829: nswapmap = getword(nl[SNSWAPMAP].n_value);
830: swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
831: if (swapmap == NULL) {
832: fprintf(stderr, "can't allocate memory for swapmap\n");
833: exit(1);
834: }
835: nswdev = getword(nl[SNSWDEV].n_value);
836: swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt));
837: if (swdevt == NULL) {
838: fprintf(stderr, "can't allocate memory for swdevt table\n");
839: exit(1);
840: }
841: lseek(fc, mkphys((off_t)nl[SSWDEVT].n_value), L_SET);
842: read(fc, swdevt, nswdev * sizeof (struct swdevt));
843: lseek(fc, mkphys((off_t)getword(nl[SPROC].n_value)), 0);
844: read(fc, proc, nproc * sizeof (struct proc));
845: lseek(fc, mkphys((off_t)getword(nl[STEXT].n_value)), 0);
846: read(fc, xtext, ntext * sizeof (struct text));
847: lseek(fc, mkphys((off_t)getword(nl[SWAPMAP].n_value)), 0);
848: read(fc, swapmap, nswapmap * sizeof (struct map));
849: swapmap->m_name = "swap";
850: swapmap->m_limit = (struct mapent *)&swapmap[nswapmap];
851: dmmin = getword(nl[SDMMIN].n_value);
852: dmmax = getword(nl[SDMMAX].n_value);
853: nswap = 0;
854: for (sw = swdevt; sw < &swdevt[nswdev]; sw++)
855: if (sw->sw_freed)
856: nswap += sw->sw_nblks;
857: free = 0;
858: for (me = (struct mapent *)(swapmap+1);
859: me < (struct mapent *)&swapmap[nswapmap]; me++)
860: free += me->m_size;
861: tused = 0;
862: for (xp = xtext; xp < &xtext[ntext]; xp++)
863: if (xp->x_iptr!=NULL) {
864: tused += ctod(clrnd(xp->x_size));
865: if (xp->x_flag & XPAGI)
866: tused += ctod(clrnd(ctopt(xp->x_size)));
867: }
868: used = tused;
869: waste = 0;
870: for (pp = proc; pp < &proc[nproc]; pp++) {
871: if (pp->p_stat == 0 || pp->p_stat == SZOMB)
872: continue;
873: if (pp->p_flag & SSYS)
874: continue;
875: db = ctod(pp->p_dsize), sb = up(db);
876: used += sb;
877: waste += sb - db;
878: db = ctod(pp->p_ssize), sb = up(db);
879: used += sb;
880: waste += sb - db;
881: if ((pp->p_flag&SLOAD) == 0)
882: used += ctod(vusize(pp));
883: }
884: if (totflg) {
885: #define btok(x) ((x) / (1024 / DEV_BSIZE))
886: printf("%3d/%3d 00k swap\n",
887: btok(used/100), btok((used+free)/100));
888: return;
889: }
890: printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
891: btok(used), btok(tused), btok(free), btok(waste),
892: /* a dmmax/2 block goes to argmap */
893: btok(nswap - dmmax/2 - (used + free)));
894: printf("avail: ");
895: for (i = dmmax; i >= dmmin; i /= 2) {
896: j = 0;
897: while (rmalloc(swapmap, i) != 0)
898: j++;
899: if (j) printf("%d*%dk ", j, btok(i));
900: }
901: free = 0;
902: for (me = (struct mapent *)(swapmap+1);
903: me < (struct mapent *)&swapmap[nswapmap]; me++)
904: free += me->m_size;
905: printf("%d*1k\n", btok(free));
906: }
907:
908: up(size)
909: register int size;
910: {
911: register int i, block;
912:
913: i = 0;
914: block = dmmin;
915: while (i < size) {
916: i += block;
917: if (block < dmmax)
918: block *= 2;
919: }
920: return (i);
921: }
922:
923: /*
924: * Compute number of pages to be allocated to the u. area
925: * and data and stack area page tables, which are stored on the
926: * disk immediately after the u. area.
927: */
928: vusize(p)
929: register struct proc *p;
930: {
931: register int tsz = p->p_tsize / NPTEPG;
932:
933: /*
934: * We do not need page table space on the disk for page
935: * table pages wholly containing text.
936: */
937: return (clrnd(UPAGES +
938: clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
939: }
940:
941: /*
942: * Allocate 'size' units from the given
943: * map. Return the base of the allocated space.
944: * In a map, the addresses are increasing and the
945: * list is terminated by a 0 size.
946: *
947: * Algorithm is first-fit.
948: *
949: * This routine knows about the interleaving of the swapmap
950: * and handles that.
951: */
952: long
953: rmalloc(mp, size)
954: register struct map *mp;
955: long size;
956: {
957: register struct mapent *ep = (struct mapent *)(mp+1);
958: register int addr;
959: register struct mapent *bp;
960: swblk_t first, rest;
961:
962: if (size <= 0 || size > dmmax)
963: return (0);
964: /*
965: * Search for a piece of the resource map which has enough
966: * free space to accomodate the request.
967: */
968: for (bp = ep; bp->m_size; bp++) {
969: if (bp->m_size >= size) {
970: /*
971: * If allocating from swapmap,
972: * then have to respect interleaving
973: * boundaries.
974: */
975: if (nswdev > 1 &&
976: (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
977: if (bp->m_size - first < size)
978: continue;
979: addr = bp->m_addr + first;
980: rest = bp->m_size - first - size;
981: bp->m_size = first;
982: if (rest)
983: rmfree(mp, rest, addr+size);
984: return (addr);
985: }
986: /*
987: * Allocate from the map.
988: * If there is no space left of the piece
989: * we allocated from, move the rest of
990: * the pieces to the left.
991: */
992: addr = bp->m_addr;
993: bp->m_addr += size;
994: if ((bp->m_size -= size) == 0) {
995: do {
996: bp++;
997: (bp-1)->m_addr = bp->m_addr;
998: } while ((bp-1)->m_size = bp->m_size);
999: }
1000: if (addr % CLSIZE)
1001: return (0);
1002: return (addr);
1003: }
1004: }
1005: return (0);
1006: }
1007:
1008: /*
1009: * Free the previously allocated space at addr
1010: * of size units into the specified map.
1011: * Sort addr into map and combine on
1012: * one or both ends if possible.
1013: */
1014: rmfree(mp, size, addr)
1015: struct map *mp;
1016: long size, addr;
1017: {
1018: struct mapent *firstbp;
1019: register struct mapent *bp;
1020: register int t;
1021:
1022: /*
1023: * Both address and size must be
1024: * positive, or the protocol has broken down.
1025: */
1026: if (addr <= 0 || size <= 0)
1027: goto badrmfree;
1028: /*
1029: * Locate the piece of the map which starts after the
1030: * returned space (or the end of the map).
1031: */
1032: firstbp = bp = (struct mapent *)(mp + 1);
1033: for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
1034: continue;
1035: /*
1036: * If the piece on the left abuts us,
1037: * then we should combine with it.
1038: */
1039: if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
1040: /*
1041: * Check no overlap (internal error).
1042: */
1043: if ((bp-1)->m_addr+(bp-1)->m_size > addr)
1044: goto badrmfree;
1045: /*
1046: * Add into piece on the left by increasing its size.
1047: */
1048: (bp-1)->m_size += size;
1049: /*
1050: * If the combined piece abuts the piece on
1051: * the right now, compress it in also,
1052: * by shifting the remaining pieces of the map over.
1053: */
1054: if (bp->m_addr && addr+size >= bp->m_addr) {
1055: if (addr+size > bp->m_addr)
1056: goto badrmfree;
1057: (bp-1)->m_size += bp->m_size;
1058: while (bp->m_size) {
1059: bp++;
1060: (bp-1)->m_addr = bp->m_addr;
1061: (bp-1)->m_size = bp->m_size;
1062: }
1063: }
1064: goto done;
1065: }
1066: /*
1067: * Don't abut on the left, check for abutting on
1068: * the right.
1069: */
1070: if (addr+size >= bp->m_addr && bp->m_size) {
1071: if (addr+size > bp->m_addr)
1072: goto badrmfree;
1073: bp->m_addr -= size;
1074: bp->m_size += size;
1075: goto done;
1076: }
1077: /*
1078: * Don't abut at all. Make a new entry
1079: * and check for map overflow.
1080: */
1081: do {
1082: t = bp->m_addr;
1083: bp->m_addr = addr;
1084: addr = t;
1085: t = bp->m_size;
1086: bp->m_size = size;
1087: bp++;
1088: } while (size = t);
1089: /*
1090: * Segment at bp is to be the delimiter;
1091: * If there is not room for it
1092: * then the table is too full
1093: * and we must discard something.
1094: */
1095: if (bp+1 > mp->m_limit) {
1096: /*
1097: * Back bp up to last available segment.
1098: * which contains a segment already and must
1099: * be made into the delimiter.
1100: * Discard second to last entry,
1101: * since it is presumably smaller than the last
1102: * and move the last entry back one.
1103: */
1104: bp--;
1105: printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
1106: (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
1107: bp[-1] = bp[0];
1108: bp[0].m_size = bp[0].m_addr = 0;
1109: }
1110: done:
1111: return;
1112: badrmfree:
1113: printf("bad rmfree\n");
1114: }
1115: /*
1116: * "addr" is a kern virt addr and does not correspond
1117: * To a phys addr after zipping out the high bit..
1118: * since it was valloc'd in the kernel.
1119: *
1120: * We return the phys addr by simulating kernel vm (/dev/kmem)
1121: * when we are reading a crash dump.
1122: */
1123: off_t
1124: mkphys(addr)
1125: off_t addr;
1126: {
1127: register off_t o;
1128:
1129: if (!kflg)
1130: return(addr);
1131: addr = clear(addr);
1132: o = addr & PGOFSET;
1133: addr >>= PGSHIFT;
1134: addr &= PG_PFNUM;
1135: addr *= NBPW;
1136: addr = getword(nl[SYSMAP].n_value + addr);
1137: addr = ((addr & PG_PFNUM) << PGSHIFT) | o;
1138: return(addr);
1139: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.