Chapter 18 Debugging at the Machine-Instruction Level
This chapter describes how to use event management and process control
commands at the machine-instruction level, how
to display the contents of memory at specified addresses, and how to display
source lines along with their corresponding machine instructions. The next command, step command, stop command,
and trace command each support a machine-instruction level
variant: the nexti command, stepi command, stopi command, and tracei command. Use the regs command to print out the contents of machine registers or the print command to print out individual registers.
This chapter is organized into the following sections:
Examining the Contents of Memory
Using addresses and the examine or x command,
you can examine the content of memory locations as well as print the assembly
language instruction at each address. Using a command derived from adb(1),
the assembly
language debugger, you can query for:
-
The address, using the = (equal
sign) character, or,
-
The contents stored at an address,
using the / (slash) character.
You can print the assembly commands using the dis command
and the listi command. (See Using the dis Command and Using the listi Command.)
Using the examine or x Command
Use the examine command, or its alias x,
to display memory contents or addresses.
Use the following syntax to display the contents of memory starting
at address for count items
in format format. The default address is
the next one after the last address previously displayed. The default count is 1. The default format is
the same as was used in the previous examine command, or X if this is the first command given.
The syntax for the examine command is:
examine [address] [/ [count] [format]]
|
To display the contents of memory from address1 through address2 inclusive, in format format,
type:
examine address1, address2 [/ [format]]
|
Display the address, instead of the contents of the address in the given
format by typing:
examine address = [format]
|
To print the value stored at the next address after the one last displayed
by examine, type:
To print the value of an expression, enter the expression as an address:
examine address=format
examine address=
|
Addresses
The address is any expression resulting in
or usable as an address. The address may be replaced
with a + (plus sign), which displays the contents of the next address in the
default format.
For example, the following are valid addresses.:
|
0xff99
|
An absolute address
|
|
main
|
Address of a function
|
|
main+20
|
Offset from a function address
|
|
&errno
|
Address of a variable
|
|
str
|
A pointer-value variable pointing to a string
|
Symbolic addresses used to display memory are specified by preceding
a name with an ampersand (&). Function names can be used without the ampersand; &main is equal to main. Registers are denoted
by preceding a name with a dollar sign ($).
Formats
The format is the address display format in
which dbx displays the results of a query. The output produced
depends on the current display format. To change
the display format, supply a different format code.
The default format set at the start of each dbx session
is X, which displays an address or value as a 32-bit word
in hexadecimal. The following memory display formats are legal.
|
i
|
Display as an assembly instruction.
|
|
d
|
Display as 16 bits (2 bytes) in decimal.
|
|
D
|
Display as 32 bits (4 bytes) in decimal.
|
|
o
|
Display as 16 bits (2 bytes) in octal.
|
|
O
|
Display as 32 bits (4 bytes) in octal.
|
|
x
|
Display as 16 bits (2 bytes) in hexadecimal.
|
|
X
|
Display as 32 bits (4 bytes) in hexadecimal. (default format)
|
|
b
|
Display as a byte in octal.
|
|
c
|
Display as a character.
|
|
w
|
Display as a wide character.
|
|
s
|
Display as a string of characters terminated by a null byte.
|
|
W
|
Display as a wide character.
|
|
f
|
Display as a single-precision floating point number.
|
|
F, g
|
Display as a double-precision floating point number.
|
|
E
|
Display as an extended-precision floating point number.
|
|
ld, lD
|
Display 32 bits (4 bytes) in decimal (same as D).
|
|
lo, lO
|
Display 32 bits (4 bytes) in octal (same as O).
|
|
lx, LX
|
Display 32 bits (4 bytes) in hexadecimal (same as X).
|
|
Ld, LD
|
Display 64 bits (8 bytes) in decimal.
|
|
Lo, LO
|
Display 64 bits (8 bytes) in octal.
|
|
Lx, LX
|
Display 64 bits (8 bytes) in hexadecimal.
|
Count
The count is a repetition count in decimal.
The increment size depends on the memory display format.
Examples of Using an Address
The following examples show how to use an address with count and format options to display five successive disassembled instructions
starting from the current stopping point.
For SPARC based systems:
(dbx) stepi
stopped in main at 0x108bc
0x000108bc: main+0x000c: st %l0, [%fp - 0x14]
(dbx) x 0x108bc/5i
0x000108bc: main+0x000c: st %l0, [%fp - 0x14]
0x000108c0: main+0x0010: mov 0x1,%l0
0x000108c4: main+0x0014: or %l0,%g0, %o0
0x000108c8: main+0x0018: call 0x00020b90 [unresolved PLT 8: malloc]
0x000108cc: main+0x001c: nop
|
For x86 based systems:
(dbx) x &main/5i
0x08048988: main : pushl %ebp
0x08048989: main+0x0001: movl %esp,%ebp
0x0804898b: main+0x0003: subl $0x28,%esp
0x0804898e: main+0x0006: movl 0x8048ac0,%eax
0x08048993: main+0x000b: movl %eax,-8(%ebp)
|
Using the dis Command
The dis command is equivalent to the examine command
with i as the default display format.
Here is the syntax for the dis command.
dis [address] [address1, address2] [/count]
|
The dis command:
-
Without arguments displays 10 instructions starting at +.
-
With the address argument only,
disassembles 10 instructions starting at address.
-
With the address argument and a count, disassembles count instructions
starting at address.
-
With the address1 and address2 arguments, disassembles instructions from address1 through address2.
-
With only a count, displays count instructions starting at +.
Using the listi Command
To display source lines with their corresponding assembly instructions,
use the listi command, which is equivalent to the command list -i. See the discussion of list -i in Printing a Source Listing.
For SPARC based systems:
(dbx) listi 13, 14
13 i = atoi(argv[1]);
0x0001083c: main+0x0014: ld [%fp + 0x48], %l0
0x00010840: main+0x0018: add %l0, 0x4, %l0
0x00010844: main+0x001c: ld [%l0], %l0
0x00010848: main+0x0020: or %l0, %g0, %o0
0x0001084c: main+0x0024: call 0x000209e8 [unresolved PLT 7: atoi]
0x00010850: main+0x0028: nop
0x00010854: main+0x002c: or %o0, %g0, %l0
0x00010858: main+0x0030: st %l0, [%fp - 0x8]
14 j = foo(i);
0x0001085c: main+0x0034: ld [%fp - 0x8], %l0
0x00010860: main+0x0038: or %l0, %g0, %o0
0x00010864: main+0x003c: call foo
0x00010868: main+0x0040: nop
0x0001086c: main+0x0044: or %o0, %g0, %l0
0x00010870: main+0x0048: st %l0, [%fp - 0xc]
|
For x86 based systems:
(dbx) listi 13, 14
13 i = atoi(argv[1]);
0x080488fd: main+0x000d: movl 12(%ebp),%eax
0x08048900: main+0x0010: movl 4(%eax),%eax
0x08048903: main+0x0013: pushl %eax
0x08048904: main+0x0014: call atoi <0x8048798>
0x08048909: main+0x0019: addl $4,%esp
0x0804890c: main+0x001c: movl %eax,-8(%ebp)
14 j = foo(i);
0x0804890f: main+0x001f: movl -8(%ebp),%eax
0x08048912: main+0x0022: pushl %eax
0x08048913: main+0x0023: call foo <0x80488c0>
0x08048918: main+0x0028: addl $4,%esp
0x0804891b: main+0x002b: movl %eax,-12(%ebp)
|
Stepping and Tracing at Machine-Instruction Level
Machine-instruction level commands behave the same as their source level
counterparts except that they operate at the level of single instructions
instead of source lines.
Single Stepping at the Machine-Instruction Level
To single step from one machine instruction to the next machine instruction,
use the nexti command or the stepi command
The nexti command and the stepi command
behave the same as their source-code level counterparts: the nexti command
steps over functions, the stepi command
steps into a function called by the next instruction (stopping at the first
instruction in the called function). The command forms are also the same.
See next Command and step Command for a description.
The output from the nexti command and the stepi command differ from the corresponding source level commands in
two ways:
-
The output includes the address of the
instruction at which the program is stopped (instead of the source code line
number).
-
The default output contains the disassembled instruction instead of the source code line.
For example:
(dbx) func
hand::ungrasp
(dbx) nexti
ungrasp +0x18: call support
(dbx)
|
For more information, see nexti Command and stepi Command.
Tracing at the Machine-Instruction Level
Tracing techniques at the machine-instruction level work the same as
at the source code level, except you use the tracei command.
For the tracei command, dbx executes
a single instruction only after each check of the address being executed or
the value of the variable being traced. The tracei command
produces automatic stepi-like behavior: the program advances
one instruction at a time, stepping into function calls.
When you use the tracei command, it causes
the program to stop for a moment after each instruction while dbx checks
for the address execution or the value of the variable or expression being
traced. Using the tracei command can slow execution considerably.
For more information on trace and its event specifications and modifiers,
see Tracing Execution and tracei Command.
Here is the general syntax for the tracei command:
tracei event-specification [modifier]
|
Commonly used forms of the tracei command are:
|
tracei step
|
Trace each instruction.
|
|
tracei next
|
Trace each instruction, but skip over calls.
|
|
tracei at address
|
Trace the given code address.
|
For more information, see tracei Command.
For SPARC:
(dbx) tracei next -in main
(dbx) cont
0x00010814: main+0x0004: clr %l0
0x00010818: main+0x0008: st %l0, [%fp - 0x8]
0x0001081c: main+0x000c: call foo
0x00010820: main+0x0010: nop
0x00010824: main+0x0014: clr %l0
....
....
(dbx) (dbx) tracei step -in foo -if glob == 0
(dbx) cont
0x000107dc: foo+0x0004: mov 0x2, %l1
0x000107e0: foo+0x0008: sethi %hi(0x20800), %l0
0x000107e4: foo+0x000c: or %l0, 0x1f4, %l0 ! glob
0x000107e8: foo+0x0010: st %l1, [%l0]
0x000107ec: foo+0x0014: ba foo+0x1c
....
....
|
Setting Breakpoints at the Machine-Instruction Level
To set a breakpoint at the machine-instruction level, use the stopi command. The command accepts any event specification, using the syntax:
stopi event-specification [modifier]
|
Commonly used forms of the stopi command are:
stopi [at address] [-if cond]
stopi in function [-if cond]
|
For more information, see stopi Command.
Setting a Breakpoint at an Address
To set a breakpoint at a specific address, type:
For example:
(dbx) nexti
stopped in hand::ungrasp at 0x12638
(dbx) stopi at &hand::ungrasp
(3) stopi at &hand::ungrasp
(dbx)
|
Using the regs Command
The regs command lets you print the value of
all the registers.
Here is the syntax for the regs command:
-f includes floating point registers (single precision). -F includes floating point registers (double precision).
For more information, see regs Command.
For SPARC based systems:
dbx[13] regs -F
current thread: t@1
current frame: [1]
g0-g3 0x00000000 0x0011d000 0x00000000 0x00000000
g4-g7 0x00000000 0x00000000 0x00000000 0x00020c38
o0-o3 0x00000003 0x00000014 0xef7562b4 0xeffff420
o4-o7 0xef752f80 0x00000003 0xeffff3d8 0x000109b8
l0-l3 0x00000014 0x0000000a 0x0000000a 0x00010a88
l4-l7 0xeffff438 0x00000001 0x00000007 0xef74df54
i0-i3 0x00000001 0xeffff4a4 0xeffff4ac 0x00020c00
i4-i7 0x00000001 0x00000000 0xeffff440 0x000108c4
y 0x00000000
psr 0x40400086
pc 0x000109c0:main+0x4 mov 0x5, %l0
npc 0x000109c4:main+0x8 st %l0, [%fp - 0x8]
f0f1 +0.00000000000000e+00
f2f3 +0.00000000000000e+00
f4f5 +0.00000000000000e+00
f6f7 +0.00000000000000e+00
...
|
For x64 based systems:
(dbx) regs
current frame: [1]
r15 0x0000000000000000
r14 0x0000000000000000
r13 0x0000000000000000
r12 0x0000000000000000
r11 0x0000000000401b58
r10 0x0000000000000000
r9 0x0000000000401c30
r8 0x0000000000416cf0
rdi 0x0000000000416cf0
rsi 0x0000000000401c18
rbp 0xfffffd7fffdff820
rbx 0xfffffd7fff3fb190
rdx 0x0000000000401b50
rcx 0x0000000000401b54
rax 0x0000000000416cf0
trapno 0x0000000000000003
err 0x0000000000000000
rip 0x0000000000401709:main+0xf9 movl $0x0000000000000000,0xfffffffffffffffc(%rbp)
cs 0x000000000000004b
eflags 0x0000000000000206
rsp 0xfffffd7fffdff7b0
ss 0x0000000000000043
fs 0x00000000000001bb
gs 0x0000000000000000
es 0x0000000000000000
ds 0x0000000000000000
fsbase 0xfffffd7fff3a2000
gsbase 0xffffffff80000000
(dbx) regs -F
current frame: [1]
r15 0x0000000000000000
r14 0x0000000000000000
r13 0x0000000000000000
r12 0x0000000000000000
r11 0x0000000000401b58
r10 0x0000000000000000
r9 0x0000000000401c30
r8 0x0000000000416cf0
rdi 0x0000000000416cf0
rsi 0x0000000000401c18
rbp 0xfffffd7fffdff820
rbx 0xfffffd7fff3fb190
rdx 0x0000000000401b50
rcx 0x0000000000401b54
rax 0x0000000000416cf0
trapno 0x0000000000000003
err 0x0000000000000000
rip 0x0000000000401709:main+0xf9 movl $0x0000000000000000,0xfffffffffffffffc(%rbp)
cs 0x000000000000004b
eflags 0x0000000000000206
rsp 0xfffffd7fffdff7b0
ss 0x0000000000000043
fs 0x00000000000001bb
gs 0x0000000000000000
es 0x0000000000000000
ds 0x0000000000000000
fsbase 0xfffffd7fff3a2000
gsbase 0xffffffff80000000
st0 +0.00000000000000000000e+00
st1 +0.00000000000000000000e+00
st2 +0.00000000000000000000e+00
st3 +0.00000000000000000000e+00
st4 +0.00000000000000000000e+00
st5 +0.00000000000000000000e+00
st6 +0.00000000000000000000e+00
st7 +NaN
xmm0a-xmm0d 0x00000000 0xfff80000 0x00000000 0x00000000
xmm1a-xmm1d 0x00000000 0x00000000 0x00000000 0x00000000
xmm2a-xmm2d 0x00000000 0x00000000 0x00000000 0x00000000
xmm3a-xmm3d 0x00000000 0x00000000 0x00000000 0x00000000
xmm4a-xmm4d 0x00000000 0x00000000 0x00000000 0x00000000
xmm5a-xmm5d 0x00000000 0x00000000 0x00000000 0x00000000
xmm6a-xmm6d 0x00000000 0x00000000 0x00000000 0x00000000
xmm7a-xmm7d 0x00000000 0x00000000 0x00000000 0x00000000
xmm8a-xmm8d 0x00000000 0x00000000 0x00000000 0x00000000
xmm9a-xmm9d 0x00000000 0x00000000 0x00000000 0x00000000
xmm10a-xmm10d 0x00000000 0x00000000 0x00000000 0x00000000
xmm11a-xmm11d 0x00000000 0x00000000 0x00000000 0x00000000
xmm12a-xmm12d 0x00000000 0x00000000 0x00000000 0x00000000
xmm13a-xmm13d 0x00000000 0x00000000 0x00000000 0x00000000
xmm14a-xmm14d 0x00000000 0x00000000 0x00000000 0x00000000
xmm15a-xmm15d 0x00000000 0x00000000 0x00000000 0x00000000
fcw-fsw 0x137f 0x0000
fctw-fop 0x0000 0x0000
frip 0x0000000000000000
frdp 0x0000000000000000
mxcsr 0x00001f80
mxcr_mask 0x0000ffff
(dbx)
|
Platform-Specific Registers
The following tables list platform-specific register names for SPARC
architecture, x86 architecture, and AMD64 architecture that can be used in
expressions.
SPARC Register Information
The following register information is for [Please define the SPARCsans text entity] architecture.
|
Register
|
Description
|
|
$g0 through $g7
|
Global registers
|
|
$o0 through $o7
|
“out” registers
|
|
$l0 through $l7
|
“local” registers
|
|
$i0 through $i7
|
“in” registers
|
|
$fp
|
Frame pointer, equivalent to register $i6
|
|
$sp
|
Stack pointer, equivalent to register $o6
|
|
$y
|
Y register
|
|
$psr
|
Processor state register
|
|
$wim
|
Window invalid mask register
|
|
$tbr
|
Trap base register
|
|
$pc
|
Program counter
|
|
$npc
|
Next program counter
|
|
$f0 through $f31
|
FPU “f” registers
|
|
$fsr
|
FPU status register
|
|
$fq
|
FPU queue
|
The $f0f1 $f2f3 ... $f30f31 pairs
of floating-point registers are treated as having C “double” type
(normally $fN registers are treated as C “float”
type). These pairs can also be referred to as $d0 ... $d30.
The following additional registers are available on SPARC V9 and V8+
hardware:
$g0g1 through $g6g7
$o0o1 through $o6o7
$xfsr $tstate $gsr
$f32f33 $f34f35 through $f62f63 ($d32 ... $$d62)
|
See the SPARC Architecture Reference Manual and
the SPARC Assembly Language Reference Manual for more
information on SPARC registers and addressing.
x86 Register Information
The following register information is for x86 architecture.
|
Register
|
Description
|
|
$gs
|
Alternate data segment register
|
|
$fs
|
Alternate data segment register
|
|
$es
|
Alternate data segment register
|
|
$ds
|
Data segment register
|
|
$edi
|
Destination index register
|
|
$esi
|
Source index register
|
|
$ebp
|
Frame pointer
|
|
$esp
|
Stack pointer
|
|
$ebx
|
General register
|
|
$edx
|
General register
|
|
$ecx
|
General register
|
|
$eax
|
General register
|
|
$trapno
|
Exception vector number
|
|
$err
|
Error code for exception
|
|
$eip
|
Instruction pointer
|
|
$cs
|
Code segment register
|
|
$eflags
|
Flags
|
|
$uesp
|
User stack pointer
|
|
$ss
|
Stack segment register
|
Commonly used registers are also aliased to their machine independent
names.
|
Register
|
Description
|
|
$SP
|
Stack pointer; equivalent of $uesp
|
|
$pc
|
Program counter; equivalent of $eip
|
|
$fp
|
Frame pointer; equivalent of $ebp
|
Registers for the 80386 lower halves (16 bits) are:
|
Register
|
Description
|
|
$ax
|
General register
|
|
$cx
|
General register
|
|
$dx
|
General register
|
|
$bx
|
General register
|
|
$si
|
Source index register
|
|
$di
|
Destination index register
|
|
$ip
|
Instruction pointer, lower 16 bits
|
|
$flags
|
Flags, lower 16 bits
|
The first four 80386 16-bit registers can be split into 8-bit parts:
|
Register
|
Description
|
|
$al
|
Lower (right) half of register $ax
|
|
$ah
|
Higher (left) half of register $ax
|
|
$cl
|
Lower (right) half of register $cx
|
|
$ch
|
Higher (left) half of register $cx
|
|
$dl
|
Lower (right) half of register $dx
|
|
$dh
|
Higher (left) half of register $dx
|
|
$bl
|
Lower (right) half of register $bx
|
|
$bh
|
Higher (left) half of register $bx
|
Registers for the 80387 are:
|
Register
|
Description
|
|
$fctrl
|
Control register
|
|
$fstat
|
Status register
|
|
$ftag
|
Tag register
|
|
$fip
|
Instruction pointer offset
|
|
$fcs
|
Code segment selector
|
|
$fopoff
|
Operand pointer offset
|
|
$fopsel
|
Operand pointer selector
|
|
$st0 through $st7
|
Data registers
|
AMD64 Register Information
The following register information is for AMD64 architecture:
|
Register
|
Description
|
|
rax
|
General purpose register - argument passing for function calls
|
|
rbx
|
General purpose register - callee-saved
|
|
rcx
|
General purpose register - argument passing for function calls
|
|
rdx
|
General purpose register - argument passing for function calls
|
|
rbp
|
General purpose register - stack management/frame pointer
|
|
rsi
|
General purpose register - argument passing for function calls
|
|
rdi
|
General purpose register - argument passing for function calls
|
|
rsp
|
General purpose register - stack management/stack pointer
|
|
r8
|
General purpose register - argument passing for function calls
|
|
r9
|
General purpose register - argument passing for function calls
|
|
r10
|
General purpose register - temporary
|
|
r11
|
General purpose register - temporary
|
|
r12
|
General purpose register - callee-saved
|
|
r13
|
General purpose register - callee-saved
|
|
r14
|
General purpose register - callee-saved
|
|
r15
|
General purpose register - callee-saved
|
|
rflags
|
Flags register
|
|
rip
|
Instruction pointer
|
|
mmx0/st0
|
64-bit media and floating point register
|
|
mmx1/st1
|
64-bit media and floating point register
|
|
mmx2/st2
|
64-bit media and floating point register
|
|
mmx3/st3
|
64-bit media and floating point register
|
|
mmx4/st4
|
64-bit media and floating point register
|
|
mmx5/st5
|
64-bit media and floating point register
|
|
mmx6/st6
|
64-bit media and floating point register
|
|
mmx7/st7
|
64-bit media and floating point register
|
|
xmm0
|
128-bit media register
|
|
xmm1
|
128-bit media register
|
|
xmm2
|
128-bit media register
|
|
xmm3
|
128-bit media register
|
|
xmm4
|
128-bit media register
|
|
xmm5
|
128-bit media register
|
|
xmm6
|
128-bit media register
|
|
xmm7
|
128-bit media register
|
|
xmm8
|
128-bit media register
|
|
xmm9
|
128-bit media register
|
|
xmm10
|
128-bit media register
|
|
xmm11
|
128-bit media register
|
|
xmm12
|
128-bit media register
|
|
xmm13
|
128-bit media register
|
|
xmm14
|
128-bit media register
|
|
xmm15
|
128-bit media register
|
|
cs
|
Segment register
|
|
os
|
Segment register
|
|
es
|
Segment register
|
|
fs
|
Segment register
|
|
gs
|
Segment register
|
|
ss
|
Segment register
|
|
fcw
|
fxsave and fxstor memory image
control word
|
|
fsw
|
fxsave and fxstor memory image
status word
|
|
ftw
|
fxsave and fxstor memory image
tag word
|
|
fop
|
fxsave and fxstor memory image
last x87 op code
|
|
frip
|
fxsave and fxstor memory image
64-bit offset into the code segment
|
|
frdp
|
fxsave and fxstor memory image
64-bit offset into the date segment
|
|
mxcsr
|
fxsave and fxstor memory image
128 media instruction control and status register
|
|
mxcsr_mask
|
set bits in mxcsr_mask indicate supported feature
bits in mxcsr
|