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