Sun Studio 12:使用 dbx 调试程序

第 18 章 在机器指令级调试

本章介绍如何在机器指令级使用事件管理和进程控制命令、如何显示指定地址处的内存内容以及如何显示源代码行及其相应的机器指令。next 命令、step 命令、stop 命令和 trace 命令分别支持相应的机器指令级变体:nexti 命令、stepi 命令、stopi 命令和 tracei 命令。可使用 regs 命令输出多个机器寄存器的内容,也可使用 print 命令输出各个寄存器的内容。

本章由以下部分组成:

检查内存的内容

可使用地址以及 examinex 命令检查内存位置的内容及打印每个地址处的汇编语言指令。使用从 adb(1)(汇编语言调试器)派生的命令,可以查询:

可使用 dis 命令和 listi 命令打印汇编命令。(请参见dis 命令用法listi 命令用法。)

examinex 命令用法

可使用 examine 命令或其别名 x 显示内存内容或地址。

下列语法用于以 format 格式显示始于 addresscount 项内存内容。缺省的 address 为先前显示的最后一个地址后的下一个地址。缺省 count 为 1。缺省 format 与在先前的 examine 命令中使用的相同;如果这是给出的第一个命令,则为 X

examine 命令的语法如下:


examine [address] [/ [count] [format]]

要以 format 格式显示 address1address2(首末地址包含在内)的内存内容,请键入:


examine address1, address2 [/ [format]]

要以给定格式显示地址而不是地址内容,请键入:


examine address = [format]

要打印 examine 最后显示的地址后的下一个地址处存储的值,请键入:


examine +/ i

要打印表达式的值,请以地址形式输入表达式:


examine address=format
examine address=

地址

address 是求值结果为地址或可用作地址的任何表达式。可用 +(加号)替换 address,它以缺省格式显示下一个地址的内容。

例如,下面所示都是有效地址:

0xff99

绝对地址 

main

函数地址 

main+20

与函数地址的偏移 

&errno

变量地址 

str

指向字符串的指针值变量 

用于显示内存的符号地址的名称前有和号 (&)。函数名称前可以不带和号,例如,&main 等同于 main。寄存器名称前有美元符号 ($)。

格式

format dbx 用来显示查询结果的地址显示格式。产生的输出取决于当前显示 format。要更改显示格式,应提供不同的 format 代码。

每个 dbx 会话开始时的缺省格式设置为 X,即以十六进制 32 位字显示地址或值。以下内存显示格式为合法格式。

显示为汇编指令。 

显示为十进制 16 位(2 字节)。 

显示为十进制 32 位(4 字节)。 

显示为八进制 16 位(2 字节)。 

显示为八进制 32 位(4 字节)。 

显示为十六进制 16 位(2 字节)。 

显示为十六进制 32 位(4 字节)。(缺省格式) 

显示为八进制字节。 

显示为字符。 

显示为宽字符。 

显示为以空字节终止的字符串。 

显示为宽字符。 

显示为单精度浮点数。 

F, g 

显示为双精度浮点数。 

显示为扩展精度浮点数。 

ld, lD 

显示为十进制 32 位(4 字节)(与 D 相同)。 

lo, lO 

显示为八进制 32 位(4 字节)(与 O 相同)。 

lx, LX 

显示为十六进制 32 位(4 字节)(与 X 相同)。 

Ld, LD 

显示为十进制 64 位(8 字节)。 

Lo, LO 

显示为八进制 64 位(8 字节)。 

Lx, LX 

显示为十六进制 64 位(8 字节)。 

Count

count 为十进制重复计数。增量大小取决于内存显示格式。

使用地址的示例

下面的示例说明如何使用地址以及 countformat 选项来显示始于当前停止点的五个连续的反汇编指令。

对于基于 SPARC 的系统:


