Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ kdb(1M) — Dell System V Release 4 Issue 2.2

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

crash(1M)

dc(1)



kdb(1M)                          UNIX System V                          kdb(1M)


NAME
      kdb - kernel debugger

SYNOPSIS
      kdb

DESCRIPTION
      KDB is a kernel debugger that works like a Reverse Polish Notation (RPN)
      calculator.  KDB can set breakpoints, display kernel stack traces and
      various kernel structures, and modify the contents of memory, I/O, and
      registers. The debugger supports basic arithmetic operations, conditional
      execution, variables, and macros.  KDB does conversions from a kernel
      symbol name to its virtual address, from a virtual address to the value
      at that address, and from a virtual address to the name of the nearest
      kernel symbol.  You have a choice of different numeric bases, address
      spaces, and operand sizes.

      This is an advanced tool, only for those who are thoroughly familiar with
      the UNIX kernel. Because UNIX systems differ, you could possibly damage
      your system by following some of the examples in this discussion.

      You can invoke the debugger by using the kdb command or the
      sysi86(SI86TODEMON) system call on all systems, <Ctrl-Alt-d> (from the
      console only) on an AT bus system, or the interrupt character (from the
      console only) on a Multibus system. In addition, KDB is entered
      automatically under various conditions, such as panics and breakpoint
      traps.  Any time the kdb>> prompt appears, you are in the debugger.  I/O
      is done via the console (kd), or a serial terminal.

      To exit the debugger, type <Ctrl-d> or q.

      When you exit and re-enter the debugger, its state is preserved,
      including the contents of the value stack.

USING KDB AS A CALCULATOR
      KDB operates as an RPN calculator, similar to dc(1).  This calculator has
      a 32-level value stack for storing results and intermediate values.
      Commands and values you enter operate on the value stack, which is an
      internal data structure in KDB.  It has no connection with the kernel
      stack or any other stack in the system.

      To use KDB, at the kdb>> prompt type one or more items (values or
      commands) on a line.  Separate items with spaces or tabs.  Press <Enter>
      to end a line and send its contents to KDB for processing.  Each item is
      processed separately, from left to right.

      The values can be:

            Numbers.  Use positive or negative integers.  Numbers must begin
            with a digit, or a minus sign for negative numbers.  Begin octal
            numbers with "0o" and hex numbers with "0x".  Otherwise, numbers
            are assumed to be in the default base - the default is hex, unless


10/89                                                                    Page 1







kdb(1M)                          UNIX System V                          kdb(1M)


            you change it.  (See "Resetting the Numeric Base" for
            instructions.)

            Character constants.   You can have KDB convert characters to a
            number by entering one to four characters inside single quotes.
            C-style escapes are supported in character constants.

            Strings.  Use C-style strings, enclosed in double quotes.

            Kernel symbol names.  When you type a kernel symbol name, its
            address is pushed onto the value stack.

      When you enter a number or a string, it is pushed onto the value stack,
      becoming the new TOS (Top Of Stack).  Values remain on the value stack
      until they are popped off as a result of a command.

      In the descriptions below, [TOS] means the value on the top of the stack
      and [TOS-1] means the value just below it (pushed previously).

   Stack Operations
      KDB provides these commands for examining or changing the value stack:
            stk         print all values on the stack
            p           print [TOS]
            dup         push [TOS]
            pop         pop 1 value
            clrstk      pop all values

      ⊕ stk  For example, starting with an empty value stack, this input:
              5 "xyzzy" 7 stk
        displays the entire stack:
              5
              "xyzzy"
              7

      ⊕ p  At this point, the input:
              p
        displays the top value on the stack, which is:
              7
        The next example uses the p command to display the address of a kernel
        symbol.  The input:
              lbolt p
        produces an address something like this:
              D01821BC

      ⊕ dup  This command is useful when you want to use a value twice in a
        calculation.  For example:
              5 3 * dup 2 + * p
        would produce the output:
              FF
        which is the value of (((5 * 3) + 2) * (5 * 3)).




Page 2                                                                    10/89







kdb(1M)                          UNIX System V                          kdb(1M)


      ⊕ pop  This command removes the top value from the value stack.  For
        example, if this is the stack:
              5
              "xyzzy"
              7
        the input:
              pop stk
        removes the top value from the stack and displays the resulting stack:
              5
              "xyzzy"

      ⊕ clrstk  This command clears the value stack.  Remember that the
        contents of the stack are saved when you exit and re-enter KDB.

   Arithmetic Operations
      You can perform arithmetic operations on the top values on the stack:
            +           compute [TOS-1] + [TOS];  pop 2;  push result
            -           compute [TOS-1] - [TOS];  pop 2;  push result
            *           compute [TOS-1] * [TOS];  pop 2;  push result
            /           compute [TOS-1] / [TOS];  pop 2;  push result
            %           compute [TOS-1] % [TOS];  pop 2;  push result
            >>          compute [TOS-1] >> [TOS];  pop 2;  push result
            <<          compute [TOS-1] << [TOS];  pop 2;  push result
            <           compute [TOS-1] < [TOS];  pop 2;  push result
            >           compute [TOS-1] > [TOS];  pop 2;  push result
            ==          compute [TOS-1] == [TOS];  pop 2;  push result
            !=          compute [TOS-1] != [TOS];  pop 2;  push result
            &           compute [TOS-1] & [TOS];  pop 2;  push result
            |           compute [TOS-1] | [TOS];  pop 2;  push result
            ^           compute [TOS-1] ^ [TOS];  pop 2;  push result
            &&          compute [TOS-1] && [TOS];  pop 2;  push result
            ||          compute [TOS-1] || [TOS];  pop 2;  push result
            !           replace [TOS] with ![TOS]
            ++          replace [TOS] with [TOS] + 1
            --          replace [TOS] with [TOS] - 1

      For example, this input (subtracting 5 from 7):
            7 5 - p
      would produce this output:
            2

      The power of KDB's calculator feature lies in its ability to evaluate
      expressions like this:
            callout 16 +
      This pushes the address of the callout table on the stack and adds 16 to
      it. If the size of a callout table entry is 16 bytes, the result of the
      calculation is the address of the second entry in the callout table. (Use
      the size command of crash(1M) to find the sizes of common system tables.)

      WARNING:  Make sure the divide operator (slash character) is both
      preceded and followed by spaces.  If any other character appears next to
      the slash, it indicates a suffix instead of division.


