この章は、イベント管理コマンドやプロセス制御コマンドを機械命令レベルで使用する方法と、特定のアドレスにおけるメモリーの内容を表示する方法、対応する機械命令とともにソース行を表示する方法を説明します。コマンド next、step、stop、trace のそれぞれに、対応する機械命令レベルのコマンド nexti、stepi、stopi、tracei が用意されています。regs コマンドは、機械語レジスタを出力するために使用できます。また、print コマンドは、個々のレジスタを出力するために使用できます。
この章は次の各節から構成されています。
アドレスと examine または x コマンドを使用して、メモリーロケーションの内容を調べたり、各アドレスでアセンブリ言語命令を出力したりすることができます。アセンブリ言語のデバッガである adb(1) から派生したコマンドを使用して、以下の項目について問い合わせることができます。
アドレス ― "=" (等号) を使用。
あるアドレスに格納されている内容 ― "/" (スラッシュ) を使用。
dis、listi コマンドを使用して、アセンブリ命令とメモリーの内容を調べることができます。
examine コマンドまたはその別名 x を使用すると、メモリーの内容やアドレスを表示することができます。
あるメモリーの内容を表示するには、書式 fmt の count 項目の addr で表される次の構文を使用します。デフォルトの addr は、前に表示された最後のアドレスの次のアドレスになります。デフォルト count は 1 です。デフォルト fmt は、前の examine または x コマンドで使用されたものと同じです。
examine [addr] [/ [count] [fmt]]
addr1 から addr2 までのメモリー内容を書式 fmt で表示するには、次のように入力します。
examine addr1, addr2 [/ [fmt]]
アドレスの内容ではなくアドレスを指定の書式で表示するには、次のように入力します。
examine addr = [fmt]
examine によって最後に表示されたアドレスの次のアドレスに格納された値を出力するには、次のように入力します。
examine +/ i
examine addr=format examine addr=
addr はアドレスの絶対値、またはアドレスとして使用できる任意の式です。+ (プラス記号) はデフォルトのアドレスの次のアドレスを表します。
0xff99 |
絶対アドレス |
main |
関数のアドレス |
main+20 |
関数アドレス + オフセット |
&errno |
変数のアドレス |
str |
文字列を指すポインタ変数 |
メモリーを表示するためのアドレス表現は、名前の前にアンパサンド & をつけて指定します。関数名はアンパサンドなしで使用できます。&main は main と同じです。レジスタは、名前の前にドル記号 $ を付けることによって表します。
fmt は、dbx がアドレスの問い合わせ結果を表示するときの書式です。生成される出力は、現在の表示書式 fmt によって異なります。表示書式を変更する場合は、異なるコードを使用してください。
指定したアドレスに対応する情報の表示方法 fmt を dbx に対して指定するには、次のような書式指定子を設定します。
各 dbx セッションの初めに設定されるデフォルトの書式は X です。このとき、16 進表記のアドレスと値が 1 ワード (32 ビット) で表示されます。次の表は、表示書式の一覧です。
i |
アセンブラ命令として表示 |
d |
10 進表記の16 ビット (2 バイト) で表示 |
D |
10 進表記の32 ビット (4 バイト) で表示 |
o |
8 進表記の16 ビット (2 バイト) で表示 |
O |
8 進表記の32 ビット (4 バイト) で表示 |
x |
16 進表記の16 ビット (2 バイト) で表示 |
X |
16 進表記の32 ビット (4 バイト) で表示 (デフォルトの書式) |
b |
8 進表記のバイトで表示 |
c |
1 バイトの文字で表示 |
w |
ワイド文字で表示 |
s |
NULL バイトで終わる文字列で表示 |
W |
ワイド文字列で表示 |
f |
単精度浮動小数点数として表示 |
F,g |
倍精度浮動小数点数として表示 |
E |
拡張精度浮動小数点数として表示 |
ld, lD |
10 進数として 32 ビット (4 バイト) で表示 (D と同じ) |
lo, lO |
8 進数として 32 ビット (4 バイト) で表示 (O と同じ) |
lx, LX |
16 進数として 32 ビット (4 バイト) で表示 (X と同じ) |
Ld, LD |
10 進数として 64 ビット (8 バイト) で表示 |
Lo, LO |
8 進数として 64 ビット (8 バイト) で表示 |
Lx, LX |
16 進数として 64 ビット (8 バイト) で表示 |
count は、10 進法での反復カウントを示します。増分サイズは、メモリーの表示書式によって異なります。
次の例は、count および fmt の各オプションを付けてアドレスを使用して、現在の停止点から始まる 5 つの連続する分解された命令を表示する方法を示しています。
(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
(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)
このコマンドは、表示書式を i として指定した examine コマンドと同じです。
dis [addr][/count]
dis に引数を指定しないと、addr + で始まる 10 個の命令が表示されます。また count だけ指定すると、addr + で始まる count 個の命令が表示されます。
対応するアセンブリ命令とともにソース行を表示するには listi コマンドを使用します。これは list -i と同じです。第 3 章「コードの表示」の list -i についての説明を参照してください。
(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]
(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)
機械命令レベルの各コマンドは、対応するソースレベルのコマンドと同じように動作します。ただし、動作の単位はソース行ではなく、単一の命令です。
ある機械命令から次の機械命令に 1 つだけステップ実行するには、nexti または stepi コマンドを使用します。
nexti と stepi は、それぞれ対応するソースコードレベルのコマンドと同じように動作します。nexti は関数を実行して呼び出し側に戻り、stepi は次の命令から呼び出された関数に入ります (呼び出された関数の最初の命令で停止します)。コマンドの書式も同じです。詳細は next と step の説明を参照してください。
nexti と stepi からの出力は、対応するソースレベルのコマンドと 2 つの点で異なります。まず、プログラムが停止したアドレス (ソースコードの行番号ではない) が出力に含まれるという点。2 番目は、デフォルトの出力に逆アセンブルされた命令が示されるという点です。
(dbx) func hand::ungrasp (dbx) nexti ungrasp +0x18: call support (dbx)
機械命令レベルでのトレースは、ソースコードレベルでのトレースと同じように行われます。ただし、tracei を使用する場合は例外で、実行中のアドレスまたはトレース対象の変数の値がチェックされた場合にだけ、単一の命令が実行されます。tracei は、stepi のような動作を自動的に行います。すなわち、プログラムは 1 度に 1 つの命令だけ進み、関数呼び出しに入ります。
tracei を使用すると、各命令が実行され、アドレスの実行またはトレース中の変数または式の値を dbx が調べている間、プログラムは一瞬停止します。このように tracei の場合、実行速度がかなり低下します。
トレースとそのイベント仕様と修飾子の詳細については、第 5 章「ブレークポイントとトレースの設定」を参照してください。
tracei event-specification [modifier]
tracei step |
各命令をトレース |
tracei next |
各命令をトレースするが、呼び出しを飛び越します。 |
tracei at address |
指定のコードアドレスをトレース |
(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) 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 コマンドを使用します。 stopi は次の構文を使用して event_specification を受け入れます。
stopi event-specification [modifier]
一般的に使用される stopi コマンドの書式は次のとおりです。
stopi [at address] [if cond] stopi in function [-if cond]
特定のアドレスにブレークポイントを設定するには、コマンドペインで次のように入力します。
(dbx) stopi at address
(dbx) nexti stopped in hand::ungrasp at 0x12638 (dbx) stopi at &hand::ungrasp (3) stopi at &hand::ungrasp (dbx)
adb(1) 構文で adb コマンドを入力できます。また、すべてのコマンドを adb 構文として解釈する adb モードに変更することもできます。ほとんどの adb コマンドがサポートされています。
adb コマンドの詳細については、dbx のオンラインヘルプを参照してください。
regs コマンドを使用すると、すべてのレジスタの値を表示することができます。
regs [-f] [-F]
-f には浮動小数点レジスタ (単精度)、-F には浮動小数点レジスタ (倍精度) が含まれます。これは、SPARC だけのオプションです。
dbx 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 ...
次の表は、式で使用できる SPARC および x86 のプラットフォームに固有のレジスタ名を示しています。
レジスタ |
説明 |
---|---|
$g0-$g7 |
「大域」レジスタ |
$o0-$o7 |
「出力」レジスタ |
$l0-$17 |
「局所」レジスタ |
$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 の“doule”型とみなされます。通常、$fN レジスタは C の“float”型とみなされます。
次の追加レジスタは、SPARC V9 および V8+ ハードウェアで使用できます。
$xg0 $xg1 through $xg7 $xo0 $xo1 through $xo7 $xfsr $tstate $gsr $f32f33 $f34f35 through $f62f63
SPARC のレジスタとアドレッシングの詳細については、『SPARC アーキテクチャマニュアルバージョン 8』(トッパン刊) および『Sun-4 Assembly Language Reference Manual』を参照してください。
レジスタ |
説明 |
---|---|
$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 ビット) |
上記のうち最初の 4 つの 80386 用 16 ビットレジスタは、8 ビットずつに分割できます。
$al |
レジスタの下位 (右) 部分 |
$ax |
$ah |
レジスタの上位 (左) 部分 |
$ax |
$cl |
レジスタの下位 (右) 部分 |
$cx |
$ch |
レジスタの上位 (左) 部分 |
$cx |
$dl |
レジスタの下位 (右) 部分 |
$dx |
$dh |
レジスタの上位 (左) 部分 |
$dx |
$bl |
レジスタの下位 (右) 部分 |
$bx |
$bh |
レジスタの上位 (左) 部分 |
$bx |
$fctrl |
コントロールレジスタ |
$fstat |
状態レジスタ |
$ftag |
タグレジスタ |
$fip |
命令ポインタオフセット |
$fcs |
コードセグメントセレクタ |
$fopoff |
オペランドポインタオフセット |
$fopsel |
オペランドポインタセレクタ |
$st0 - $st7 |
データレジスタ |