|
|
1.1 ! root 1: .po .5i ! 2: .bd S B 3 ! 3: .de UX ! 4: .ie \\n(GA>0 \\$2UNIX\\$1 ! 5: .el \{\ ! 6: .if n \\$2UNIX\\$1* ! 7: .if t \\$2UNIX\\$1\\f1\(dg\\fP ! 8: .FS ! 9: .if n *UNIX ! 10: .if t \(dgUNIX ! 11: .ie \\$3=1 is a Footnote of Bell Laboratories. ! 12: .el is a Trademark of Bell Laboratories. ! 13: .FE ! 14: .nr GA 1\} ! 15: .. ! 16: .TL ! 17: Using ADB to Debug the ! 18: .UX ! 19: Kernel ! 20: .AU ! 21: Samuel J. Leffler ! 22: .AU ! 23: William N. Joy ! 24: .AI ! 25: Computer Systems Research Group ! 26: Department of Electrical Engineering and Computer Science ! 27: University of California, Berkeley ! 28: Berkeley, California 94720 ! 29: (415) 642-7780 ! 30: .de IR ! 31: \fI\\$1\fP\\$2 ! 32: .. ! 33: .de DT ! 34: .TA 8 16 24 32 40 48 56 64 72 80 ! 35: .. ! 36: .AB ! 37: .PP ! 38: .FS ! 39: *DEC and VAX are trademarks of ! 40: Digital Equipment Corporation. ! 41: .FE ! 42: This document describes the use of extensions made ! 43: to the 4.1bsd release of the VAX* ! 44: .UX ! 45: debugger adb for the purpose of debugging the ! 46: .UX ! 47: kernel. ! 48: It discusses the changes made to allow ! 49: standard adb commands to ! 50: function properly with the kernel and ! 51: introduces the basics necessary for users ! 52: to write adb command scripts which ! 53: may be used to augment the standard adb ! 54: command set. The examination techniques described here ! 55: may be applied to running systems, as well as ! 56: the post-mortem dumps automatically created ! 57: by the ! 58: .IR savecore (8) ! 59: program after a system crash. ! 60: The reader is expected to have at least a ! 61: passing familiarity with the debugger command ! 62: language. ! 63: .AE ! 64: .ds LH "Using ADB on the UNIX Kernel ! 65: .ds RH Introduction ! 66: .ds CF \*(DY ! 67: .LP ! 68: .nr H1 1 ! 69: .ds CH " ! 70: .bp ! 71: .nr % 1 ! 72: .ds CH "\(hy \\n(PN \(hy ! 73: .LG ! 74: .B ! 75: .ce ! 76: 1. INTRODUCTION ! 77: .sp 2 ! 78: .R ! 79: .NL ! 80: .PP ! 81: Modifications have been made to the ! 82: standard VAX ! 83: .UX ! 84: debugger adb to simplify ! 85: examination of post-mortem ! 86: dumps automatically generated following a system crash. ! 87: These changes may also be used when examining ! 88: .UX ! 89: in its normal operation. ! 90: This document serves as ! 91: an introduction to the \fBuse\fP of ! 92: these facilities, and ! 93: should not be construed as a description ! 94: of \fIhow to debug the kernel\fP. ! 95: .NH 2 ! 96: Invocation ! 97: .PP ! 98: When examining the ! 99: .UX ! 100: kernel a new option, \fB\-k\fP, should be used, e.g. ! 101: .sp 1 ! 102: .ti +5 ! 103: adb \-k /vmunix /dev/mem ! 104: .sp 1 ! 105: This flag causes adb to partially simulate ! 106: the VAX virtual memory hardware when ! 107: accessing the \fIcore\fP file. ! 108: In addition the internal state maintained ! 109: by the debugger is initialized from ! 110: data structures maintained by the ! 111: .UX ! 112: kernel explicitly for debugging\(dd. ! 113: A post-mortem dump may be examined in a similar ! 114: fashion, ! 115: .sp 1 ! 116: .ti +5 ! 117: adb \-k vmunix.? vmcore.? ! 118: .sp 1 ! 119: where the appropriate version of the saved operating system ! 120: image and core dump are supplied in place of ``?''. ! 121: .FS ! 122: \(dd If the \-k flag is not used when invoking ! 123: adb the user must explicitly calculate virtual ! 124: addresses. With the \-k option adb interprets ! 125: page tables to automatically ! 126: perform virtual to physical address translation. ! 127: .FE ! 128: .NH 2 ! 129: Establishing Context ! 130: .PP ! 131: During initialization adb attempts to establish the ! 132: context of the ``currently active process'' by examining ! 133: the value of the kernel variable \fImasterpaddr\fP. ! 134: This variable contains the virtual address of the ! 135: process context block of the last process which ! 136: was set executing by the \fISwtch\fP routine. ! 137: \fImasterpaddr\fP normally provides sufficient information ! 138: to locate the current stack frame (via the stack ! 139: pointers found in the context block). ! 140: By locating the VAX process context block for the ! 141: process, adb may then perform virtual to ! 142: physical address translation using that process's ! 143: in-core page tables. ! 144: .PP ! 145: When examining post-mortem dumps establishing the ! 146: context of the ``currently active process'' is nontrivial. ! 147: This is due to the different ways in which the ! 148: VAX may save state after a nonrecoverable error. ! 149: Crashes may or may not be ``clean'' (i.e. ! 150: the top of the interrupt stack contains the process's ! 151: kernel mode stack pointer and program counter); ! 152: an ``unclean'' crash will occur, for instance, ! 153: if the interrupt stack overflows. ! 154: Thus, one must manually try one of two possible techniques ! 155: to get a stack trace from a post-mortem dump. If the ! 156: crash was clean the current stack frame is present at the ! 157: ``top'' of the interrupt stack, \fIintstack\-4\fP, ! 158: and the command ! 159: .sp 1 ! 160: .ti +5 ! 161: *(\fBintstack\fP\-4)$c ! 162: .sp 1 ! 163: will generate a stack trace all the way from the kernel ! 164: to the top of the user process's stack (e.g. to the ! 165: \fImain\fP routine in the user process which was running). ! 166: Otherwise, one must scan through the interrupt stack ! 167: looking for the stack frame. This is usually indicated ! 168: by a zero longword entry (the argument count), ! 169: .sp 1 ! 170: .in +5 ! 171: .nf ! 172: \fBintstack\fP/\fBX\fP ! 173: .fi ! 174: .in -5 ! 175: .sp 1 ! 176: Once the stack frame has been located, the command ! 177: .sp 1 ! 178: .ti +5 ! 179: \fB*.$c\fP ! 180: .sp 1 ! 181: will generate a stack trace. ! 182: An alternate method may be used when a trace of a particular ! 183: process is required, see section 2.3. ! 184: .ds RH "Command Scripts ! 185: .LP ! 186: .nr H1 2 ! 187: .bp ! 188: .LG ! 189: .B ! 190: .ce ! 191: 2. ADB COMMAND SCRIPTS ! 192: .sp 2 ! 193: .R ! 194: .nr H2 0 ! 195: .NL ! 196: .NH 2 ! 197: Extending the Formatting Facilities ! 198: .PP ! 199: Once the process context has been established, the ! 200: complete adb command set is available for interpreting ! 201: data structures. In addition, a number of adb scripts have ! 202: been created to simplify the structured printing of commonly ! 203: referenced kernel data structures. The scripts normally ! 204: reside in ! 205: the directory \fI/usr/lib/adb\fP, and are invoked ! 206: with the ``$<'' operator. ! 207: (A later table lists the ``standard'' scripts.) ! 208: .PP ! 209: As an example, consider the following listing which ! 210: contains a dump of a faulty process's state ! 211: (our typing is shown emboldened). ! 212: .sp 1 ! 213: .nf ! 214: .DT ! 215: % \fBadb \-k vmunix.17 vmcore.17\fP ! 216: sbr 8001d064 slr d9c ! 217: p0br 800efa00 p0lr 34 p1br 7f8efe00 p1lr 1ffff2 ! 218: \fB*(intstack\-4)$c\fP ! 219: _boot() from 80004025 ! 220: _boot(0,4) from 80004025 ! 221: _panic(80021185) from 800057e2 ! 222: _soreceive(8017478c,0) from 80007c90 ! 223: _read() from 800098d7 ! 224: _syscall() from 8000b6e2 ! 225: _Xsyscall(3,7fffe834,258) from 80000f64 ! 226: ?() from c1c ! 227: ?() from 26a ! 228: ?(0,7fffef18,7fffef1c) from 1d3 ! 229: ?() from 2f ! 230: \fB800021185/s\fP ! 231: _icpreg+99: receive ! 232: \fBu$<u\fP ! 233: _u: ! 234: _u: ksp usp ! 235: 7fffff9c 7fffe59c ! 236: r0 r1 r2 r3 ! 237: 155c00 800237d4 80041800 3 ! 238: r4 r5 r6 r7 ! 239: 0 0 11090 80041800 ! 240: r8 r9 r10 r11 ! 241: 80021244 c 7fffe5b4 80000000 ! 242: ap fp pc psl ! 243: 7fffffe8 7fffffa4 8000b784 d80004 ! 244: p0br p0lr p1br p1lr ! 245: 800efa00 4000034 7f8efe00 1ffff2 ! 246: szpt cmap2 sswap ! 247: 2 94000307 0 ! 248: sigc1 sigc2 sigc3 ! 249: 1af03fb fa007f02 40cbc6c ! 250: _u+78: arg0 arg1 arg2 ! 251: 3 7fffe834 258 ! 252: _u+8c: segflg error uid gid ruid rgid procp ! 253: 0 0 4 a 4 a 80041800 ! 254: ! 255: _u+d4: uap rv1 rv2 ubase ! 256: 7ffff078 0 1 7fffe834 ! 257: count off cdir rdir ! 258: 258 150 8003cf00 0 ! 259: _u+f4: pathname ! 260: .netrc ! 261: dirp dino entry pdir ! 262: 3 1395 .netrc0 ! 263: 7ffff11c: ofiles ! 264: 80040818 80040818 80040818 800406b0 ! 265: 800406d4 800406ec 0 0 ! 266: 0 0 0 0 ! 267: 0 0 0 0 ! 268: 0 0 0 0 ! 269: ! 270: ofileflg ! 271: 0 0 0 0 0 0 0 0 ! 272: 0 0 0 0 0 0 0 0 ! 273: 0 0 0 0 ! 274: 7ffff180: sigs ! 275: 0 360c 1 360c ! 276: 0 0 0 aae ! 277: 0 0 0 0 ! 278: 0 0 0 0 ! 279: 0 0 0 0 ! 280: 1 0 0 0 ! 281: 0 0 0 0 ! 282: 0 0 0 0 ! 283: ! 284: code ar0 prbase prsize ! 285: 0 80000000 0 0 ! 286: ! 287: .ne 2 ! 288: 7ffff248: proff prscal eosys sep ttyp ! 289: 0 0 0 0 800288b4 ! 290: ! 291: 7ffff258: ttymin ttymaj ! 292: 0 0 ! 293: 7ffff25e: xmag xtsiz xdsiz xbsiz ! 294: 3c000000 10000000 108c0000 a680000 ! 295: ! 296: xssiz entloc relflg ! 297: 0 0 6c720000 ! 298: 7ffff27e: directory ! 299: ogin ! 300: start acflg fpflg cmsk tsiz dsiz ! 301: 11688 0 12 0 160000 60000 ! 302: ! 303: 7ffff2a2: ssiz ! 304: 80000 ! 305: \fB80041800$<proc\fP ! 306: 80041800: link rlink addr ! 307: 800237d4 0 800efde0 ! 308: 8004180c: upri pri cpu stat time nice slp cursig ! 309: 073 073 045 03 023 024 0 0 ! 310: 80041814: sig siga0 siga1 flag ! 311: 0 80002 45 8001 ! 312: 80041824: uid pgrp pid ppid poip szpt tsize ! 313: 4 bb bc bb 0 2 1e ! 314: 80041834: dsize ssize rssize maxrss ! 315: 16 6 14 3fffff ! 316: 80041844: swrss swaddr wchan textp ! 317: 0 0 0 80044ee0 ! 318: 80041854: clktim p0br xlink ticks ! 319: 0 800efa00 80041720 22 ! 320: 80041864: %cpu ndx idhash pptr ! 321: +5.1369253545999527e\-02 1c 8 80041720 ! 322: \fB80044ee0$<text\fP ! 323: 80044ee0: daddr ! 324: 7e2 0 0 0 ! 325: 0 0 0 0 ! 326: 0 0 0 0 ! 327: ! 328: ptdaddr size caddr iptr ! 329: 352 1e 80041800 8003cfa0 ! 330: ! 331: rssize swrss count ccount flag slptim poip ! 332: 1a 0 02 02 042 0 0 ! 333: .sp 1 ! 334: .fi ! 335: .PP ! 336: The cause of the crash was a ``panic'' ! 337: (see the stack trace) due to the 0 ! 338: argument passed the \fIsoreceive\fP routine. The majority ! 339: of the dump was done to illustrate the use of two command ! 340: scripts used to format kernel data structures. The ``u'' ! 341: script, invoked by the command ``u$<u'', is a lengthy series ! 342: of commands which pretty-prints the user vector. Likewise, ! 343: ``proc'' and ``text'' are scripts used to format the obvious ! 344: data structures. Let's quickly examine the ``text'' script (the ! 345: script has been broken into a number of lines for convenience ! 346: here; in actuality it is a single line of text). ! 347: .sp 1 ! 348: .nf ! 349: \&./"daddr"n12Xn\e ! 350: "ptdaddr"16t"size"16t"caddr"16t"iptr"n4Xn\e ! 351: "rssize"8t"swrss"8t"count"8t"ccount"8t"flag"8t"slptim"8t"poip"n2x4bx++n ! 352: .sp 1 ! 353: .fi ! 354: The first line produces the list of disk block addresses associated ! 355: with a swapped out text segment. The ``n'' format forces a new-line ! 356: character, with 12 hexadecimal integers printed immediately after. ! 357: Likewise, the remaining two lines of the command format the remainder ! 358: of the text structure. The expression ``16t'' causes adb to tab ! 359: to the next column which is a multiple of 16. ! 360: The last two plus operators are present ! 361: to round ``.'' to the end of the text structure. This allows the ! 362: user to reinvoke the format on consecutive text structures without ! 363: having to be concerned about proper alignment of ``.''. ! 364: .PP ! 365: The majority of the scripts provided are of this nature. ! 366: When possible, the formatting scripts print a data structure ! 367: with a single format to allow subsequent reuse when interrogating ! 368: arrays of structures. That is, the previous script could have ! 369: been written ! 370: .sp 1 ! 371: .nf ! 372: \&./"daddr"n12Xn ! 373: +/"ptdaddr"16t"size"16t"caddr"16t"iptr"n4Xn ! 374: +/"rssize"8t"swrss"8t"count"8t"ccount"8t"flag"8t"slptim"8t"poip"n2x4bx++n ! 375: .sp 1 ! 376: .fi ! 377: but then reuse of the format would have invoked only the last ! 378: line of the format. ! 379: .NH 2 ! 380: Traversing Data Structures ! 381: .PP ! 382: The adb command language can be used to traverse complex data ! 383: structures. One such data structure, a linked list, occurs ! 384: quite often in the kernel. By using adb variables and the ! 385: normal expression operators it is a simple matter to construct ! 386: a script which chains down the list printing each element ! 387: along the way. ! 388: .PP ! 389: For instance, the queue of processes awaiting timer events, ! 390: the callout queue, is printed with the following two scripts: ! 391: .sp 1 ! 392: .nf ! 393: .ne 4 ! 394: \fBcallout\fP: ! 395: .in +5 ! 396: .sp 1 ! 397: calltodo/"time"16t"arg"16t"func"12+ ! 398: *+$<callout.next ! 399: .sp 1 ! 400: .ne 6 ! 401: .ti -5 ! 402: \fBcallout.next\fP: ! 403: .sp 1 ! 404: \&./Dpp ! 405: *+>l ! 406: ,#<l$< ! 407: <l$<callout.next ! 408: .sp 1 ! 409: .in -5 ! 410: .fi ! 411: .PP ! 412: The first line of the script \fBcallout\fP starts the traversal ! 413: at the global symbol ! 414: \fIcalltodo\fP and prints a set of headings. ! 415: It then skips the empty portion of the structure used ! 416: as the head of the queue. ! 417: The second line then invokes the script \fBcallout.next\fP ! 418: moving ``.'' to ! 419: the top of the queue (``*+'' performs the indirection ! 420: through the link entry of the structure at the head of the queue). ! 421: .PP ! 422: \fBcallout.next\fP prints values for each column, then performs ! 423: a conditional test on the link to the next entry. This test ! 424: is performed as follows, ! 425: .IP "*+>l" 9 ! 426: Place the value of the ``link'' in the adb variable ``<l''. ! 427: .IP ",#<l$<" ! 428: If the value stored in ``<l'' is non-zero, then the current ! 429: input stream (i.e. the script \fBcallout.next\fP) is terminated. ! 430: Otherwise, the expression ``#<l'' will be zero, and the ``$<'' ! 431: will be ignored. That is, the combination of the logical negation ! 432: operator ``#'', adb variable ``<l'', and ``$<'' operator ! 433: creates a statement of the form, ! 434: .sp 1 ! 435: .ce ! 436: if (!link) exit; ! 437: .sp 1 ! 438: The remaining line of \fBcallout.next\fP simply reapplies the ! 439: script on the next element in the linked list. ! 440: .LP ! 441: A sample \fIcallout\fP dump is shown below. ! 442: .nf ! 443: .sp 1 ! 444: .ne 14 ! 445: % \fBadb \-k /vmunix /dev/mem\fP ! 446: sbr 8001f864 slr d9c ! 447: p0br 800efa00 p0lr 8e p1br 7f8efe00 p1lr 1ffff2 ! 448: \fB$<callout\fP ! 449: _calltodo: ! 450: _calltodo: time arg func ! 451: 8004ecfc: 26 0 _dzscan ! 452: 8004ed0c: 8 0 _upwatch ! 453: 8004ed1c: 0 0 _ip_timeo ! 454: 8004ed5c: 0 0 _tcp_timeo ! 455: 8004ed6c: 0 0 _rkwatch ! 456: 8004ecfc: 52 0 _dzscan ! 457: 8004ed2c: 68 _Syssize+70 _tmtimer ! 458: 8004ed3c: 2920 0 _memenable ! 459: .fi ! 460: .sp 1 ! 461: .NH 2 ! 462: Supplying Parameters ! 463: .PP ! 464: If one is clever, a command script may use the address ! 465: and count portions of an adb command as parameters. An example of ! 466: this is the \fBsetproc\fP script used to switch to the ! 467: context of a process with a known process-id; ! 468: .sp 1 ! 469: .ti +5 ! 470: \fB99$<setproc\fP ! 471: .sp 1 ! 472: The body of \fBsetproc\fP is ! 473: .sp 1 ! 474: .in +5 ! 475: .nf ! 476: \&.>4 ! 477: *nproc>l ! 478: *proc>f ! 479: $<setproc.nxt ! 480: .in -5 ! 481: .sp 1 ! 482: .fi ! 483: while \fBsetproc.nxt\fP is ! 484: .sp 1 ! 485: .nf ! 486: .in +5 ! 487: (*(<f+28))&0xffff="pid "X ! 488: ,#((*(<f+28)&0xffff)-<4)$<setproc.done ! 489: <l-1>l ! 490: <f+70>f ! 491: ,#<l$< ! 492: $<setproc.nxt ! 493: .in -5 ! 494: .sp 1 ! 495: .fi ! 496: The process-id, supplied as the parameter, is stored in the ! 497: variable ``<4'', the number of processes is placed in ``<l'', ! 498: and the base of the array of process structures in ``<f''. ! 499: \fBsetproc.nxt\fP then performs a linear search through the ! 500: array until it matches the process-id requested, or until ! 501: it runs out of process structures to check. The script ! 502: \fBsetproc.done\fP simply establishes the context of the ! 503: process, then exits. ! 504: .NH 2 ! 505: Standard Scripts ! 506: .PP ! 507: The following table summarizes the command scripts currently ! 508: available in the directory \fI/usr/lib/adb\fP. ! 509: .TS ! 510: center, box; ! 511: c s s ! 512: l | l | l ! 513: lb | l | l. ! 514: Standard Command Scripts ! 515: _ ! 516: Name Use Description ! 517: _ ! 518: buf \fIaddress\fP$<\fBbuf\fP format block I/O buffer ! 519: callout $<\fBcallout\fP print timer queue ! 520: clist \fIaddress\fP$<\fBclist\fP format character I/O linked list ! 521: dino \fIaddress\fP$<\fBdino\fP format directory inode ! 522: dir \fIaddress\fP$<\fBdir\fP format directory entry ! 523: file \fIaddress\fP$<\fBfile\fP format open file structure ! 524: filsys \fIaddress\fP$<\fBfilsys\fP format in-core super block structure ! 525: findproc \fIpid\fP$<\fBfindproc\fP find process by process id ! 526: ifnet \fIaddress\fP$<\fBifnet\fP format network interface structure ! 527: ifuba \fIaddress\fP$<\fBifuba\fP format UNIBUS resource structure ! 528: inode \fIaddress\fP$<\fBinode\fP format in-core inode structure ! 529: inpcb \fIaddress\fP$<\fBinpcb\fP format internet protocol control block ! 530: mact \fIaddress\fP$<\fBmact\fP show ``active'' list of mbuf's ! 531: mbstat $<\fBmbstat\fP show mbuf statistics ! 532: mbuf \fIaddress\fP$<\fBmbuf\fP show ``next'' list of mbuf's ! 533: mount \fIaddress\fP$<\fBmount\fP format mount structure ! 534: pcb \fIaddress\fP$<\fBpcb\fP format process context block ! 535: proc \fIaddress\fP$<\fBproc\fP format process table entry ! 536: setproc \fIpid\fP$<\fBsetproc\fP switch process context to \fIpid\fP ! 537: socket \fIaddress\fP$<\fBsocket\fP format socket structure ! 538: tcpcb \fIaddress\fP$<\fBtcpcb\fP format TCP control block ! 539: text \fIaddress\fP$<\fBtext\fP format text structure ! 540: traceall $<\fBtraceall\fP show stack trace for all processes ! 541: tty \fIaddress\fP$<\fBtty\fP format tty structure ! 542: u \fIaddress\fP$<\fBu\fP format user vector, including pcb ! 543: vtimes \fIaddress\fP$<\fBvtimes\fP format process times ! 544: .TE ! 545: .ds RH "Summary ! 546: .LP ! 547: .nr H1 2 ! 548: .bp ! 549: .LG ! 550: .B ! 551: .ce ! 552: 3. SUMMARY ! 553: .sp 2 ! 554: .R ! 555: .nr H2 0 ! 556: .NL ! 557: .PP ! 558: The extensions made to adb provide basic support for ! 559: debugging the ! 560: .UX ! 561: kernel by eliminating the need for a user to carry ! 562: out virtual to physical address translation. A collection ! 563: of scripts have been written to nicely format the major ! 564: kernel data structures and aid in switching between ! 565: process contexts. This has been carried out with ! 566: only minimal changes to the debugger. ! 567: .PP ! 568: More work is needed to provide enough information ! 569: for the debugger to automatically establish context ! 570: after a system crash. The system currently does not ! 571: always save enough state to allow the debugger to reliably ! 572: locate the stack frame just prior to an exception. ! 573: .PP ! 574: More work is also required on the user interface ! 575: to adb. It appears the inscrutable adb command language ! 576: has limited widespread use of much of the power of ! 577: adb. One possibility is to provide a more comprehensible ! 578: ``adb frontend'', just as \fIbc\fP(1) is used to ! 579: frontend \fIdc\fP(1). ! 580: .PP ! 581: Finally, adb could be significantly improved if it ! 582: were knowledgeable about a programs data structures. ! 583: This would eliminate the use of numeric offsets into ! 584: C structures.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.