|
|
1.1 ! root 1: .\" Copyright (c) 1983 Regents of the University of California. ! 2: .\" All rights reserved. The Berkeley software License Agreement ! 3: .\" specifies the terms and conditions for redistribution. ! 4: .\" ! 5: .\" @(#)kdebug.ms 6.5 (Berkeley) 3/8/89 ! 6: .\" ! 7: .bd S B 3 ! 8: .de UX ! 9: .ie \\n(GA>0 \\$2UNIX\\$1 ! 10: .el \{\ ! 11: .if n \\$2UNIX\\$1* ! 12: .if t \\$2UNIX\\$1\\f1\(dg\\fP ! 13: .FS ! 14: .if n *UNIX ! 15: .if t \(dgUNIX ! 16: .ie \\$3=1 is a Footnote of Bell Laboratories. ! 17: .el is a Trademark of Bell Laboratories. ! 18: .FE ! 19: .nr GA 1\} ! 20: .. ! 21: .de cw ! 22: .nr >G \\n(.f \" save current font ! 23: .ft CW ! 24: .. ! 25: .de pw ! 26: .ft \\n(>G ! 27: .. ! 28: .TL ! 29: Using ADB to Debug the ! 30: .UX ! 31: Kernel ! 32: .AU ! 33: Samuel J. Leffler and William N. Joy ! 34: .AI ! 35: Computer Systems Research Group ! 36: Department of Electrical Engineering and Computer Science ! 37: University of California, Berkeley ! 38: Berkeley, California 94720 ! 39: .de IR ! 40: \fI\\$1\fP\\$2 ! 41: .. ! 42: .de DT ! 43: .TA 8 16 24 32 40 48 56 64 72 80 ! 44: .. ! 45: .AB ! 46: .PP ! 47: .FS ! 48: *DEC and VAX are trademarks of ! 49: Digital Equipment Corporation. ! 50: .FE ! 51: This document describes the facilities found in ! 52: the 4.3BSD version of the VAX* ! 53: .UX ! 54: debugger ! 55: .I adb ! 56: which may be used to debug the ! 57: .UX ! 58: kernel. ! 59: It discusses how standard ! 60: .I adb ! 61: commands may be used in examining the kernel and ! 62: introduces the basics necessary for users ! 63: to write ! 64: .I adb ! 65: command scripts which can augment the standard ! 66: .I adb ! 67: command set. The examination techniques described here ! 68: may be applied both to running systems and ! 69: the post-mortem dumps automatically created ! 70: by the ! 71: .IR savecore (8) ! 72: program after a system crash. ! 73: The reader is expected to have at least a ! 74: passing familiarity with the debugger command ! 75: language. ! 76: .sp ! 77: .LP ! 78: Revised March 8, 1989 ! 79: .AE ! 80: .LP ! 81: .OH 'Using ADB to Debug the Kernel''SMM:3-%' ! 82: .EH 'SMM:3-%''Using ADB to Debug the Kernel' ! 83: .ds RH Introduction ! 84: .LP ! 85: .ne 2i ! 86: .NH ! 87: Introduction ! 88: .PP ! 89: Modifications have been made to the ! 90: standard VAX ! 91: .UX ! 92: debugger ! 93: .I adb ! 94: to simplify ! 95: examination of post-mortem ! 96: dumps automatically generated following a system crash. ! 97: These changes may also be used when examining ! 98: .UX ! 99: in its normal operation. ! 100: This document serves as ! 101: an introduction to the ! 102: .B use ! 103: of these facilities, and ! 104: should not be construed as a description ! 105: of \fIhow to debug the kernel\fP. ! 106: .NH 2 ! 107: Invocation ! 108: .PP ! 109: When examining post-mortem dumps of the ! 110: .UX ! 111: kernel the ! 112: \fB\-k\fP option should be used, e.g. ! 113: .DS ! 114: .cw ! 115: % adb \-k vmunix.? vmcore.? ! 116: .pw ! 117: .DE ! 118: where the appropriate version of the saved operating system ! 119: image and core dump are supplied in place of ``?''. ! 120: This flag causes ! 121: .I adb ! 122: to partially simulate ! 123: the VAX virtual memory hardware when ! 124: accessing the ! 125: .I core ! 126: file. ! 127: In addition the internal state maintained ! 128: by the debugger is initialized from ! 129: data structures maintained by the ! 130: kernel explicitly for debugging\(dd. ! 131: A running kernel may be examined in a similar ! 132: fashion, ! 133: .DS ! 134: .cw ! 135: % adb \-k /vmunix /dev/mem ! 136: .pw ! 137: .DE ! 138: .FS ! 139: \(dd If the \-k flag is not used when invoking ! 140: .I adb ! 141: the user must explicitly calculate virtual ! 142: addresses. With the ! 143: .B \-k ! 144: option ! 145: .I adb ! 146: interprets page tables to automatically ! 147: perform virtual to physical address translation. ! 148: .FE ! 149: .NH 2 ! 150: Establishing Context ! 151: .PP ! 152: During initialization ! 153: .I adb ! 154: attempts to establish the ! 155: context of the ``currently active process'' by examining ! 156: the value of the kernel variable \fImasterpaddr\fP. ! 157: This variable contains the virtual address of the ! 158: process context block of the last process which ! 159: was set executing by the \fISwtch\fP routine. ! 160: \fIMasterpaddr\fP normally provides sufficient information ! 161: to locate the current stack frame (via the stack ! 162: pointers found in the context block). ! 163: By locating the process context block for the process ! 164: .I adb ! 165: may then perform virtual to ! 166: physical address translation using that process's ! 167: in-core page tables. ! 168: .PP ! 169: When examining post-mortem dumps locating the ! 170: most recent stack frame of the last ! 171: currently active process can be nontrivial. ! 172: This is due to the different ways in which ! 173: state may be saved after a nonrecoverable error. ! 174: Crashes may or may not be ``clean'' (i.e. ! 175: the top of the interrupt stack contains a pointer ! 176: to the process's ! 177: kernel mode stack pointer and program counter); ! 178: an ``unclean'' crash will occur, for instance, ! 179: if the interrupt stack overflows. When ! 180: .I adb ! 181: is invoked on a post-mortem crash dump it tries ! 182: to automatically establish the proper stack frame. ! 183: This is done by first checking the stack pointer ! 184: normally saved in the restart parameter ! 185: block at \fIrpb\fP+1fc (or \fIscb\fP\-4). If this ! 186: value does not point to a valid stack frame, ! 187: .I adb ! 188: searches the interrupt stack looking for a valid stack ! 189: frame. Should this also fail ! 190: .I adb ! 191: then searches the kernel ! 192: stack located in the user structure associated with ! 193: the last executing process. If ! 194: .I adb ! 195: is able to locate a valid stack frame using this procedure ! 196: the command ! 197: .DS ! 198: .cw ! 199: $c ! 200: .pw ! 201: .DE ! 202: will generate a stack trace from the last point at which ! 203: the kernel was executing on behalf of the user process ! 204: all the way ! 205: to the top of the user process's stack (e.g. to the ! 206: \fImain\fP routine in the user process). ! 207: Should ! 208: .I adb ! 209: be unable to locate a valid stack frame it prints a message ! 210: and the current state is left undefined. ! 211: When a stack trace of a particular process (other than that ! 212: which was currently executing) is desired, an ! 213: alternate method, described in \(sc2.4, should be used. ! 214: .PP ! 215: Additional information may be obtained from the kernel stack. ! 216: Discussion of that subject is postponed until command scripts ! 217: have been introduced; see \(sc2.2. ! 218: .ds RH "Command Scripts ! 219: .ne 2i ! 220: .NH ! 221: Command Scripts ! 222: .NH 2 ! 223: Extending the Formatting Facilities ! 224: .PP ! 225: Once the process context has been established, the ! 226: complete ! 227: .I adb ! 228: command set is available for interpreting ! 229: data structures. In addition, a number of ! 230: .I adb ! 231: scripts have ! 232: been created to simplify the structured printing of commonly ! 233: referenced kernel data structures. The scripts normally ! 234: reside in ! 235: the directory \fI/usr/lib/adb\fP, and are invoked ! 236: with the ``$<'' operator. ! 237: (A later table lists the standard scripts ! 238: distributed with the system.) ! 239: .PP ! 240: As an example, consider the following listing which ! 241: contains a dump of a faulty process's state ! 242: (our typing is shown emboldened). ! 243: .ID ! 244: .DT ! 245: .cw ! 246: % \fBadb \-k vmunix.175 vmcore.175\fP ! 247: sbr 5868 slr 2770 ! 248: p0br 5a00 p0lr 236 p1br 6600 p1lr fff0 ! 249: panic: dup biodone ! 250: \fB$c\fP ! 251: _boot() from _boot+f3 ! 252: _boot(0,0) from _panic+3a ! 253: _panic(800413d0) from _biodone+17 ! 254: _biodone(800791e8) from _rxpurge+23 ! 255: _rxpurge(80044754) from _rxstart+5a ! 256: _rxstart(80044754) from 80031df8 ! 257: _rxintr(0) from _Xrxintr0+11 ! 258: _Xrxintr0(45b01,3aaf4) from 457f ! 259: _Syssize(3aaf4) from 365a ! 260: _Syssize() from 19a8 ! 261: ?() from 2ff3 ! 262: _Syssize(4,7fffe834) from 9cf3 ! 263: _Syssize(4,7fffe834,7fffe848) from 37 ! 264: ?() ! 265: \fBu$<u\fP ! 266: _u: ! 267: _u: ksp usp ! 268: 7fffff94 7fffe24c ! 269: r0 r1 r2 r3 ! 270: 12e000 80044e60 800661bc 15fd1 ! 271: r4 r5 r6 r7 ! 272: 13 4 80065114 16544 ! 273: r8 r9 r10 r11 ! 274: a0 80066de8 15a08 80000000 ! 275: ap fp pc psl ! 276: 7fffffe8 7fffffa4 80029ed2 180000 ! 277: p0br p0lr p1br p1lr ! 278: 802f5a00 4000236 7faf6600 1ffff0 ! 279: szpt cmap2 sswap ! 280: 6 94000e59 0 ! 281: _u+80: procp ar0 comm ! 282: 80066de8 80000000 ccom^@^@^@^@^@^@^@^@^@^@^@^@ ! 283: _u+9c: arg0 arg1 arg2 ! 284: 46bfc 3aefc 0 ! 285: _u+bc: uap qsave ! 286: 7fffec9c 7fffffa4 8002a11a ! 287: _u+f8: rv1 rv2 error eosys ! 288: 0 3aafa 0 03 ! 289: 7fffed02: uid ruid gid rgid ! 290: 2025 2025 10 10 ! 291: 7fffed0a: groups ! 292: 10 0 2 3 11 79 -1 -1 ! 293: -1 -1 -1 -1 -1 -1 -1 -1 ! 294: ! 295: 7fffed2c: tsize dsize ssize ! 296: aa 18c 6 ! 297: 7fffeff0: odsize ossize outime ! 298: 52 40 0 ! 299: 7fffeffc: signal ! 300: 0 0 0 0 ! 301: 0 0 0 0 ! 302: 7a10 0 0 0 ! 303: 0 0 0 0 ! 304: 0 0 0 0 ! 305: 0 0 0 0 ! 306: 0 0 0 0 ! 307: 0 0 0 0 ! 308: sigmask ! 309: 0 4000 0 0 ! 310: 0 0 0 0 ! 311: 0 0 0 0 ! 312: 0 0 0 1 ! 313: 0 0 0 0 ! 314: 0 0 0 0 ! 315: 0 0 0 0 ! 316: 0 0 0 0 ! 317: 7ffff0fc: onstack sigintr oldmask ! 318: 0 0 80002 ! 319: 7ffff108: code sigstack onsigstack ! 320: 0 0 0 ! 321: 7ffff114: ofile ! 322: 80063e40 80063e58 80064ce0 0 ! 323: 0 0 0 0 ! 324: 0 0 0 0 ! 325: 0 0 0 0 ! 326: 0 0 0 0 ! 327: 0 0 0 0 ! 328: 0 0 0 0 ! 329: 0 0 0 0 ! 330: 0 0 0 0 ! 331: 0 0 0 0 ! 332: 0 0 0 0 ! 333: 0 0 0 0 ! 334: 0 0 0 0 ! 335: 0 0 0 0 ! 336: 0 0 0 0 ! 337: 0 0 0 0 ! 338: ! 339: pofile ! 340: 0 0 0 0 0 0 0 0 ! 341: 0 0 0 0 0 0 0 0 ! 342: 0 0 0 0 0 0 0 0 ! 343: 0 0 0 0 0 0 0 0 ! 344: 0 0 0 0 0 0 0 0 ! 345: 0 0 0 0 0 0 0 0 ! 346: 0 0 0 0 0 0 0 0 ! 347: 0 0 0 0 0 0 0 0 ! 348: 7ffff254: lastfile ! 349: 2 ! 350: 7ffff258: cdir rdir ttyp ttyd cmask ! 351: 80060f80 0 80056be8 106 02 ! 352: ! 353: ru ! 354: 7ffff268: utime stime ! 355: 1 15f90 1 cf850 ! 356: 7ffff278: maxrss ixrss idrss isrss ! 357: 432 28250 79590 0 ! 358: 7ffff288: minflt majflt nswap ! 359: 64 7 0 ! 360: 7ffff294: inblock oublock msgsnd msgrcv ! 361: 12 19 0 0 ! 362: 7ffff2a4: nsignals nvcsw nivcsw ! 363: 0 12 22 ! 364: 7ffff2b0: cru ! 365: 7ffff2b0: utime stime ! 366: 0 0 0 0 ! 367: 7ffff2c0: maxrss ixrss idrss isrss ! 368: 0 0 0 0 ! 369: 7ffff2d0: minflt majflt nswap ! 370: 0 0 0 ! 371: 7ffff2dc: inblock oublock msgsnd msgrcv ! 372: 0 0 0 0 ! 373: 7ffff2ec: nsignals nvcsw nivcsw ! 374: 0 0 0 ! 375: 7ffff2f8: itimers ! 376: 0 0 0 0 ! 377: 0 0 0 0 ! 378: 0 0 0 0 ! 379: 7ffff328: XXX ! 380: 0 0 0 ! 381: 7ffff334: start acflag ! 382: 1985 Nov 1 21:27:18 0 ! 383: 7ffff340: pr_base pr_size pr_off scale ! 384: 0 0 0 0 ! 385: 7ffff350: limits ! 386: 7fffffff 7fffffff 7fffffff 7fffffff ! 387: 600000 1000000 80000 1000000 ! 388: 7fffffff 7fffffff 123000 123000 ! 389: 7ffff380: quota qflags ! 390: 80074a18 0 ! 391: 7ffff388: nc_off nc_inum nc_dev nc_time ! 392: 284 2 8 1985 Nov 1 21:27:19 ! 393: 7ffff398: ni_dirp nameiop ni_err ni_pdir ni_bp ! 394: 7fffe8a8 41 0 200 800606c4 ! 395: 7ffff3a8: ni_base ni_count ni_iovec ni_iovcnt ! 396: 0 92 7ffff3a8 1 ! 397: 7ffff3b8: ni_offset ni_segflg ni_resid ! 398: 284 0 0 ! 399: 7ffff3c4: ni_dent.d_inum reclen namlen name ! 400: 19 72 9 ctm110435^@c^@^@^@ ! 401: \fB80066de8$<proc\fP ! 402: 80066de8: link rlink next prev ! 403: 80044e50 0 80067dec 8004e198 ! 404: ! 405: 80066df8: addr upri pri cpu stat time ! 406: 802f65d8 0150 0150 0330 03 04 ! 407: 80066e01: nice slp cursig sig ! 408: 0 0 0 0 ! 409: 80066e08: mask ignore catch ! 410: 0 0 80 ! 411: 80066e14: flag uid pgrp pid ppid ! 412: 1008001 2025 11019 11045 11043 ! 413: 80066e20: xstat ru poip szpt tsize ! 414: 0 0 0 6 aa ! 415: 80066e30: dsize ssize rssize maxrss ! 416: 18c 6 13c 918 ! 417: 80066e40: swrss swaddr wchan textp ! 418: 0 6d8 0 8006b400 ! 419: 80066e50: p0br xlink ticks ! 420: 802f5a00 0 0 ! 421: 80066e5c: %cpu ndx idhash pptr ! 422: +0.0000000000000000e+00 3ea4 106a 2e ! 423: 80066e68: cptr osptr ysptr ! 424: 80067dec 0 0 ! 425: 80066e74: real itimer ! 426: 0 0 0 0 ! 427: 80066e84: quota 0 ! 428: \fB8006b400$<text\fP ! 429: 8006b400: forw back ! 430: 1f30 0 ! 431: daddr ! 432: 0 0 0 0 ! 433: 0 0 0 0 ! 434: 0 0 2c2 aa ! 435: ! 436: ptdaddr size caddr iptr ! 437: 80066de8 8005f4a0 74 10001 ! 438: ! 439: rssize swrss count ccount flag slptim poip ! 440: 22 0 0100 031 0 0 0 ! 441: .pw ! 442: .DE ! 443: The cause of the crash was a ``panic'' ! 444: (see the stack trace) due to an inconsistency recognized ! 445: inside the \fIbiodone\fP routine. The majority ! 446: of the dump was done to illustrate the use of two command ! 447: scripts used to format kernel data structures. The ``u'' ! 448: script, invoked with the command ``u$<u'', is a lengthy series ! 449: of commands which pretty-prints the user structure. Likewise, ! 450: ``proc'' and ``text'' are scripts used to format the obvious ! 451: data structures. Let's quickly examine the ``text'' script (the ! 452: script has been broken into a number of lines for convenience ! 453: here; in actuality it is a single line of text). ! 454: .DS ! 455: .cw ! 456: \&./"forw"16t"back"n2Xn\e ! 457: "daddr"n12Xn\e ! 458: "ptdaddr"16t"size"16t"caddr"16t"iptr"n4Xn\e ! 459: "rssize"8t"swrss"8t"count"8t"ccount"8t"flag"8t"slptim"8t"poip"n2x4bx++n ! 460: .pw ! 461: .DE ! 462: The first line displays the pointers associated with the doubly ! 463: linked list used in managing text segments. ! 464: The second line produces the list of disk block addresses associated ! 465: with a swapped out text segment. The ``n'' format forces a new-line ! 466: character, with 12 hexadecimal integers printed immediately after. ! 467: Likewise, the remaining two lines of the command format the remainder ! 468: of the text structure. The expression ``16t'' causes ! 469: .I adb ! 470: to tab ! 471: to the next column which is a multiple of 16. ! 472: The last two plus operators are present ! 473: to round ``.'' to the end of the text structure. This allows the ! 474: user to reinvoke the format on consecutive text structures without ! 475: having to be concerned about proper alignment of ``.''. ! 476: .PP ! 477: The majority of the scripts provided are of this nature. ! 478: When possible, the formatting scripts print a data structure ! 479: with a single format to allow subsequent reuse when interrogating ! 480: arrays of structures. That is, the previous script could have ! 481: been written ! 482: .DS ! 483: .cw ! 484: \&./"forw"16t"back"n2Xn ! 485: +/"daddr"n12Xn ! 486: +/"ptdaddr"16t"size"16t"caddr"16t"iptr"n4Xn ! 487: +/"rssize"8t"swrss"8t"count"8t"ccount"8t"flag"8t"slptim"8t"poip"n2x4bx++n ! 488: .pw ! 489: .DE ! 490: but then reuse of the format would have invoked only the last ! 491: line of the format. ! 492: .NH 2 ! 493: Locating stack frames ! 494: .PP ! 495: It is frequently desirable to locate stack frames ! 496: in order to examine local and register variables. ! 497: In particular, frames created by a trap include saved values ! 498: of all registers and the trap context, and all registers are saved ! 499: upon a panic as well. ! 500: Two scripts are provided for tracing stack frames. ! 501: The first is capable of tracing through multiple frames, ! 502: printing the information common to each. ! 503: The second prints all of the information available ! 504: in the stack frame after a trap. ! 505: The following example illustrates their use. ! 506: .ID ! 507: .DT ! 508: .cw ! 509: % \fBadb -k vmunix.188 vmcore.188\fP ! 510: sbr 7068 slr 2770 ! 511: p0br 5a00 p0lr 74 p1br 5e00 p1lr fff0 ! 512: panic: Segmentation fault ! 513: \fB$c\fP ! 514: _boot() from 80029ddb ! 515: _boot(0,0) from _panic+3a ! 516: _panic(800447a8) from _trap+ac ! 517: _trap() from _Xtransflt+1d ! 518: _Xtransflt() from _Xsyscall+c ! 519: _Xsyscall(7fffe7ac,1b6) from 514 ! 520: ?(7fffe7ac) from 4ac ! 521: ?() from 196 ! 522: ?(2,7fffe810,7fffe81c) from 3d ! 523: ?() ! 524: \fB1000$s\fP ! 525: \fB*(rpb+1fc),4$<frame\fP ! 526: 7ffffe74: handler psr mask ! 527: 0 0 2101 ! 528: ap fp pc ! 529: 7ffffec0 7ffffe9c 80029ddb _boot+103 ! 530: ! 531: 7ffffe9c: handler psr mask ! 532: 0 0 2f00 ! 533: ap fp pc ! 534: 7fffff14 7ffffed0 80012de2 _panic+3a ! 535: ! 536: 7ffffed0: handler psr mask ! 537: 0 0 2fff ! 538: ap fp pc ! 539: 7fffff70 7fffff2c 8002a408 _trap+ac ! 540: ! 541: 7fffff2c: handler psr mask ! 542: 0 0 2fff ! 543: ap fp pc ! 544: 7fffffe8 7fffffa4 80001031 _Xtransflt+1d ! 545: ! 546: \fB<1$<trapframe\fP ! 547: 7fffff2c: handler psr mask ! 548: 0 0 2fff ! 549: ap fp pc ! 550: 7fffffe8 7fffffa4 80001031 _Xtransflt+1d ! 551: r0 r1 r2 r3 ! 552: 0 80046988 80046a00 800728db ! 553: r4 r5 r6 r7 ! 554: 800728b0 80054158 80063a60 80066ee0 ! 555: r8 r9 r10 r11 ! 556: 80041b80 8 7fffe578 80000000 ! 557: 7fffff70: nargs sp type code ! 558: 0 7fffe560 8 2a50b6ca ! 559: pc (pc) ps ! 560: 80001651 _Swtch+2b d80008 ! 561: \fB80001651?i\fP ! 562: _Swtch+2b: remque *0(r1),r2 ! 563: \fB80046988/X\fP ! 564: _qs: ! 565: _qs: 2a50b6ca ! 566: .pw ! 567: .DE ! 568: .PP ! 569: The example shows a panic due to a segmentation fault. ! 570: The command ``1000$s'' expands the range over which addresses will be ! 571: displayed symbolically. ! 572: The back trace indicates that the trap occurred four frames ! 573: from the end; ! 574: as the frame pointer is stored at \fIrpb\fP+1fc, the command ! 575: ``*(rpb+1fc),4$<frame'' prints the last four stack frames; ! 576: ``*(rpb+1fc)'' is the initial frame pointer, and the count determines the number ! 577: of frames to print. ! 578: Having located the stack frame after the trap (the frame with a return PC ! 579: of Xtransflt+1d), that frame may be displayed again using the script ! 580: for a trap frame. ! 581: The previous frame pointer was left in register 1 by the previous script, ! 582: and thus ``<1$<trapframe'' displays the state at the time of the trap. ! 583: The PC at the time of the fault is shown on the last line from the script, ! 584: with the faulting address listed as the code in the previous line. ! 585: The instruction that caused the fault can then be examined. ! 586: In this example, the instruction was a remque that used a displacement ! 587: addressing mode indirecting through R1. ! 588: The location to which the register points is the first of the process ! 589: run queues, and its first element can be seen to be corrupted; ! 590: its forward pointer, 2a50b6ca, is invalid and is the address that caused ! 591: the fault. ! 592: .NH 2 ! 593: Traversing Data Structures ! 594: .PP ! 595: The ! 596: .I adb ! 597: command language can be used to traverse complex data ! 598: structures. One data structure, a linked list, occurs ! 599: quite often in the kernel. By using ! 600: .I adb ! 601: variables and the ! 602: normal expression operators it is a simple matter to construct ! 603: a script which chains down a list printing each element ! 604: along the way. ! 605: .PP ! 606: For instance, the queue of processes awaiting timer events, ! 607: the callout queue, is printed with the following two scripts: ! 608: .ID ! 609: .cw ! 610: .in +5 ! 611: .ne 3 ! 612: .ti -5 ! 613: \fBcallout\fP: ! 614: calltodo/"time"16t"arg"16t"func"12+ ! 615: *+$<callout.next ! 616: .sp 1 ! 617: .ne 6 ! 618: .ti -5 ! 619: \fBcallout.next\fP: ! 620: \&./Dpp ! 621: *+>l ! 622: ,#<l$< ! 623: <l$<callout.next ! 624: .in -5 ! 625: .pw ! 626: .DE ! 627: The first line of the script \fBcallout\fP starts the traversal ! 628: at the global symbol ! 629: \fIcalltodo\fP and prints a set of headings. ! 630: It then skips the empty portion of the structure used ! 631: as the head of the queue. ! 632: The second line then invokes the script \fBcallout.next\fP ! 633: moving ``.'' to ! 634: the top of the queue (``*+'' performs the indirection ! 635: through the link entry of the structure at the head of the queue). ! 636: .PP ! 637: \fBcallout.next\fP prints values for each column, then performs ! 638: a conditional test on the link to the next entry. This test ! 639: is performed as follows, ! 640: .IP "*+>l" 9 ! 641: Place the value of the ``link'' in the ! 642: .I adb ! 643: variable ``<l''. ! 644: .IP ",#<l$<" ! 645: If the value stored in ``<l'' is non-zero, then the current ! 646: input stream (i.e. the script \fBcallout.next\fP) is terminated. ! 647: Otherwise, the expression ``#<l'' will be zero, and the ``$<'' ! 648: will be ignored. That is, the combination of the logical negation ! 649: operator ``#'', the ! 650: .I adb ! 651: variable ``<l'', and the ``$<'' operator ! 652: creates a statement of the form, ! 653: .DS ! 654: .cw ! 655: if (!link) exit; ! 656: .pw ! 657: .DE ! 658: The remaining line of \fBcallout.next\fP simply reapplies the ! 659: script on the next element in the linked list. ! 660: .LP ! 661: A sample \fIcallout\fP dump is shown below. ! 662: .ID ! 663: .cw ! 664: % \fBadb \-k /vmunix /dev/mem\fP ! 665: sbr 8001f864 slr d9c ! 666: p0br 800efa00 p0lr 8e p1br 7f8efe00 p1lr 1ffff2 ! 667: \fB$<callout\fP ! 668: _calltodo: ! 669: _calltodo: time arg func ! 670: 8004ecfc: 26 0 _dzscan ! 671: 8004ed0c: 8 0 _upwatch ! 672: 8004ed1c: 0 0 _ip_timeo ! 673: 8004ed5c: 0 0 _tcp_timeo ! 674: 8004ed6c: 0 0 _rkwatch ! 675: 8004ecfc: 52 0 _dzscan ! 676: 8004ed2c: 68 _Syssize+70 _tmtimer ! 677: 8004ed3c: 2920 0 _memenable ! 678: .pw ! 679: .DE ! 680: .NH 2 ! 681: Supplying Parameters ! 682: .PP ! 683: If one is clever, a command script may use the address ! 684: and count portions of an ! 685: .I adb ! 686: command as parameters. An example of ! 687: this is the \fBsetproc\fP script used to switch to the ! 688: context of a process with a known process-id: ! 689: .DS ! 690: .cw ! 691: 0t99$<setproc ! 692: .pw ! 693: .DE ! 694: The body of \fBsetproc\fP is ! 695: .DS ! 696: .cw ! 697: \&.>4 ! 698: *nproc>l ! 699: *proc>f ! 700: $<setproc.nxt ! 701: .pw ! 702: .DE ! 703: while \fBsetproc.nxt\fP is ! 704: .DS ! 705: .cw ! 706: (*(<f+0t52))&0xffff="pid "D ! 707: ,#((*(<f+0t52)&0xffff)-<4)$<setproc.done ! 708: <l-1>l ! 709: <f+0t164>f ! 710: ,#<l$< ! 711: $<setproc.nxt ! 712: .pw ! 713: .DE ! 714: The process-id, supplied as the parameter, is stored in the ! 715: variable ``<4'', the number of processes is placed in ``<l'', ! 716: and the base of the array of process structures in ``<f''. ! 717: \fBsetproc.nxt\fP then performs a linear search through the ! 718: array until it matches the process-id requested, or until ! 719: it runs out of process structures to check. The script ! 720: \fBsetproc.done\fP simply establishes the context of the ! 721: process, then exits. ! 722: .NH 2 ! 723: Standard Scripts ! 724: .PP ! 725: The following table summarizes the command scripts supplied ! 726: with 4.3BSD; these scripts are found in the directory \fI/usr/lib/adb\fP. ! 727: .TS H ! 728: center, box; ! 729: c s s ! 730: l | l | l ! 731: lb | l | l. ! 732: Standard Command Scripts ! 733: _ ! 734: Name Use Description ! 735: _ ! 736: .TH ! 737: buf \fIaddr\fP$<\fBbuf\fP format block I/O buffer ! 738: callout $<\fBcallout\fP print timer queue ! 739: clist \fIaddr\fP$<\fBclist\fP format character I/O linked list ! 740: dino \fIaddr\fP$<\fBdino\fP format directory inode ! 741: dir \fIaddr\fP$<\fBdir\fP format directory entry ! 742: dirblk \fIaddr\fP$<\fBdirblk\fP scan directory entries ! 743: dmap \fIaddr\fP$<\fBdmap\fP format a disk-map structure ! 744: dmcstats $<\fBdmcstats\fP dump statistics for dmc0 ! 745: file \fIaddr\fP$<\fBfile\fP format open file structure ! 746: filsys \fIaddr\fP$<\fBfilsys\fP format in-core super block structure ! 747: findinode \fIinum\fP$<\fBfindinode\fP find an inode in the in-core inode table ! 748: findproc \fIpid\fP$<\fBfindproc\fP find process by process id ! 749: frame \fIaddr\fP,\fIcount\fP$<\fBframe\fP trace \fIcount\fP stack frames starting at \fIaddr\fP ! 750: hosts \fIaddr\fP$<\fBhosts\fP format IMP host table entries ! 751: hosttable \fIaddr\fP$<\fBhosttable\fP show all IMP host table entries ! 752: ifaddr \fIaddr\fP$<\fBifaddr\fP format a network interface address structure ! 753: ifnet \fIaddr\fP$<\fBifnet\fP format network interface structure ! 754: ifuba \fIaddr\fP$<\fBifuba\fP format UNIBUS resource structure ! 755: imp \fIaddr\fP$<\fBimp\fP format an IMP interface state structure ! 756: in_ifaddr \fIaddr\fP$<\fBin_ifaddr\fP format internet network addresses for an interface ! 757: inode \fIaddr\fP$<\fBinode\fP format in-core inode structure ! 758: inpcb \fIaddr\fP$<\fBinpcb\fP format internet protocol control block ! 759: iovec \fIaddr\fP$<\fBiovec\fP format a list of \fIiov\fP structures ! 760: ipreass \fIaddr\fP$<\fBipreass\fP format an ip reassembly queue ! 761: mact \fIaddr\fP$<\fBmact\fP show ``active'' list of mbuf's ! 762: mba_device \fIaddr\fP$<\fBmba_device\fP format an MBA device structure ! 763: mba_hd \fIaddr\fP$<\fBmba_hd\fP format an MBA queue head ! 764: mbstat $<\fBmbstat\fP show mbuf statistics ! 765: mbuf \fIaddr\fP$<\fBmbuf\fP show ``next'' list of mbuf's ! 766: mbufchain \fIaddr\fP$<\fBmbufchain\fP display a chain of mbufs queued at a socket ! 767: mbufs \fIaddr\fP$<\fBmbufs\fP show a number of mbuf's ! 768: mount \fIaddr\fP$<\fBmount\fP format mount structure ! 769: nameidata \fIaddr\fP$<\fBnameidata\fP format a namei parameter block ! 770: packetchain \fIaddr\fP$<\fBpacketchain\fP format a chain of packets ! 771: pcb \fIaddr\fP$<\fBpcb\fP format process context block ! 772: proc \fIaddr\fP$<\fBproc\fP format process table entry ! 773: protosw \fIaddr\fP$<\fBprotosw\fP format a protocol switch entry ! 774: quota \fIaddr\fP$<\fBquota\fP format a disk quota structure ! 775: rawcb \fIaddr\fP$<\fBrawcb\fP format a raw protocol control block ! 776: rtentry \fIaddr\fP$<\fBrtentry\fP format a routing table entry ! 777: rusage \fIaddr\fP$<\fBrusage\fP format a resource usage structure ! 778: setproc \fIpid\fP$<\fBsetproc\fP switch process context to \fIpid\fP ! 779: socket \fIaddr\fP$<\fBsocket\fP format socket structure ! 780: stat \fIaddr\fP$<\fBstat\fP format a stat structure ! 781: tcpcb \fIaddr\fP$<\fBtcpcb\fP format TCP control block ! 782: tcpip \fIaddr\fP$<\fBtcpip\fP format a TCP/IP packet header ! 783: tcpreass \fIaddr\fP$<\fBtcpreass\fP show a TCP reassembly queue ! 784: text \fIaddr\fP$<\fBtext\fP format text structure ! 785: traceall $<\fBtraceall\fP show stack trace for all processes ! 786: trapframe \fIaddr\fP$<\fBtrapframe\fP format a stack frame generated by a trap ! 787: tty \fIaddr\fP$<\fBtty\fP format tty structure ! 788: u \fIaddr\fP$<\fBu\fP format user vector, including pcb ! 789: ubadev \fIaddr\fP$<\fBubadev\fP format a UBA device structure ! 790: ubahd \fIaddr\fP$<\fBubahd\fP format a UNIBUS header structure ! 791: unpcb \fIaddr\fP$<\fBunpcb\fP format a UNIX domain protocol control block ! 792: .TE ! 793: .ds RH "Summary ! 794: .NH ! 795: Summary ! 796: .PP ! 797: The extensions made to ! 798: .I adb ! 799: provide basic support for debugging the ! 800: .UX ! 801: kernel by eliminating the need for a user to carry ! 802: out virtual to physical address translation and by automatically ! 803: locating the stack frame after a system crash. A collection ! 804: of scripts have been written to format the major ! 805: kernel data structures and aid in switching between ! 806: process contexts. These facilities have been implemented with ! 807: only minimal changes to the debugger. While the symbolic debugger ! 808: .I dbx ! 809: provides facilities similar to those described here it is ! 810: not yet a viable alternative to ! 811: .I adb ! 812: because ! 813: .I dbx ! 814: takes too long to read in the symbol table. As soon as ! 815: this problem is corrected there will be only limited need for ! 816: the facilities provided by \fIadb\fP.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.