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