10/89                                                                    Page 3







kdb(1M)                          UNIX System V                          kdb(1M)


READING AND WRITING TO MEMORY
      These commands still operate like an RPN calculator, but they perform
      specific debugging operations instead of calculations.  To examine and
      set the contents of memory (and I/O) use the commands:
            r           replace [TOS] with the value at virtual address [TOS]
            w           write [TOS-1] into virtual address [TOS];  pop 2
            dump        show [TOS] bytes starting at virtual address [TOS-1];  pop 2

      ⊕ r  For example, you can find the value of the (long) kernel variable,
        lbolt, by typing:
              lbolt r p
        This puts the virtual address of lbolt on the stack, replaces it with
        the value found at that address, and prints the result.

      ⊕ w  To change the value of lbolt to 2000, type:
              2000 lbolt w
        This writes 2000 at lbolt's virtual address.
        You could increment lbolt by typing:
              lbolt r ++ lbolt w
        This puts the virtual address of lbolt on the stack, replaces it with
        the value found at that address, adds 1 to the value, and writes the
        result at lbolt's virtual address.

      ⊕ dump  This command displays a range of memory, both in hex and ASCII.
        For example, if you typed:
              putbuf 10 dump
        which shows 10 bytes, starting at the virtual address of putbuf, you
        would see something like:
            ........ ........ ........ 61746F74  D0108C50  ............tota
            6572206C 6D206C61 726F6D65 ........  D0108C60  l real memor....
        In each line, the block of four values on the left shows the values of
        16 bytes, displayed as four 4-byte longwords in hex.  The dots
        represent values outside of the requested range.  (dump may also
        display question marks here; that means the address is invalid).  The
        next column is the address of the first of the 16 bytes.  The last
        column is the same 16 bytes displayed in ASCII.  Dots here represent
        values outside the requested range or unprintable characters.

   Suffixes
      Suffixes can be appended to many KDB commands.  They always begin with
      the slash character (/).

      WARNING:  Don't leave spaces before or after the slash character.  When
      the slash is preceded and followed by a space, it indicates division
      instead of a suffix.

      Operand-size suffixes.  The r, w and dump commands can also work with
      units of bytes and words, as well as the default longs.  To do this,
      append one of these suffixes to the command:
            /b          byte
            /w          word (2 bytes)
            /l          long (4 bytes)-this is the default.


Page 4                                                                    10/89







kdb(1M)                          UNIX System V                          kdb(1M)


      For example, to display the value of a short (2-byte) variable at address
      0xD0008120, type:
            0xD0008120 r/w p
      Entering the dump command with /b displays 16 1-byte values per line,
      with /w displays eight 2-byte values per line, and with /l (or nothing)
      displays four 4-byte values per line.

      Address-space suffixes.  The r, w and dump commands, by default, work
      with kernel virtual addresses.  You can change to physical addresses, I/O
      addresses, or user process virtual addresses by appending one of these
      suffixes to the command:
            /k          kernel virtual - the default
            /p          physical
            /io         I/O port
            /u#         user process number # virtual (# is a process slot number in hex)

      ⊕ /p  For example, to dump 40 (hex) bytes in longword format from
        physical address 2000, type:
              2000 40 dump/p
        The default address is kernel virtual, so the /p suffix is required for
        the physical address.  Note that an operand-size suffix is not
        required, because long is the default.

      ⊕ /io  For example, to read from port 300 (in bytes) and display the
        result, type:
              300 r/io/b p

      ⊕ /u#  For example, to dump 20 longwords from process 16's u area at an
        offset of 1000, type:
              1000 u + 20 dump/u16
























10/89                                                                    Page 5







kdb(1M)                          UNIX System V                          kdb(1M)


      Suffix formats.  Address-space suffixes can be combined with operand-size
      suffixes; only the first slash is required.  For example, to do the read
      from I/O port 300 shown above, any of these command lines is acceptable:
            300 r/io/b
            300 r/b/io
            300 r/iob
            300 r/bio

      Suffixes can also be attached directly to an address as shorthand for
      "read and print."  Thus, 2000 r/p p can be shortened to 2000/p.

      Since the default address-space is kernel virtual, the common operation
      of "read and print from kernel virtual" can be even further shortened.
      Type lbolt/ to read and print the value of the (long) kernel variable,
      lbolt.

DISPLAYING AND WRITING TO REGISTERS
      You can examine the CPU's general registers (and a couple of pseudo-
      registers) with these commands:
            %eax        push the contents of 32-bit register eax
            %ebx        push the contents of 32-bit register ebx
            %ecx        push the contents of 32-bit register ecx
            %edx        push the contents of 32-bit register edx
            %esi        push the contents of 32-bit register esi
            %edi        push the contents of 32-bit register edi
            %ebp        push the contents of 32-bit register ebp
            %esp        push the contents of 32-bit register esp
            %eip        push the contents of 32-bit register eip
            %efl        push the contents of 32-bit register efl
            %cs         push the contents of 16-bit register cs
            %ds         push the contents of 16-bit register ds
            %es         push the contents of 16-bit register es
            %fs         push the contents of 16-bit register fs
            %gs         push the contents of 16-bit register gs
            %err        push the error number
            %trap       push the trap number
            %ax         push the contents of 16-bit register ax
            %bx         push the contents of 16-bit register bx
            %cx         push the contents of 16-bit register cx
            %dx         push the contents of 16-bit register dx
            %si         push the contents of 16-bit register si
            %di         push the contents of 16-bit register di
            %bp         push the contents of 16-bit register bp
            %sp         push the contents of 16-bit register sp
            %ip         push the contents of 16-bit register ip
            %fl         push the contents of 16-bit register fl
            %al         push the contents of 8-bit register al
            %ah         push the contents of 8-bit register ah
            %bl         push the contents of 8-bit register bl
            %bh         push the contents of 8-bit register bh
            %cl         push the contents of 8-bit register cl
            %ch         push the contents of 8-bit register ch


Page 6                                                                    10/89







