debugger(8) INTERACTIVE UNIX System debugger(8)
NAME
debugger - symbolic kernel debugger
SYNOPSIS
<CTRL> <ALT> d
DESCRIPTION
The RAM-resident kernel debugger is accessed by generating
an interrupt on interrupt level 1. This is frequently done
by pressing a front-panel switch (press front-panel int).
In the case of PC-type systems without front-panel interrupt
switches, the debugger is activated by typing CTRL ALT d on
the console.
The general structure of the debugger is a stack-based
language, using postfix notation similar to that of the typ-
ical Reverse Polish Notation pocket calculator. Arguments
are pushed on the stack, and then the operation is entered.
Pushing items onto the stack:
Items are pushed onto the stack by typing them in. Errors
are printed for items that are not recognized, such as sym-
bols that do not exist in the symbol table.
Symbols and symbolic references:
The debugger has the capability of referring to objects in
the kernel by their symbolic names. Since the symbol table
from the COFF image of the kernel does not get loaded at
boot time, these references are resolved in a different
fashion. When a kernel is built, it is processed by the
utility unixsyms as the last step in building the kernel.
This utility takes the symbols and values from the COFF
image and places them in a specially reserved area of the
initialized data section of the image.
Invoking operations:
Operations are invoked by entering the name of the operation
(refer to ``Pushing items onto the stack,'' above). An
error will be printed if there are not enough items on the
stack for the selected operation or if the selected opera-
tion doesn't exist.
Arguments may be entered on separate lines, or an entire
expression may be entered on one line. For example:
200
350
+
This would leave the value 550 on top of the stack, where it
can be printed, using the p operator, or used in future cal-
culations. The same result can be accomplished by:
Rev. 1.2 Page 1
debugger(8) INTERACTIVE UNIX System debugger(8)
200 350 +
Arguments on the stack are referred to by their positions
relative to the top of the stack. The top of the stack
always contains the last item pushed. The bottom of the
stack is always the first item pushed (assuming that the
operation always begins with a clean stack). For example,
if two items are pushed onto the stack, the latest one
pushed is referred to as the <tos> (top of stack). The last
item pushed is said to be on top of the stack. The first
item that was pushed is referred to as <tos-1> (top of stack
-1). This ordering scheme is important for operations that
are not commutative or those that require different types of
operators.
Arithmetic and logical operators:
The set of available arithmetic and logical operators is
similar to that of the C language. The following table
lists the arithmetic and logical operators. Also listed are
those arguments that must be on the stack and those argu-
ments that are left on the stack.
No. of No. of
Operator Operands Results Result Description
+ 2 1 sum
- 2 1 difference (<tos-1> - <tos>)
* 2 1 product
/ 2 1 integer dividend
(<tos-1> / <tos>)
% 2 1 integer remainder
(<tos-1> % <tos>)
<< 2 1 <tos> shifted left by <tos-1>
>> 2 1 <tos> shifted right by <tos-1>
& 2 1 result of logical and
| 2 1 result of logical or
-- 1 1 decrement
++ 1 1 increment
^ 2 1 exclusive or
Relational operators:
Each of the following operators leaves a 1 on the stack if
the condition is true, and leaves a 0 if it is false.
No. of No. of
Operator Operands Results Result Description
== 2 1 1 if <tos-1> and <tos> are equal
!= 2 1 1 if <tos-1> and <tos> are not
equal
> 2 1 1 if <tos-1> is greater than <tos>
Rev. 1.2 Page 2
debugger(8) INTERACTIVE UNIX System debugger(8)
< 2 1 1 if <tos-1> is less than <tos>
|| 2 1 1 if either <tos-1> or <tos> is
non-zero
&& 2 1 1 if both <tos-1> and <tos> are
non-zero
Debugger control operators:
The following operators control the behavior of the debugger
itself. Most of them are related to the user interface.
Rev. 1.2 Page 3
debugger(8) INTERACTIVE UNIX System debugger(8)
No. of No. of
Operator Operands Results Result Description
verbose 0 0 places the debugger in verbose
mode
useful for debugging the
debugger, little else
nonverbose 0 0 takes the debugger out of
verbose mode
ibase 1 0 sets the debugger input base to
<tos>
ioctal 0 0 sets the debugger input base to
8 (octal)
idecimal 0 0 sets the debugger input base to
10 (decimal)
ihex 0 sets the debugger input base to
16 (hex)
ibinary 0 0 sets the debugger input base to
2 (binary)
ooctal 0 0 sets the debugger output base to
8 (octal)
odecimal 0 0 sets the debugger output base to
10 (decimal)
ohex 0 0 sets the debugger output base to
16 (hex)
stk 0 0 displays the debugger operation
stack
clrstk X 0 clears the debugger operation
stack
sysdump 0 0 causes a memory image to be
written on swapdev
Reading and writing memory, I/O ports, and registers:
In order to read the contents of a memory location, I/O, or
register, first push the address of the memory location or
I/O port on the stack. In order to read a register, it is
necessary to push a non-printable token, which refers to the
register in question, onto the stack. Memory and I/O
address can be entered either as numbers in the current
input base or as symbolics. Registers are referred to by a
percent sign (%), followed by the register name (e.g.,
%eax). The operators to read memory locations and registers
are r1, r2, and r4. These operators read 1, 2, or 4 bytes
respectively. The value read is left on the top of the
stack. In order to write a register or memory location, the
value to be written must be pushed first, then the address
or register name to which it is to be written. The opera-
tors for writing are w1, w2, and w4. The same syntax
applies to reading and writing I/O ports. The operators for
reading and writing I/O ports are rio1, rio2, rio4, wio1,
wio2, and wio4. The following table summarizes the read and
write operators.
Rev. 1.2 Page 4
debugger(8) INTERACTIVE UNIX System debugger(8)
Rev. 1.2 Page 5
debugger(8) INTERACTIVE UNIX System debugger(8)
No. of No. of
Operator Operands Results Result Description
r1 1 1 the byte read from address <tos>
r2 1 1 the word read from address <tos>
r4 1 1 the long word read from address <tos>
w1 2 0 the byte value <tos-1> is written
to address <tos>
w2 2 0 the word value <tos-1> is written
to address <tos>
w4 2 0 the long word value <tos-1> is
written to address <tos>
rio1 1 1 the byte read from port <tos>
rio2 1 1 the word read from port <tos>
rio4 1 1 the long word read from port <tos>
wio1 2 1 the byte value <tos-1> is written
to I/O port <tos>
wio2 2 1 the word value <tos-1> is written
to I/O port <tos>
wio4 2 1 the long word value <tos-1> is
written to I/O port <tos>
Special commands:
Among the special commands are commands to print inode
structures, process table entries, and disassembled 80386
assembly code.
To display disassembled code, the starting address from
which to disassemble must be pushed, followed by the number
of lines of assembly code to print (remember this is in the
input base). The operator is dis.
Process table entries can be displayed by invoking the
operator ps. This operator takes no arguments and leaves no
results on the stack.
The sleeping operator displays the process IDs and WCHAN
values of all processes that are sleeping. Like ps, sleep-
ing requires no arguments on the stack and leaves no results
there.
The stack operator displays a symbolic stack backtrace from
the current point of execution. It needs no arguments and
leaves no result on the stack.
The findsym operator takes one argument on the stack, an
address, and displays the symbol with the highest address
which is equal to or below the argument address. This
allows the user to find the name of the routine or data
structure into which a given address is pointing.
The dump operator displays a specified number of words of
memory, starting at a specified location. The starting
Rev. 1.2 Page 6
debugger(8) INTERACTIVE UNIX System debugger(8)
location is pushed on the stack first, followed by the count
of words to display. Words are displayed grouped as bytes,
and are displayed from top to bottom, left to right, higher
address locations first. In this way, byte and word ordering
is always correct.
On the right-hand side of the display are the ASCII
equivalents of the bytes displayed on the left-hand side,
which are displayed in hex. The output of the dump operator
is unaffected by the current output base of the debugger; it
is always displayed in hex.
The stackdump operator displays the entire kernel stack and
user structure. This dump is printed in the same format as
that of the dump command (see above). The pinode operator
prints information contained in an inode structure. It
takes one argument on the stack, which must be the address
of an inode structure. Information printed includes the
address of the inode (relative to the kernel symbol inode),
the reference count, the device number, the inode number,
the number of links to this inode, the owner and group IDs
of this inode, and the size of the file referred to by this
inode.
The gdevcblk command takes one argument, an address, and
prints in English all structure items of the gdev_ctl_block
structure with items indicated where the use of other com-
mands is appropriate.
The gdevpblk command takes one argument, an address, and
prints in English all structure items of the gdev_parm_block
structure with items indicated where the use of other com-
mands is appropriate.
The gdevpart command takes one argument, an address, and
prints information on the partition table of the
gdev_parm_block structure.
The gdevdrv command takes one argument, an address, and
prints information on the gdev_driver of the gdev_parm_block
structure.
The print_chain command takes one argument, an address, and
prints the drq chain for a gdev_parm_block item.
The print_proc command takes one argument, an address, and
prints the proc structure information in English.
Breakpoints:
The debug registers on the chip are available directly to
the debugger. In addition, there are some commands for set-
ting breakpoints and single-stepping conveniently. The
debug registers are read and written with the following
Rev. 1.2 Page 7
debugger(8) INTERACTIVE UNIX System debugger(8)
operators:
No. of No. of
Operator Operands Results Result Description
db0 0 1 leaves the contents of debug register
0 on stack
db1 0 1 leaves the contents of debug register
1 on stack
db2 0 1 leaves the contents of debug register
2 on stack
db3 0 1 leaves the contents of debug register
3 on stack
db6 0 1 leaves the contents of debug register
6 on stack
db7 0 1 leaves the contents of debug register
7 on stack
wdb0 1 0 sets db0 to <tos-1>
wdb1 1 0 sets db1 to <tos-1>
wdb2 1 0 sets db2 to <tos-1>
wdb3 1 0 sets db3 to <tos-1>
wdb6 1 0 sets db6 to <tos-1>
wdb7 1 0 sets db7 to <tos-1>
The functions of each of the debug registers can be found in
the Intel 80386 Programmer's Reference Manual (Order No.
230985-001).
There are also explicit operators to set breakpoints. These
operators are brk0, brk1, brk2, brk3 ... These operators
all have the same syntax; the only difference is that each
one uses a different debug address register. These opera-
tors need two arguments on the stack when executed. The
first of these arguments is the address or symbol at which
to set a breakpoint. The second argument is a token speci-
fying which type of breakpoint to set. The possible break-
point type tokens are:
Token Breakpoint Type
.i break on instruction execution
.a break on byte access (read/write)
.aw break on word access (read/write)
.al break on long word access (read/write)
.m break on byte modify (write)
.mw break on word modify (write)
.ml break on long word modify (write)
.clr clear the breakpoint
The db? operator displays the current status of the debug
registers.
For example, to set a breakpoint at the routine namei in the
Rev. 1.2 Page 8
debugger(8) INTERACTIVE UNIX System debugger(8)
kernel, type:
namei .i brk0
This sets an instruction execution breakpoint at the first
instruction in the routine namei. As another example,
assume you would also like to break into the debugger when-
ever a write takes place to the data location swapdev.
Further, suppose swapdev is a word (16-bit) object. To set
this breakpoint, enter:
swapdev .mw brk1
Notice the use of break register 1 this time; this is to
avoid using the break register used by the instruction
breakpoint above.
To clear a breakpoint, for example, the breakpoint set at
namei above, enter:
0 .clr brk0
In addition to allowing the setting of breakpoints using the
on-chip debug facilities, the debugger also has the capabil-
ity to single step instructions. This is done by typing s.
Subsequent single steps may be performed by using RETURN.
SEE ALSO
crash(1M).
BUGS
These are the currently known bugs. They are being investi-
gated.
The sysdump command doesn't always work.
Due to variable initialization problems, after entering the
debugger, always execute the stack command first.
The debugger uses tab characters to separate columns of out-
put, so make sure tabs are set on the terminal before enter-
ing the debugger.
The ps operator is not implemented at this time.
After breaking into the debugger at an instruction break-
point, register access operators access the register set
from the user context, not the kernel.
The dis function sometimes enters an endless loop when given
too large a count. If this occurs, use CTRL ALT d to re-
enter the debugger.
Rev. 1.2 Page 9
debugger(8) INTERACTIVE UNIX System debugger(8)
ADDED VALUE
This entry, supplied by INTERACTIVE Systems Corporation, is
an extension of UNIX System V.
Rev. 1.2 Page 10