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