kdb(1M)                          UNIX System V                          kdb(1M)


            %dl         push the contents of 8-bit register dl
            %dh         push the contents of 8-bit register dh

      You can modify the values of general-purpose registers with these
      commands:
            w%eax       write [TOS] into 32-bit register eax;  pop 1
            w%ebx       write [TOS] into 32-bit register ebx;  pop 1
            w%ecx       write [TOS] into 32-bit register ecx;  pop 1
            w%edx       write [TOS] into 32-bit register edx;  pop 1
            w%esi       write [TOS] into 32-bit register esi;  pop 1
            w%edi       write [TOS] into 32-bit register edi;  pop 1
            w%ebp       write [TOS] into 32-bit register ebp;  pop 1
            w%esp       write [TOS] into 32-bit register esp;  pop 1
            w%eip       write [TOS] into 32-bit register eip;  pop 1
            w%efl       write [TOS] into 32-bit register efl;  pop 1
            w%cs        write [TOS] into 16-bit register cs;  pop 1
            w%ds        write [TOS] into 16-bit register ds;  pop 1
            w%es        write [TOS] into 16-bit register es;  pop 1
            w%fs        write [TOS] into 16-bit register fs;  pop 1
            w%gs        write [TOS] into 16-bit register gs;  pop 1
            w%err       write [TOS] into the error number pseudo-register;  pop 1
            w%trap      write [TOS] into the trap number pseudo-register;  pop 1
            w%ax        write [TOS] into 16-bit register ax;  pop 1
            w%bx        write [TOS] into 16-bit register bx;  pop 1
            w%cx        write [TOS] into 16-bit register cx;  pop 1
            w%dx        write [TOS] into 16-bit register dx;  pop 1
            w%si        write [TOS] into 16-bit register si;  pop 1
            w%di        write [TOS] into 16-bit register di;  pop 1
            w%bp        write [TOS] into 16-bit register bp;  pop 1
            w%sp        write [TOS] into 16-bit register sp;  pop 1
            w%ip        write [TOS] into 16-bit register ip;  pop 1
            w%fl        write [TOS] into 16-bit register fl;  pop 1
            w%al        write [TOS] into 8-bit register al;  pop 1
            w%ah        write [TOS] into 8-bit register ah;  pop 1
            w%bl        write [TOS] into 8-bit register bl;  pop 1
            w%bh        write [TOS] into 8-bit register bh;  pop 1
            w%cl        write [TOS] into 8-bit register cl;  pop 1
            w%ch        write [TOS] into 8-bit register ch;  pop 1
            w%dl        write [TOS] into 8-bit register dl;  pop 1
            w%dh        write [TOS] into 8-bit register dh;  pop 1

   Register Sets
      The commands listed above can also be used to access specific register
      sets. Multiple sets of general registers may have been saved on the
      kernel stack (one for each interrupt, trap, etc.).  For more information
      see "Printing Kernel Stack Traces."








10/89                                                                    Page 7







kdb(1M)                          UNIX System V                          kdb(1M)


      Register sets are numbered from 0 to 19, with 0 being the current (most
      recent) set.  By default, the general-register commands use register set
      0, but you can override this with a register-set suffix:
            /rs#        register set number #

      Note that by combining suffixes, you can access any register of any
      process.  For example, you can get the eax register from process 5's
      register set 1 by typing:
            %eax/u5rs1

      to push the contents of that register (%eax) in register set 1 (/rs1) of
      user process 5 (/u5).

   CPU Control Registers
      In addition to the general registers, you can examine the values of CPU
      control registers with these commands:
            cr0         push the contents of register cr0
            cr2         push the contents of register cr2
            cr3         push the contents of register cr3

CREATING DEBUGGER VARIABLES
      KDB allows you to create named variables that are stored in the debugger
      and hold debugger values (numbers or strings).  Two KDB commands apply to
      variables:
            = variable  store [TOS] in [variable];  pop 1
            vars        show values of debugger variables

      ⊕ = variable  This command assigns a value to a debugger variable.  For
        example:
              5 = abc
        creates the variable abc if it does not exist, and sets the variable
        equal to 5.  Now whenever you use the variable name, its value is
        pushed onto the stack.  For example:
              abc abc + 2 - p
        (5 + 5 - 2) will yield 8.
        Note that variable names share the same namespace as debugger macros
        and kernel global symbols.

      ⊕ vars  To look at all the existing variables, use the vars command.
        Variables are shown in the following format:
              name = value
        The vars command also lists macros, in this format:
              name :: value











Page 8                                                                    10/89







kdb(1M)                          UNIX System V                          kdb(1M)


SETTING BREAKPOINTS
      Set and modify breakpoints with these commands:
            B           set breakpoint #[TOS] at address [TOS-1];  pop 2
                  -or-  set breakpoint #[TOS] at address [TOS-2] with command string
                                 [TOS-1];  pop 3
            b           set first free breakpoint address [TOS];  pop 1
                  -or-  set first free breakpoint at address [TOS-1] with command string
                                 [TOS];  pop 2
            brkoff      disable breakpoint #[TOS];  pop 1
            brkon       re-enable breakpoint #[TOS];  pop 1
            brksoff     disable all breakpoints
            brkson      re-enable all (disabled) breakpoints
            trace       set breakpoint #[TOS] trace count to [TOS-1];  pop 2
            clrbrk      clear breakpoint #[TOS];  pop 1
            clrbrks     clear all breakpoints
            curbrk      push the current breakpoint number, or -1 if
                                 not entered from a breakpoint
            ?brk        show current breakpoint settings

      You can have up to 20 breakpoints, numbered 0 through 19, set at one
      time.

      ⊕ B and b  The B command lets you set specific breakpoints, while the b
        command automatically picks the first un-set breakpoint.
        This example sets breakpoint 3 at a specific address:
              0xD0125098 3 B
        Normally, you'll just set a breakpoint at a certain address.  For
        example:
              read b
        This sets an instruction breakpoint at the beginning of the kernel read
        routine, using the next available breakpoint number.  When the
        specified address is executed (after exiting from the debugger), you
        enter the debugger again, with a message indicating which breakpoint
        was triggered.
        Debugger command strings can be added to the breakpoint commands. Enter
        a quoted string of commands after the address:
              read "stack" b
        which is used as a series of debugger commands that are executed when
        the breakpoint is triggered.  If there are several items in the string,
        separate them with spaces:
              ie6unitdatareq "300 r/bio p" b
        After these commands are executed, you are prompted for debugger
        commands, as usual, unless the q (quit) command is executed in the
        command string.
        You can append breakpoint-type suffixes to the breakpoint commands (B
        and b).  By default, breakpoints are "instruction" breakpoints, which
        trigger when