(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

对于基于 x86 的系统:


(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)

dis 命令用法

dis 命令等同于以 i 作为缺省显示格式的 examine 命令。

dis 命令的语法如下。


dis [address] [address1, address2] [/count]

dis 命令:

listi 命令用法

要显示源代码行及其对应的汇编指令,请使用 listi 命令,它等同于命令 list -i。请参见打印源码列表中有关 list -i 的讨论内容。

对于基于 SPARC 的系统:


(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]

对于基于 x86 的系统:


(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)

在机器指令级单步执行和跟踪

机器指令级命令与其对应的源码级命令的功能相同,只不过它们在单步指令级而非源代码行级执行。

在机器指令级单步执行

要从一个机器指令单步执行到下一个机器指令,请使用 nexti 命令或 stepi 命令

nexti 命令和 stepi 命令与其对应的源代码级命令运行方式相同:nexti 命令步过 函数,stepi 命令步入由下一个指令调用的函数(停止于被调用函数中的第一个指令)。命令形式也相同。有关说明,请参见next 命令step 命令

nexti 命令和 stepi 命令的输出与其对应的源代码级命令的输出有两点不同:

例如:


(dbx) func
hand::ungrasp
(dbx) nexti
ungrasp +0x18:  call support
(dbx)

有关更多信息,请参见nexti 命令stepi 命令

在机器指令级跟踪

机器级的跟踪技术与源代码级相同,只是要使用 tracei 命令。执行 tracei 命令时,dbx 只会在每次检查执行的地址或跟踪的变量值后,执行一个指令。tracei 命令会产生类似 stepi 的自动行为。程序一次前进一个指令来步入函数调用。

使用 tracei 命令时,它会使程序在执行每个指令后停止一会儿,这时,dbx 检查地址执行情况或跟踪的变量或表达式的值。使用 tracei 命令会显著降低执行速度。

有关跟踪及其事件规范和修饰符的更多信息,请参见跟踪执行tracei 命令

tracei 命令的常规语法如下:


tracei event-specification [modifier]

tracei 命令的常用形式为:

tracei step

跟踪每一指令。 

tracei next

跟踪每一指令,但跳过调用。 

tracei at address

跟踪给定代码地址。 

有关更多信息,请参见tracei 命令

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
....
....

在机器指令级设置断点

要在机器指令级设置断点,应使用 stopi 命令。该命令接受任何 event specification,语法如下:


stopi event-specification [modifier]

stopi 命令的常用形式如下:


stopi [at address] [-if cond]
stopi in function [-if cond]

有关更多信息,请参见stopi 命令

在地址处设置断点

要在特定地址设置断点,请键入:


(dbx) stopi at address

例如:


(dbx) nexti
stopped in hand::ungrasp at 0x12638
(dbx) stopi at &hand::ungrasp
(3) stopi at &hand::ungrasp
(dbx)

regs 命令用法

使用 regs 命令可以打印所有寄存器的值。

regs 命令的语法如下:


regs [-f][-F]

-f 表示包括浮点寄存器(单精度)。-F 表示包括浮点寄存器(双精度)。

有关更多信息,请参见regs 命令

对于基于 SPARC 的系统:


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
...

对于基于 x64 的系统:


(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)

平台特定寄存器

以下各表列出了可在表达式中使用的 SPARC、x86 和 AMD64 体系结构的平台特定寄存器名称。

SPARC 寄存器信息

下面的寄存器信息适用于 [Please define the SPARCsans text entity] 体系结构。

寄存器 

说明 

$g0 到 $g7

全局寄存器 

$o0 到 $o7

“外部”寄存器 

$l0 到 $l7

“本地”寄存器 

$i0 到 $i7

“内部”寄存器 

$fp

帧指针,等同于寄存器 $i6 

$sp

栈指针,等同于寄存器 $o6 

$y

Y 寄存器 

$psr

处理器状态寄存器 

$wim

窗口无效屏蔽寄存器 

$tbr

捕获基址寄存器 

$pc

程序计数器 

$npc

下一程序计数器 

$f0 到 $f31

FPU "f" 寄存器 

$fsr

FPU 状态寄存器 

$fq

FPU 队列 

$f0f1 $f2f3 ... $f30f31 对浮点型寄存器视为 C 的“双精度”类型(通常 $fN 寄存器视为 C 的“浮点”类型)。这些对也可称为 $d0 ... $d30.

SPARC V9 和 V8+ 硬件上另外还提供了以下这些寄存器:


$g0g1 through $g6g7
$o0o1 through $o6o7
$xfsr $tstate $gsr
$f32f33 $f34f35 through $f62f63 ($d32 ... $$d62)

有关 SPARC 寄存器和寻址的更多信息,请参见《SPARC 体系结构参考手册》和《SPARC 汇编语言参考手册》。

x86 寄存器信息

下面的寄存器信息适用于 x86 体系结构。

寄存器 

说明 

$gs

交替数据段寄存器 

$fs

交替数据段寄存器 

$es

交替数据段寄存器 

$ds

数据段寄存器 

$edi

目标索引寄存器 

$esi

源索引寄存器 

$ebp

帧指针 

$esp

栈指针 

$ebx

通用寄存器 

$edx

通用寄存器 

$ecx

通用寄存器 

$eax

通用寄存器 

$trapno

异常向量数 

$err

异常错误代码 

$eip

指令指针 

$cs

代码段寄存器 

$eflags

标志 

$uesp

用户栈指针 

$ss

堆栈段寄存器 

常用寄存器也使用其机器无关名称作为别名。

寄存器 

说明 

$SP

栈指针,等同于 $uesp

$pc

程序计数器,等同于 $eip

$fp

帧指针,等同于 $ebp

80386 下半部(16 位)寄存器为:

寄存器 

说明 

$ax

通用寄存器 

$cx

通用寄存器 

$dx

通用寄存器 

$bx

通用寄存器 

$si

源索引寄存器 

$di

目标索引寄存器 

$ip

指令指针,下 16 位 

$flags

标志,下 16 位 

80386 的前四个 16 位寄存器可分为多个 8 位部分:

寄存器 

说明 

$al

寄存器 $ax 的(右)下半部分

$ah

寄存器 $ax 的(左)上半部分

$cl

寄存器 $cx 的(右)下半部分

$ch

寄存器 $cx 的(左)上半部分

$dl

寄存器 $dx 的(右)下半部分

$dh

寄存器 $dx 的(左)上半部分

$bl

寄存器 $bx 的(右)下半部分

$bh

寄存器 $bx 的(左)上半部分

80387 的寄存器为:

寄存器 

说明 

$fctrl

控制寄存器 

$fstat

状态寄存器 

$ftag

标记寄存器 

$fip

指令指针偏移 

$fcs

代码段选择符 

$fopoff

操作数指针偏移 

$fopsel

操作数指针选择符 

$st0 到 $st7

数据寄存器 

AMD64 寄存器信息

下面的寄存器信息适用于 AMD64 体系结构:

寄存器 

说明 

rax

通用寄存器-为函数调用传递参数 

rbx

通用寄存器-被调用方保存 

rcx

通用寄存器-为函数调用传递参数 

rdx

通用寄存器-为函数调用传递参数 

rbp

通用寄存器-栈管理/帧指针 

rsi

通用寄存器-为函数调用传递参数 

rdi

通用寄存器-为函数调用传递参数 

rsp

通用寄存器-栈管理/栈指针 

r8

通用寄存器-为函数调用传递参数 

r9

通用寄存器-为函数调用传递参数 

r10

通用寄存器-临时 

r11

通用寄存器-临时 

r12

通用寄存器-被调用方保存 

r13

通用寄存器-被调用方保存 

r14

通用寄存器-被调用方保存 

r15

通用寄存器-被调用方保存 

rflags

标志寄存器 

rip

指令指针 

mmx0/st0

64 位媒体和浮点寄存器 

mmx1/st1

64 位媒体和浮点寄存器 

mmx2/st2

64 位媒体和浮点寄存器 

mmx3/st3

64 位媒体和浮点寄存器 

mmx4/st4

64 位媒体和浮点寄存器 

mmx5/st5

64 位媒体和浮点寄存器 

mmx6/st6

64 位媒体和浮点寄存器 

mmx7/st7 

64 位媒体和浮点寄存器 

xmm0

128 位媒体寄存器 

xmm1

128 位媒体寄存器 

xmm2

128 位媒体寄存器 

xmm3

128 位媒体寄存器 

xmm4

128 位媒体寄存器 

xmm5

128 位媒体寄存器 

xmm6

128 位媒体寄存器 

xmm7

128 位媒体寄存器 

xmm8

128 位媒体寄存器 

xmm9

128 位媒体寄存器 

xmm10

128 位媒体寄存器 

xmm11

128 位媒体寄存器 

xmm12

128 位媒体寄存器 

xmm13

128 位媒体寄存器 

xmm14

128 位媒体寄存器 

xmm15

128 位媒体寄存器 

cs

段寄存器 

os

段寄存器 

es

段寄存器 

fs

段寄存器 

gs

段寄存器 

ss

段寄存器 

fcw 

fxsavefxstor 内存映像控制字

fsw 

fxsavefxstor 内存映像状态字

ftw 

fxsavefxstor 内存映像标记字

fop 

fxsavefxstor 内存映像最后一个 x87 op 代码

frip 

fxsavefxstor 内存映像 64 位代码段偏移

frdp 

fxsavefxstor 内存映像 64 位日期段偏移

mxcsr 

fxsavefxstor 内存映像 128 位媒体指令控制和状态寄存器

mxcsr_mask 

mxcsr_mask 中的设置位指示 mxcsr 中支持的特征位