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