10/89                                                                    Page 9







kdb(1M)                          UNIX System V                          kdb(1M)


        the specified address is executed.  The suffixes cause breakpoints to
        trigger on data accesses instead.  The breakpoint-type suffixes are:
              /a          data access breakpoint
              /m          data modify breakpoint
              /i          instruction execution breakpoint-this is the default
        With access and modify breakpoints, you can also use operand-size
        suffixes to control the size of the address range that will trigger the
        breakpoint.  The default is /l (4 bytes); you can also use /w (word)
        and /b (byte). (See the earlier discussion of suffixes under "Reading
        and Writing to Memory" for more information.)

      ⊕ brkoff and brkon  These commands let you temporarily disable and re-
        enable a breakpoint, instead of clearing it with clrbrk and then re-
        entering it later.  This is especially handy for breakpoints with
        command strings.

      ⊕ trace  This command sets a trace count for a breakpoint.  This causes
        the debugger to just print a message and decrement the count when the
        breakpoint is triggered, instead of entering the debugger, until the
        count reaches zero.  Commands attached to the breakpoint are not
        executed.

      ⊕ ?brk  Use this command to determine the current breakpoint settings.
        Each set breakpoint is displayed, with (1) the breakpoint number, the
        address (both (2) in hex and (3) symbolic), (4) the current state, and
        (5) the type:
              0: 0xD003907C(read) ON /i
              1      2        3   4   5
        The possible states are:
              ON          set and enabled
              DISABLED    set, but currently disabled
              OFF         un-set (these breakpoints are not displayed by ?brk)
        The possible types (in this example /i) are the same as the
        breakpoint-type suffixes described earlier.
        If a breakpoint has a non-zero trace count, that is displayed after the
        breakpoint state.  If a breakpoint has a command string, it is
        displayed at the end of the line.  For example, with a count of 5 and a
        stack command, the above breakpoint would display as:
              0: 0xD003907C(read) ON  0x5 /i "stack"

SINGLE-STEPPING THROUGH INSTRUCTIONS
      You can use these commands for single-stepping:
            s           single step 1 instruction
            ss          single step [TOS] instructions;  pop 1
            S           single step 1 instruction (passing calls)
            SS          single step [TOS] instructions (passing calls);  pop 1








Page 10                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


      s and ss single-step all instructions.  S and SS single-step all
      instructions except call instructions.  They don't step down into the
      called routine, but instead skip ahead to the return from the call,
      treating the whole subroutine sequence as a single instruction.

EXAMINING KERNEL DATA STRUCTURES
      KDB provides commands for looking at certain kernel structures:
            ps          show process information
            sleeping    show list of sleeping processes
            pinode      print s5 inode at address [TOS];  pop 1
            puinode     print ufs inode at address [TOS];  pop 1
            pprnode     print /proc inode at address [TOS];  pop 1
            psnode      print snode at address [TOS];  pop 1
            pvfs        print vfs struct at address [TOS];  pop 1
            pvnode      print vnode at address [TOS];  pop 1

      The sleeping command shows sleeping processes with their process table
      slot numbers and the channels on which they are waiting. This information
      can be used with the call and pstack commands.

      The ps command shows informatin about each active process in the system.
      This information includes process IDs, flags, states, and command names.
      The current process is marked with an asterisk (*) after its state code.

PRINTING KERNEL STACK TRACES
      KDB provides the following commands to look at kernel stack traces:
            stack       kernel stack trace for the current process
            pstack      kernel stack trace for process [TOS];  pop 1
            stackargs   set max # arguments in stack trace to [TOS];  pop 1
            stackdump   show contents of kernel stack in hex

      Note that the argument to pstack can be specified either as a process
      table slot number, the address of the process structure, or -1 for the
      current process.  (-1 pstack is equivalent to the stack command.)

      The output of stack and pstack have the same format.  A typical stack
      trace (for the current process, entered via <Ctrl-Alt-d>) looks like
      this:
      DEBUGGER ENTERED FROM USER REQUEST
       kdcksysrq(D101FD40 D00DE624 81)...........ebp:E0000D30  ret:D008F592
      *kdintr+0x186(1 0).........................ebp:E0000D74  ret:D0011A3A
      INTERRUPT 0x1 from 158:D001218A (ebp:E0000D84)
        eax:       8 ebx:       0 ecx:FFFFFFFF edx:       8 efl: 246 ds:160
        esi:D00EDDD0 edi:D106BC00 esp:E0000DC8 ebp:E0000DE0 regset:0 es:160
       idle(0 D00EDDD0 D106BC00)................(ebp:E0000DC4) ret:D006F11F
       pswtch(D002464C 0 D00F9090)...............ebp:E0000DE0  ret:D00122ED
       swtch(0 D00F9090 D101A160)...............(ebp:E0000DE4) ret:D002464C
       sleep(D0038B0C 14 D00BCA3C)...............ebp:E0000DFC  ret:D0038D6F
       fsflush(0 E0000002 E0000002)..............ebp:E0000E38  ret:D001E24B
       main+0x5FB()..............................ebp:E0000E70




10/89                                                                   Page 11







kdb(1M)                          UNIX System V                          kdb(1M)


      The stack trace shows a history of which routine called which other
      routine, up until the point the debugger was entered (or in the case of a
      non-current process, until the process was context-switched out).

      The most-recently-entered routine is shown on the first line.  In the
      example, the debugger was entered from kdcksysrq, which, in turn, was
      called by kdintr; idle was called from pswtch, and so on.  The stack
      trace ends at the point the kernel was entered from user mode.  In the
      case of a system process (as shown here) where there is no user mode, the
      stack trace ends at the call from main.

   Routine Trace Format
      The trace for each routine has four parts: (1) its address, (2) the
      arguments passed to it, (3) the value of its ebp register, and (4) its
      return address.  For example:
       fsflush(0 E0000002 E0000002).............ebp:E0000E38  ret:D001E24B
          1   ----------2---------              ------3-----  ------4-----

      Address.  The address that was called usually appears in symbolic form.
      A routine name may also include:

        An offset (a plus sign (+) and a hex number):  *kdintr+0x186
          The offset may mean that the actual address called was somewhere past
          the start of the indicated routine.  This will most likely happen if
          a subroutine was declared "static."  Since the debugger only has
          access to global symbols, it finds the nearest preceding global
          symbol.
          The offset may also mean that the exact address called cannot be
          determined.  The address displayed in this case is the return address
          into this routine from the routine it called.  This will most likely
          happen if this routine was called indirectly via a function pointer.

        An asterisk (*):  *kdintr+0x186
          This means the routine was called indirectly.  There is insufficient
          information in the stack format to be 100% sure of the correctness of
          indirect call traces.

        A tilde (~)
          This is used where there is some uncertainty in the stack trace that
          did not arise from indirect calls.

      Whenever you see an asterisk or a tilde in a stack trace, there is a
      small chance that some part of the stack trace from that point on is
      incorrect.

      Arguments.  The arguments passed to the routine appear as a list of hex
      numbers, enclosed in parentheses.  Since the actual number of arguments
      passed cannot be determined, KDB assumes that each routine has no more
      than a certain maximum number of arguments.  The default is three, but
      you can change it with the stackargs command.  If a routine actually has:




Page 12                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


        Fewer arguments than displayed:
          Only the first ones are real.  In rare cases when the debugger can
          deduce that a routine could not have been called with the maximum
          number of arguments (because there isn't enough room on the stack),
          it displays only the maximum possible number of arguments.  In the
          above stack trace, the call to kdintr is shown with only two
          arguments (1 0).

        More arguments than displayed:
          Increase the number with stackargs and then display the stack trace
          again, or dump out a portion of the stack directly in order to see
          all the arguments (continue to the next section for details).

      ebp register.  The value of the ebp register inside the routine is shown
      as a hex number following ebp:.  This value can be used as a "frame
      pointer" to access arguments and local variables for the routine.  The
      following diagram illustrates the stack layout.

                             |        .  .  .          |
                             +-------------------------+
                 [EBP] + 0xC | argument 2              |
                             +-------------------------+
                 [EBP] + 8   | argument 1              |
                             +-------------------------+
                 [EBP] + 4   | return address          |
                             +-------------------------+
                [EBP]  --->  | saved EBP from caller   |
                             +-------------------------+
                 [EBP] - 4   | local or saved register |
                             +-------------------------+
                 [EBP] - 8   | local or saved register |
                             +-------------------------+
                             |        .  .  .          |


      For example, if you want to see all the arguments to a routine that takes
      five arguments, find its ebp value from the stack trace - say 0xE0000E0C
      - and enter these commands:
            0xE0000E0C 8 + 5 4 * dump
      or, more succinctly:
            0xE0000E14 14 dump

      Any ebp value in parentheses is a computed value (see the ebp values for
      idle and switch in the example).  In these cases, due to code
      optimization or partial execution, the ebp value has not been set up for
      one or more routines.  KDB computes the value ebp ought to have had and
      displays it in parentheses.

      Return address.  This is the address this routine returns to in its
      caller.  It is shown as a hex number following ret:.




10/89                                                                   Page 13







kdb(1M)                          UNIX System V                          kdb(1M)


   Trap Frames
      In addition to lines for each routine, stack traces will often include
      "trap frames" created when an event causes suspension of current
      processing, saving all register values on the stack.  Typical events are
      interrupts, hardware exceptions, and system calls.  Trap frames are three
      lines each, starting with an upper-case, non-indented keyword (like
      INTERRUPT in the example).  The next two lines contain the values of the
      registers at the time the event occurred.  The first line of a trap frame
      is in one of these formats:
      INTERRUPT 0x1 from 158:D001218A (ebp:E0000D84)
      TRAP 0x1(err 0x0)from 158:D001218A (ebp:E0000D94,ss:esp:1F:80468E8)
      SYSTEM CALL from 158:D001218A (ebp: E0000D94, ss:esp: 1F:80468E8)
      SIGNAL RETURN from 158:D001218A (ebp: E0000D94, ss:esp: 1F:80468E8)
      These represent interrupts, hardware exception traps, system calls, and
      returns from old-style signal handlers, respectively.  The number after
      INTERRUPT is the interrupt vector number (IRQ).  The number after TRAP is
      the hardware exception number; the most common are 0x1 for breakpoint
      traps and 0xE for page faults.

      The colon-separated numbers after the word from are the segment and
      offset (cs and eip) at the time the event occurred.  The values in
      parentheses show the ebp value for the beginning of the trap frame, and
      the user stack pointer segment and offset at the time the event occurred.
      The user stack information is only displayed if the trap frame is for an
      entry into the kernel from user mode.

RESETTING THE NUMERIC BASE
      If you don't start numbers with "0o" (for octal) or "0x" (for hex), KDB
      assumes they are in the default numeric base.  Initially, the defaults
      for both input and output are set to 16 (hex), but you can use these
      commands to change them:
            ibase       set default input base to [TOS];  pop 1
            ibinary     set default input base to 2
            ioctal      set default input base to 8
            idecimal    set default input base to 10
            ihex        set default input base to 16
            obase       set output base to [TOS];  pop 1
            ooctal      set output base to 8
            odecimal    set output base to 10
            ohex        set output base to 16

CONVERTING ADDRESS SPACES
      Use these commands to convert a virtual address to a physical address:
            kvtop       convert kernel virtual address [TOS] to physical
            uvtop       convert user proc #[TOS] address [TOS-1] to physical;  pop 1

DOING CONDITIONAL EXECUTION
      KDB provides two commands for conditional execution:
            then        if [TOS] = 0, skip to endif;  pop 1
            endif       end scope of then command
      In other words, a sequence like:
            <condition> then <commands> endif


Page 14                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


      executes <commands> if and only if the <condition> is true (non-zero).

      These are mostly useful for macros and breakpoint command strings.  For
      example, imagine you wish to set a breakpoint for when the function inb
      is called with 2E as its first argument.  Use the following command:
            inb "%esp 4 + r 2E != then q" b

      This says to set a breakpoint at inb, but enter the debugger only if the
      contents of (%esp+4) are equal to 2E.  This works because esp points to
      the return address on the stack, and the longword after that is the first
      argument.  For the second argument, you would add 8 instead of 4 (see the
      "Printing Kernel Stack Traces" section for details of the stack layout).

      If you do a ?brk command, the display for that breakpoint includes the
      string of debugger commands:
            0: 0xD003907C(inb) ON  /i "%esp 4 + r 2E != then q"

CALLING A KERNEL FUNCTION
      Use this command to call an arbitrary kernel function:
            call        call the function at address [TOS-1] with [TOS] arguments,
                        given by [TOS-([TOS]+1)], ... [TOS-2]; pop [TOS]+2

      To call psignal() with two arguments, the current process and 9, type:
            curproc r 9 psignal 2 call
      curproc r gives the value of the current process, the first argument, and
      9 is the second argument.  psignal is converted into the address at which
      that function can be called, and 2 specifies the number of arguments to
      pass to psignal().

DOING A SYSTEM DUMP
      This command causes a system dump and forces a reboot:
            sysdump     cause a system dump
      All of memory and the current state is dumped to the dump partition on
      the disk, so you can use crash(1M) to do a postmortem.

MISCELLANEOUS COMMANDS
      Some miscellaneous KDB commands are:
            findsym     print kernel symbol with address closest to [TOS];  pop 1
            dis         disassemble [TOS] instructions starting at address [TOS-1];
                        pop 2
            nonverbose  turn verbose mode off
            verbose     turn verbose mode on
            newdebug    switch to another debugger on next debugger entry
            help        print a help message
            ?           print a help message (same as help)
            cmds        print a list of all debugger commands

WRITING MACROS
      KDB provides the ability to assign a string of commands to a single new
      command name, called a macro.  When a debugging task involves repeating
      the same set of commands many times (possibly doing other things in
      between), it is easier to define a macro and use it in place of the whole


10/89                                                                   Page 15







kdb(1M)                          UNIX System V                          kdb(1M)


      set of commands.

      These commands are used for macros:
            :: macro    define [macro] as command string [TOS];  pop 1
            P           print [TOS] in raw form;  pop 1
            PP          print [TOS] values in raw form,
                        from [TOS-[TOS]], ... [TOS-1]; pop [TOS]+1
            vars        show values of debugger macros and variables

      + : : macro  Use this command to define macros.  For example:
              "curproc r 16 - p" :: newaddr
        Note that macro names share the same namespace as debugger variables
        and kernel global symbols.

      ⊕ P and PP  These commands are provided to aid in writing macros.  P and
        PP print values in raw form, without the embellishments provided by the
        p command, such as quotes around strings and automatic newlines after
        each value.  This allows complete control over formatting.  For
        example, the input:
              "The value of curproc is " curproc r ".\n" 3 PP
        might produce the output:
              The value of curproc is 0xD1011E80.
        To put something like this into a macro means putting strings inside
        strings, so you'll have to escape the inner quotes:
        "\"The value of curproc is \" curproc r \".\n\" 3 PP" :: pcurproc

      ⊕ vars  Use this command to show the macro definitions.  Macros are shown
        in this format:
              name :: value
        Note that the vars command also shows the values of variables, in this
        format:
              name = value

EXECUTING DEBUGGER COMMANDS AT BOOT TIME
      KDB allows you to specify an arbitrary command sequence to be executed at
      boot time, when the system is coming up (specifically, from main() at the
      time of the iostart routines).  You can do this by writing the commands
      into the file $ROOT/etc/conf/cf.d/kdb.rc, then rebuilding the kernel with
      idbuild.

      Instead of rebuilding the kernel with idbuild, you can modify the KDB
      information in an already-built kernel by typing the command:
            unixsyms -i /etc/conf/cf.d/kdb.rc /unix

      At boot time, after the (possibly blank) string is executed, the system
      enters KDB at the kdb>> prompt, unless a q command was executed as part
      of the string - just like conditional breakpoints.  (A non-existent or
      zero-length kdb.rc file acts as a single q command, so KDB is not
      entered.)





Page 16                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


USING A SERIAL TERMINAL
      KDB can be used from a serial terminal as well as the console.  This is
      particularly useful if you are trying to debug a scenario that involves
      graphics or multiple virtual terminals on the console.

      Before you attempt to use the debugger from a serial terminal, make sure
      there is a getty or ttymon running on it.  It may be either logged in or
      waiting at the login prompt.  This ensures that the baud rate and other
      parameters are properly set.

      You can switch from the console to a terminal, and vice-versa, with the
      newterm command.  This immediately switches you to the new terminal.  The
      debugger continues to use this terminal until you give it the newterm
      command again, even if you exit and re-enter KDB.

      The newterm command does not take an argument.  On a 386, the serial
      terminal is assumed to be tty00, the terminal on the com1 port.  You can
      change the device used by editing the /etc/conf/pack.d/kdb-util/space.c
      file, rebuilding the kernel and rebooting. If the terminal is attached to
      the com2 port, set the device to tty01 by changing all occurences of
      asyputchar and asygetchar to asyputchar2 and asygetchar2, respectively,
      and changing the minor number of the device from 0 to 1.  The first lines
      of 386-specific code should look like this:
            #ifdef AT386
            int asyputchar2(), asygetchar2();
            static struct conssw asysw = {
                  asyputchar2,      1,    asygetchar2
            };
            #endif
      To use terminals on both com1 and com2 ports, you can set up newterm to
      cycle from the console to tty00 to tty01 and back to the console.  Edit
      all the 386-specific code in the space.c file to look like this:
            #ifdef AT386
            int asyputchar(), asygetchar();
            int asyputchar2(), asygetchar2();
            static struct conssw asysw = {
                  asyputchar, 0,    asygetchar
            };
            static struct conssw asysw2 = {
                  asyputchar2,      1,    asygetchar2
            };
            #endif
                  .
                  .
                  .

            #ifdef AT386
                  &asysw,
                  &asysw2,
            #endif




10/89                                                                   Page 17







kdb(1M)                          UNIX System V                          kdb(1M)


      Once you exit from KDB, you can invoke it again from either the console
      or a serial terminal. Use the kdb command to invoke the debugger from a
      terminal; <Ctrl-Alt-d> only works from the console.  Regardless of where
      you invoke KDB, its I/O appears where you directed it during the last KDB
      session.

















































Page 18                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


ENTERING THE DEBUGGER FROM A DRIVER
      If you are debugging a device driver or another part of the kernel, you
      can directly invoke the kernel debugger by including this code in your
      driver:
            #include <sys/xdebug.h>

            (*cdebugger) (DROTHER, NOFRAME);
      DR_OTHER tells the debugger that the reason for entering is "other."  See
      sys/xdebug.h for a list of other reason codes.

      Note that this mechanism cannot be used for debugging early kernel
      startup code or driver init routines, since the debugger cannot be used
      until its init routine (kdbinit) has been called.

DISABLING THE <Ctrl-Alt-d> SEQUENCE
      As a security feature, KDB can only be called from the console via
      <Ctrl-Alt-d> if the kdbsecurity flag was set to 0 when the kernel was
      built. To disable the <Ctrl-Alt-d> key sequence, reset the kdbsecurity
      flag by using /etc/conf/bin/idtune to change the KDBSECURITY tunable to
      1.  Note that the flag setting does not affect the kdb command.




COMMAND SUMMARY
      +             compute [TOS-1] + [TOS];  pop 2;  push result
      -             compute [TOS-1] - [TOS];  pop 2;  push result
      *             compute [TOS-1] * [TOS];  pop 2;  push result
      /             compute [TOS-1] / [TOS];  pop 2;  push result
      %             compute [TOS-1] % [TOS];  pop 2;  push result
      >>            compute [TOS-1] >> [TOS];  pop 2;  push result
      <<            compute [TOS-1] << [TOS];  pop 2;  push result
      <             compute [TOS-1] < [TOS];  pop 2;  push result
      >             compute [TOS-1] > [TOS];  pop 2;  push result
      ==            compute [TOS-1] == [TOS];  pop 2;  push result
      !=            compute [TOS-1] != [TOS];  pop 2;  push result
      &             compute [TOS-1] & [TOS];  pop 2;  push result
      |             compute [TOS-1] | [TOS];  pop 2;  push result
      ^             compute [TOS-1] ^ [TOS];  pop 2;  push result
      &&            compute [TOS-1] && [TOS];  pop 2;  push result
      ||            compute [TOS-1] || [TOS];  pop 2;  push result
      !             replace [TOS] with ![TOS]
      ++            replace [TOS] with [TOS] + 1
      --            replace [TOS] with [TOS] - 1
      %eax          push the contents of 32-bit register eax
      %ebx          push the contents of 32-bit register ebx
      %ecx          push the contents of 32-bit register ecx
      %edx          push the contents of 32-bit register edx
      %esi          push the contents of 32-bit register esi
      %edi          push the contents of 32-bit register edi




10/89                                                                   Page 19







kdb(1M)                          UNIX System V                          kdb(1M)


      %ebp          push the contents of 32-bit register ebp
      %esp          push the contents of 32-bit register esp
      %eip          push the contents of 32-bit register eip
      %efl          push the contents of 32-bit register efl
      %cs           push the contents of 16-bit register cs
      %ds           push the contents of 16-bit register ds
      %es           push the contents of 16-bit register es
      %fs           push the contents of 16-bit register fs
      %gs           push the contents of 16-bit register gs
      %err          push the error number
      %trap         push the trap number
      %ax           push the contents of 16-bit register ax
      %bx           push the contents of 16-bit register bx
      %cx           push the contents of 16-bit register cx
      %dx           push the contents of 16-bit register dx
      %si           push the contents of 16-bit register si
      %di           push the contents of 16-bit register di
      %bp           push the contents of 16-bit register bp
      %sp           push the contents of 16-bit register sp
      %ip           push the contents of 16-bit register ip
      %fl           push the contents of 16-bit register fl
      %al           push the contents of 8-bit register al
      %ah           push the contents of 8-bit register ah
      %bl           push the contents of 8-bit register bl
      %bh           push the contents of 8-bit register bh
      %cl           push the contents of 8-bit register cl
      %ch           push the contents of 8-bit register ch
      %dl           push the contents of 8-bit register dl
      %dh           push the contents of 8-bit register dh
      = variable    store [TOS] in [variable];  pop 1
      :: macro      define [macro] as command string [TOS];  pop 1
      ?             print a help message (same as help)
      ?brk          show current breakpoint settings
      B             set breakpoint #[TOS] at address [TOS-1];  pop 2 -or-  set
                    brkpoint #[TOS] at address [TOS-2] w/command string [TOS-
                    1];  pop 3
      b             set 1st free breakpoint address [TOS];  pop 1 -or-  set 1st
                    free brkpoint at address [TOS-1] w/command string [TOS];
                    pop 2
      brkoff        disable breakpoint #[TOS];  pop 1
      brkon         re-enable breakpoint #[TOS];  pop 1
      brksoff       disable all breakpoints
      brkson        re-enable all (disabled) breakpoints
      call          call the function at address [TOS-1] with [TOS] arguments,
                    given by [TOS-([TOS]+1)], ... [TOS-2]; pop [TOS]+2
      clrbrk        clear breakpoint #[TOS];  pop 1
      clrbrks       clear all breakpoints
      clrstk        pop all values
      cmds          print a list of all debugger commands
      cr0           push the contents of register cr0




Page 20                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


      cr2           push the contents of register cr2
      cr3           push the contents of register cr3
      curbrk        push the current breakpoint number, or -1 if not entered
                    from a breakpoint
      dis           disassemble [TOS] instructions starting at address [TOS-1];
                    pop 2
      dump          show [TOS] bytes starting at virtual address [TOS-1];  pop
                    2
      dup           push [TOS]
      endif         end scope of then command
      findsym       print kernel symbol with address closest to [TOS];  pop 1
      help          print a help message
      ibase         set default input base to [TOS];  pop 1
      ibinary       set default input base to 2
      ioctal        set default input base to 8
      idecimal      set default input base to 10
      ihex          set default input base to 16
      kvtop         convert kernel virtual addr [TOS] to physical
      newterm       alternate debugger I/O between console and tty00
      newdebug      switch to another debugger on next debugger entry
      nonverbose    turn verbose mode off
      obase         set output base to [TOS];  pop 1
      odecimal      set output base to 10
      ohex          set output base to 16
      ooctal        set output base to 8
      P             print [TOS] in raw form;  pop 1
      p             print [TOS]
      PP            print [TOS] values in raw form, from [TOS-[TOS]], ...
                    [TOS-1]; pop [TOS]+1
      pinode        print s5 inode at address [TOS];  pop 1
      pop           pop 1 value
      pprnode       print /proc inode at address [TOS];  pop 1
      psnode        print snode at address [TOS];  pop 1
      ps            show process information
      pstack        kernel stack trace for process [TOS];  pop 1
      pvfs          print vfs struct at address [TOS];  pop 1
      pvnode        print vnode at address [TOS];  pop 1
      puinode       print ufs inode at address [TOS];  pop 1
      q             quit-exit from the debugger
      r             replace [TOS] with the value at virtual address [TOS]
      S             single step 1 instruction (passing calls)
      s             single step 1 instruction
      sleeping      show list of sleeping processes
      SS            single step [TOS] instructions (passing calls);  pop 1
      ss            single step [TOS] instructions;  pop 1
      stack         kernel stack trace for the current process
      stackargs     set max # arguments in stack trace to [TOS];  pop 1
      stackdump     show contents of kernel stack in hex
      stk           print all values on the stack
      sysdump       cause a system dump




10/89                                                                   Page 21







kdb(1M)                          UNIX System V                          kdb(1M)


      then          if [TOS] = 0, skip to endif;  pop 1
      trace         set breakpoint #[TOS] trace count to [TOS-1];  pop 2
      uvtop         convert user process #[TOS] address [TOS-1] to physical;
                    pop 1
      vars          show values of debugger variables
      verbose       turn verbose mode on
      w             write [TOS-1] into virtual address [TOS];  pop 2
      w%eax         write [TOS] into 32-bit register eax;  pop 1
      w%ebx         write [TOS] into 32-bit register ebx;  pop 1
      w%ecx         write [TOS] into 32-bit register ecx;  pop 1
      w%edx         write [TOS] into 32-bit register edx;  pop 1
      w%esi         write [TOS] into 32-bit register esi;  pop 1
      w%edi         write [TOS] into 32-bit register edi;  pop 1
      w%ebp         write [TOS] into 32-bit register ebp;  pop 1
      w%esp         write [TOS] into 32-bit register esp;  pop 1
      w%eip         write [TOS] into 32-bit register eip;  pop 1
      w%efl         write [TOS] into 32-bit register efl;  pop 1
      w%cs          write [TOS] into 16-bit register cs;  pop 1
      w%ds          write [TOS] into 16-bit register ds;  pop 1
      w%es          write [TOS] into 16-bit register es;  pop 1
      w%fs          write [TOS] into 16-bit register fs;  pop 1
      w%gs          write [TOS] into 16-bit register gs;  pop 1
      w%err         write [TOS] into the error number pseudo-register;  pop 1
      w%trap        write [TOS] into the trap number pseudo-register;  pop 1
      w%ax          write [TOS] into 16-bit register ax;  pop 1
      w%bx          write [TOS] into 16-bit register bx;  pop 1
      w%cx          write [TOS] into 16-bit register cx;  pop 1
      w%dx          write [TOS] into 16-bit register dx;  pop 1
      w%si          write [TOS] into 16-bit register si;  pop 1
      w%di          write [TOS] into 16-bit register di;  pop 1
      w%bp          write [TOS] into 16-bit register bp;  pop 1
      w%sp          write [TOS] into 16-bit register sp;  pop 1
      w%ip          write [TOS] into 16-bit register ip;  pop 1
      w%fl          write [TOS] into 16-bit register fl;  pop 1
      w%al          write [TOS] into 8-bit register al;  pop 1
      w%ah          write [TOS] into 8-bit register ah;  pop 1
      w%bl          write [TOS] into 8-bit register bl;  pop 1
      w%bh          write [TOS] into 8-bit register bh;  pop 1
      w%cl          write [TOS] into 8-bit register cl;  pop 1
      w%ch          write [TOS] into 8-bit register ch;  pop 1
      w%dl          write [TOS] into 8-bit register dl;  pop 1
      w%dh          write [TOS] into 8-bit register dh;  pop 1












Page 22                                                                   10/89







kdb(1M)                          UNIX System V                          kdb(1M)


   Command Suffixes
      Operand size
      /b            byte
      /w            word (2 bytes)
      /l            long (4 bytes)-this is the default
      Address space
      /k            kernel virtual-this is the default
      /p            physical
      /io           I/O port
      /u#           user process number # virtual
      Register set
      /rs#          register set number #
      Breakpoint type
      /a            data access breakpoint
      /m            data modify breakpoint
      /i            instruction execution breakpoint-this is the default

   Old Commands
      These commands from previous versions are supported as aliases to new
      commands:

      Old           New
      Command       Equivalent
      r1            r/b
      r2            r/w
      r4            r/l
      w1            w/b
      w2            w/w
      w4            w/l
      rp1           r/b/p
      rp2           r/w/p
      rp4           r/l/p
      wp1           w/b/p
      wp2           w/w/p
      wp4           w/l/p
      rio1          r/b/io
      rio2          r/w/io
      rio4          r/l/io
      wio1          w/b/io
      wio2          w/w/io
      wio4          w/l/io
      .trap         %trap
      trc0          0 trace
      trc1          1 trace
      trc2          2 trace
      trc3          3 trace
      db?           ?brk

      These old commands are supported:





10/89                                                                   Page 23







kdb(1M)                          UNIX System V                          kdb(1M)


      .i            push breakpoint type: instruction
      .a            push breakpoint type: access byte
      .m            push breakpoint type: modify byte
      .aw           push breakpoint type: access word
      .mw           push breakpoint type: modify word
      .al           push breakpoint type: access long
      .ml           push breakpoint type: modify long
      .clr          push breakpoint type: clear breakpoint
      brk0          set breakpoint 0 to type [TOS] at address [TOS-1];  pop 2
      brk1          set breakpoint 1 to type [TOS] at address [TOS-1];  pop 2
      brk2          set breakpoint 2 to type [TOS] at address [TOS-1];  pop 2
      brk3          set breakpoint 3 to type [TOS] at address [TOS-1];  pop 2

SEE ALSO
      crash(1M)

      dc(1) in the User's Reference Manual
      The discussion of the UNIX kernel in the System Administrator's Guide.




































Page 24                                                                   10/89





Typewritten Software • bear@typewritten.org • Edmonds, WA 98026