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