dbx コマンドによるデバッグ |
第 6 章
イベント管理
イベント管理は、デバッグ中のプログラムで特定のイベントが発生したときに特定のアクションを実行する、
dbx
の一般的な機能です。イベントハンドラ
イベント管理は「ハンドラ」の概念に基づくもので、この名前はハードウェアの割り込みハンドラからきたものです。通常、ハンドラは各イベント管理コマンドによって作成されます。これらのコマンドは、イベント指定と関連する一連のアクションで構成されます (「イベント指定の設定」参照)。イベント指定は、ハンドラを発生させるイベントを指定します。
イベントが発生し、ハンドラが引き起こされると、イベント指定に含まれる任意の修飾子に従って、ハンドラはイベントを評価します (「イベント指定のための修飾子」参照)。修飾子によって課された条件にイベントが適合すると、ハンドラの関連アクションが実行されます (つまり、ハンドラが起動します)。
プログラムイベントを
dbx
アクションに対応付ける例は、特定の行にブレークポイントを設定するものです。ハンドラを作成する最も一般的な形は、
when
コマンドを使用するものです。
when
event-specification{
action; ... }
この章の例は、
when
を使用した表現でコマンド (stop
、step
、ignore
など) を記述する方法を示します。これらの例は、when
とその配下にあるハンドラ機構の柔軟性を示すものですが、常に同じ働きをするとは限りません。イベントハンドラの作成
when
、stop
、trace
コマンドを使用して、イベントハンドラを作成します。共通の
when
構文は、stop
を使用して簡単に表現できます。
when
event-specification{ stop -update; whereami; }
event-specification は、イベント管理コマンド
stop
、when
、trace
にて使用され、関心のあるイベントを指定します。(「イベント指定の設定」参照)。
trace
コマンドのほとんどは、when
コマンド、ksh
機能、イベント変数を使用して手動で作成することができます。これは、スタイル化されたトレーシング出力を希望する場合、特に有益です。詳細については、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「when コマンド」、「stop コマンド」、「trace コマンド」を参照してください。
コマンドが実行される度に、ハンドラ id (hid) 番号を返します。事前定義変数
$newhandlerid
を介してこの番号にアクセスすることができます。
stop
とwhen
コマンドをハンドラモデルに合致させるよう試みましたが、以前の dbx リリースとの下位互換性を保つため、完全にはできませんでした。一例として、初期の
dbx
バージョンで使用されていたハンドラと、それに相当する新しいハンドラを次の表に示します。
when
cond bodywhen step -if
cond bodywhen
condin
funcbody
when next -if
cond-in
funcbody
この例は、cond が純粋なイベントではないことを示しています。条件に対する内部ハンドラはありません。
イベントハンドラを操作するコマンド
次のコマンドを使用して、イベントハンドラを操作することができます。各コマンドについての詳細は、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「コマンド」リストを参照してください。
status
- ハンドラを表示 (「status コマンド」参照)。delete
- 一時ハンドラを含むすべてのハンドラを削除します (「delete コマンド」参照)。clear
- ブレークポイントの位置にもとづいてハンドラを削除します (「clear コマンド」参照)。handler
-enable
- ハンドラを有効にします (「handler コマンド」参照)。handler
-disable
- ハンドラを無効にします。cancel
- 信号を取り消し、プロセスを継続させます (「cancel コマンド」参照)。イベントカウンタ
イベントハンドラはカウンタを備えており、制限値と実際のカウンタを保持します。イベントが発生するたびにカウンタをインクリメント (1 つ増加) し、その値が制限値に達すると、ハンドラに対応するアクションを起動してカウンタをゼロにリセットします。デフォルトの制限値は 1 です。プロセスが再実行されるたびに、すべてのイベントカウンタがリセットされます。
stop
、when
、trace
コマンドを持つ-count
修飾子を使用して、カウント制限を設定することができます (「-count n -count infinity」参照)。このほか、handler
コマンドを使用して、個々のイベントハンドラを操作できます。
handler [ -count | -reset ]
hid new-count new-count-limitイベント指定の設定
イベント指定子は、
stop
、when
、trace
コマンドがイベントタイプやパラメータを表すために使用します。その書式は、イベントタイプを表すキーワードと省略可能なパラメータで構成されます。詳細については、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「イベント指定」を参照してください。ブレークポイントイベント仕様
次に、ブレークポイントイベントに対するイベント仕様を説明します。
in
function関数が入力され、最初の行が実行される直前。
-instr
修飾子が使用される場合 (「-instr」参照) は、関数の最初の命令が実行される直前です。func
仕様は、仮パラメータを含むことができるため、多重定義関数名、またはテンプレートインスタンスの指定に役立ちます。たとえば、次のように使用できます。
stop in mumble(int, float, struct Node *)
注 -in
function と-in
function 修飾子とを混同しないでください。
at [
filename:]
lineno指定の行が実行される直前。filename を指定した場合は、指定ファイルの指定の行が実行される直前。ファイル名には、ソースファイル名またはオブジェクトファイル名を指定します。引用符は不要ですが、ファイル名に特殊文字が含まれる場合は、必要な場合もあります。指定の行がテンプレートコードに含まれる場合、ブレークポイントは、そのテンプレートのすべてのインスタンス上に置かれます。
infuction
functionfunction と名付けられたすべての多重定義関数、およびテンプレートインスタンスのすべてに対し、
in
function と同じ働きをします。
inmember
functioninmethod
functionすべてのクラスの function と名付けられたメンバー関数に対し、
in
function と同じ働きをします。
inclass
classnameclassname のメンバーであるすべてのメンバー関数に対し、
in
function と同じ働きをします。
inobject
object-expressionobject-expression に指定されているアドレスのオブジェクトを呼び出したメンバー関数が呼び出されているとき。
ウォッチポイントイベント仕様
次に、ウォッチポイントイベントに対するイベント仕様について説明します。詳細については、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「ウォッチポイント仕様」を参照してください。
access
mode addr-exp, [byte-size-exp]addr-exp で指定されたメモリーがアクセスされたとき。
mode には、メモリーがアクセスされたことを示す、次のいずれか (またはすべて) の文字を指定します。
r
メモリーが読み取られた w
メモリーが書き込まれた x
メモリーが実行された
さらに mode には、次のいずれかの文字も指定することができます。
a
アクセス後にプロセスを停止する (デフォルト) b
アクセス前にプロセスを停止する
いずれの場合も、プログラムカウンタは副作用アクションの前後で違反している命令をポイントします。
address-expression は、その評価によりアドレスを生成できる任意の式です。シンボル式を使用すると、監視される領域のサイズが自動的に推定されます。このサイズは、byte-size-expression を指定することにより、上書されます。シンボルを使用しない、型を持たないアドレス式を使用することもできますが、その場合はサイズを指定する必要があります。たとえば、次のようにします。
stop access 0x5678, sizeof(Complex)
access
コマンドには、2 つの一致する範囲が重複しない、という制限があります。
注 -access
イベント仕様は、modify
イベント仕様の代替です。どちらの構文も、Solaris 2.6、Solaris 7、Solaris 8 で動作します。ただし、そのうち Solaris 2.6 を除くオペレーティング環境では、access
にmodify
と同じ制限が課せられ、wa
モード以外は使用できません。
change
variable
cond
cond-exprcond-expr によって示される条件が真と評価されます。cond-expr には任意の式を使用できますが、整数型に評価されなければなりません。
modify
addr-exp[ ,
byte-size]
指定されたアドレス範囲で変更があったとき。これは古いウォッチポイント機能です。
addr-exp は、その評価によりアドレスを生成できる任意の式です。シンボル式を使用すると、監視対象の領域のサイズが自動的に推定されます。このサイズは '
,
' 構文を使用して変更できます。また、記号を使用しない、型を持たないアドレス式を使用することもできますが、その場合はサイズを指定する必要があります。たとえば、次のようにします。
stop modify 0x5678, sizeof(Complex)
注 - マルチスレッドアプリケーションは、デッドロックする傾向があります。そのため、mt ウォッチポイントは公式には許可されていません。mt ウォッチポイントは、dbx
環境変数mt_watchpoints
を設定することにより、オンにすることができます。
システムイベント仕様
次に、システムイベントに対するイベント仕様について説明します。
dlopen [
lib-path]|dlclose [
lib-path]
これらのイベントは、
dlopen()
またはdlclose()
の呼び出しが正常終了した後に発生します。dlopen()
またはdlclose()
の呼び出しにより、複数のライブラリが読み込まれることがあります。これらのライブラリのリストは、事前定義済み変数$dllist
で常に入手できます。$dllist
の中の最初の単語は実際には "+" または "-
" で、それぞれライブラリが追加されているか、削除されているかを示します。lib-path は、該当する共有ライブラリの名前です。これを指定した場合、そのライブラリが読み込まれたり、読み込みが取り消されたりした場合にだけイベントが起動します。その場合、
$dlobj
にライブラリの名前が格納されます。また、$dllist
も利用できます。lib-path が
/
で始まる場合は、パス名全体が比較されます。それ以外の場合は、パス名のベースだけが比較されます。lib-path を指定しない場合、イベントは任意の
dl
動作があるときに必ず起動します。$dlobj
は空になりますが、$dllist
は有効です。
falut
fault
fault
イベントは、指定の障害に遭遇したとき、発生します。障害は、アーキテクチャ依存です。dbx
に対して知られる次の一連の障害は、proc
(4) マニュアルページで定義されています。
注 -BPT
、TRACE
、BOUNDS
は、ブレークポイント、ステップ実行、ウォッチポイントを実現するため、dbx
で使用されます。これらを操作すると、dbx
の動作に影響を及ぼす場合があります。
これらの障害は、
/sys/fault.h
から抜粋されています。fault には上記の名前を大文字または小文字で指定できるほか、実際のコードも指定できます。また、コードの名前には、接頭辞FLT-
をつけることがあります。
lwp_exit
lwp_exit
イベントは、lwp
が終了したとき、発生します。$lwp
には、終了した LWP (軽量プロセス) の id が含まれます。
sig
sig
sig
sig イベントは、デバッグ中のプログラムに信号が初めて送られたとき、発生します。sig は、10 進数、または大文字、小文字の信号名のいずれかです。接頭辞は任意です。このイベントは、catch/ignore
コマンドからは完全に独立しています。ただし、catch
コマンドは次のように実現することができます。
function simple_catch {when sig $1 {stop;echo Stopped due to $sigstr $sigwhereami}}
注 -sig
イベントを受け取った時点では、プロセスはまだそれを見ることができません。指定の信号を持つプロセスを継続する場合のみ、その信号が転送されます。
sig
sigsub-code
指定の sub-code を持つ指定の信号が child に初めて送られたとき、
sig
sigsub-code イベントが発生します。信号同様、sub-code は 10 進数として、大文字または小文字で入力することができます。接頭辞は任意です。
sysin
code|
name指定されたシステムコールが起動された直後で、プロセスがカーネルモードに入ったとき。
dbx
の認識するシステムコールはprocfs
(4) の認識するものに限られます。これらのシステムコールはカーネルでトラップされ、/usr/include/sys/syscall.h
に列挙されます。これは、ABI の言うところのシステムコールとは違います。ABI のシステムコールの一部は部分的にユーザーモードで実装され、非 ABI のカーネルトラップを使用します。ただし、一般的なシステムコールのほとんど (シグナル関係は除く) は
syscall.h
と ABI で共通です。
sysout
code|
name指定されたシステムコールが終了し、プロセスがユーザーモードに戻る直前。
sysin|sysout
引数がないときは、すべてのシステムコールがトレースされます。ここで、
modify
イベントや RTC (実行時検査) などの特定のdbx
は、子プロセスにその目的でシステムコールを引き起こすことがあることに注意してください。トレースした場合にそのシステムコールの内容が示されることがあります。実行進行状況イベント仕様
次に、実行進行状況に関するイベントのイベント仕様について説明します。
next
next
イベントは、関数がステップされないことを除いては、step
イベントと同様です。
returns
このイベントは、現在表示されている関数の戻りのブレークポイントです。表示されている関数を使用するのは、いくつかの
up
を行なった後にreturns
イベント指定を使用できるようにするためです。通常の戻りイベントは常に一時イベント (-temp
) で、動作中のプロセスが存在する場合にだけ作成できます。
returns
funcこれは一時イベントではありません。特定の関数がその呼び出し場所にリターンするたびに発生します。戻り値は示されませんが、SPARC プラットフォームでは
$o0
、Intel プラットフォームでは$eax
を使用して、必須戻り値を調べることができます。
SPARC $o0
Intel $eax
when in func { stop returns; }
step
step
イベントは、ソース行の先頭の命令が実行されると発生します。たとえば、次のようにシンプルに表現することができます。
when step { echo $lineno: $line; }
step
を有効にするということは、次にcont
が使用されるときに自動的にステップ実行するようにdbx
に命令することと同じです。step
コマンドは、次のように指定できます。
alias step="when step -temp { whereami; stop; }; cont"
その他のイベント仕様
次に、その他のタイプのイベントに対するイベント仕様を説明します。
attach
detach
lastrites
デバッグ対象のプロセスが終了する直前。このイベントが発生するのは次の 3 つの場合です。
- システムコール
_exit
(2) が呼び出し中 (これは、明示的に呼び出されたとき、またはmain()
のリターン時に発生します)。- 終了シグナルが送信されようとするとき。
dbx
コマンドkill
によってプロセスが強制終了されつつあるとき。
proc_gone
dbx
がデバッグ中のプロセスと関連しなくなるとき。事前定義済み変数$reason
に、signal
、exit
、kill
、またはdetach
のいずれかが設定されます。
prog_new
follow exec
の結果、新規のプログラムがロードされると、prog_new
イベントが発生します。
注 - このイベントのハンドラは常に存在しています。
stop
プロセスが停止したとき。特に
stop
ハンドラによりユーザーがプロンプトを受け取るときのようにプロセスが停止すると、このイベントが起動します。次に例を示します。
display x
when stop {print x;}
sync
デバッグ対象のプロセスが
exec()
で実行された直後。a.out
で指定されたメモリーはすべて有効で存在しますが、あらかじめ読み込まれるべき共有ライブラリはまだ読み込まれていません。たとえばprintf
はdbx
に認識されていますが、まだメモリーにはマップされていません。
stop
コマンドにこのイベントを指定しても期待した結果は得られません。when
コマンドに指定してください。
syncrtld
このイベントは、
sync
(被デバッグ側が共有ライブラリをまだ処理していない場合はattach
) の後に発生します。すなわち、動的リンカーの起動時コードが実行され、あらかじめ読み込まれている共有ライブラリすべてのシンボルテーブルが読み込まれた後、ただし、.init
セクション内のコードがすべて実行される前に発生します。
stop
コマンドにこのイベントを指定しても期待した結果は得られません。when
コマンドに指定してください。
throw
処理されない、または予期されない例外がアプリケーションによって投げ出されると、
throw
イベントが発生します。
throw
type例外 type が
throw
イベントで指定されると、そのタイプの例外のみがthrow
イベントを発生させます。
throw -unhandled
-unhandled
は、投げ出されたが、それに対するハンドラがない例外を示す、特別な例外タイプです。
throw -unexpected
-unexpected
は、それを投げ出した関数の例外仕様を満たさない例外を示す、特別な例外タイプです。
timer
secondsデバッグ中のプログラムが seconds 間実行されると、
timer
イベントが発生します。このイベントで使用されるタイマーは、collector
コマンドで共有されます。解像度はミリ秒であるため、秒の浮動小数点値が使用可能です。イベント指定のための修飾子
イベント指定のため修飾子は、ハンドラの追加属性を設定します。最も一般的な種類はイベントフィルタです。修飾子はイベント指定のキーワードの後に指定しなければなりません。修飾語はすべて '
-
' で始まります (その前にブランクが置かれます)。各修飾子の構成は次のとおりです。
-if
condevent-spec で指定されたイベントが発生したとき、条件 cond が評価されます。イベントは、条件が非ゼロと評価された場合にだけ発生すると考えられます。
-if
が、in
またはat
などの単独のソース位置に基づくイベントで使用された場合、cond はその位置に対応するスコープで評価されます。そうでない場合は、必要なスコープによって正しく修飾する必要があります。
-in
funcハンドラは、指定した関数 func、または func から呼び出された関数によって制御されている間だけ有効になります。関数へ入った回数は、再帰呼び出しに正しく対応するため「参照による計数」が行われます。
-disable
-count
n-count infinity
-count
n および-count infinity
修飾子は、0 からのハンドラカウントを持ちます (「イベントカウンタ」参照)。イベントが発生する度、n に達するまでカウントはインクリメントします。一度それが生じると、ハンドラはファイアし、カウンタはゼロにリセットされます。プログラムが実行または再実行されると、すべてのイベントのカウントがリセットされます。より具体的に言えば、カウントは
sync
イベントが発生するとリセットされます。
-temp
一時ハンドラを作成します。イベントが発生すると、一時イベントは削除されます。デフォルトではハンドラは、一時イベントではありません。ハンドラが計数ハンドラ
(-count
が指定されたイベント) の場合はゼロに達すると自動的に破棄されます。一時ハンドラをすべて削除するには
delete -temp
を実行します。
-instr
イベントを命令レベルで動作させます。これにより、ほとんどの '
i
' で始まるコマンドは不要となります。この修飾子は、イベントハンドラの 2 つの面を修飾します。
-thread
thread_ID指定されたイベントがスレッド識別子 thread_ID に一致するアクティブなスレッドで発生した場合にコマンドを実行します。
-lwp
lwp_ID指定されたイベントが LWP 識別子 lwp_ID に一致するアクティブな LWP で発生した場合にコマンドを実行します。
-hidden
ハンドラが正規の
status
コマンドに示されないようにします。隠されたハンドラを表示するには、status -h
を使用してください。
-perm
通常、すべてのハンドラは、新しいプログラムが読み込まれると廃棄されます。この修飾子を使用すると、ハンドラはデバッグが終わっても保存されます。
delete
コマンド単独では、永続ハンドラは削除されません。永続ハンドラを削除するには、delete -p
を使用してください。解析とあいまいさに関する注意
下位互換性のため、式の中には空白を含むことができます。そのため、式の内容があいまいになることがあります。たとえば、次の 2 つのコマンドがあるとします。
when a -tempwhen a-temp
上の例では、アプリケーションで temp という名前の変数が使用されていても、
dbx
は-temp
を修飾子としてイベント指定を解釈します。下の例では、a-temp
がまとめて言語固有の式解析プログラムに渡され、a および temp という変数が存在しなければ、エラーになります。オプションを括弧で囲むことにより、解析を強制できます。事前定義済み変数
読み取り専用の ksh 事前定義済み変数がいくつか用意されています。以下に示す変数は常に有効です。
function whereami {
echo Stopped in $func at line $lineno in file $(basename $file)
echo "$lineno\t$line"
}
when
コマンドに対して有効な変数
$handlerid
本体の実行中、
$handlerid
にはそれが属するwhen
コマンドの ID が格納されます。次のコマンドは同じ結果になります。
when X -temp { do_stuff; }
when X { do_stuff; delete $handlerid; }
$booting
イベントがブートプロセス中に起こると、
true
(真) に設定されます。新しいプログラムは、デバッグされるたびに、まず共有ライブラリのリストと位置を確認できるよう、ユーザーに通知されないまま実行されます。プロセスはその後終了します。ブートはこのようなシーケンスで行われます。ブートが起こっても、イベントはすべて使用可能です。この変数は、デバッグ中に起こる
sync
およびsyncrtld
のイベントと、通常の実行中に起こるこれらのイベントを区別するときに使用してください。イベント別の有効変数
以下の表で指定されている、特定のイベントの場合のみ有効な変数があります。
表 6-1 sig
イベントに固有の変数$sig
イベントを発生させたシグナル番号 $sigstr
$sig
の名前$sigcode
適用可能な場合、 $sig
のサブコード$sigcodestr
$sigcode
の名前$sigsender
必要であれば、シグナルの送信者のプロセス ID
表 6-2 exit
イベントに固有の変数$exitcode
_exit
(2) またはexit
(3) に渡された引数の値、またはmain
の戻り値
表 6-3 dlopen
およびdlclose
イベントに固有の変数$dlobj
dlopen
またはdlclose
されたロードオブジェクトのパス名
表 6-4 sysin
およびsysout
イベントに固有の変数$syscode
システムコールの番号 $sysname
システムコールの名前
表 6-5 proc_gone
イベントに固有の変数$reason
シグナル、終了、強制終了、または切り離しのいずれか。
イベントハンドラの設定例
配列メンバーへの書き込みに対するウォッチポイントを設定する
(dbx)stop access w &array[99]
(2) stop access w &array[99], 4(dbx)run
実行中: watch.x(プロセス id 9247)ウォッチポイント &array[99] (0x20b68[4]) 行番号 12 ファイル "watch.c"12 array[i] = i;単純なトレースを実行する
(dbx)
when step { echo at line $lineno; }
関数の中だけイベントを有効にする (
in
func)
(dbx)
trace step -in foo
実行された行の数を調べる
(dbx)
stop step -count infinity
# ステップ実行し、count=inf
(関数が 無限大) になったところで停止する(2) stop step -count 0/infinity
(dbx)
run
...
(dbx)
status
(2) stop step -count 133/infinity
ここでは、プログラムを停止させているのではなく、明らかにプログラムが終了しています。133 は実行された行数です。ただし、このプロセスは非常に低速です。この方法が有効なのは、何度も呼び出される関数にブレークポイントを設定している場合です。
実行された命令の数をソース行で調べる
(dbx) ...
# 調べたい行まで移動する(dbx)
stop step -instr -count infinity
(dbx)
step ...
(dbx)
status
(3) stop step -count 48/infinity
# 48 個の命令が実行されたステップ実行している行で関数呼び出しが行われる場合、最終的にそれらの呼び出しもカウントされます。
step
イベントの代わりにnext
イベントを使用すれば、そのような呼び出しはカウントされません。イベント発生後にブレークポイントを有効にする
別のイベントが発生した場合のみ、ブレークポイントを有効にします。たとえば、プログラムで関数
hash
が 1300 番目のシンボル検索以後に正しく動作しなくなるとします。次のように入力します。
(dbx)
when in lookup -count 1300 {
stop in hash
hash_bpt=$newhandlerid
when proc_gone -temp { delete $hash_bpt; }
}
注 -$newhandlerid
が、実行された直後のstop in
コマンドを参照している点に注意してください。
replay
時にアプリケーションファイルをリセットするアプリケーションが処理するファイルを
replay
中にリセットする必要がある場合、プログラムを実行するたびに自動的にリセットを行うハンドラを書くことができます。
(dbx)
when sync { sh regen ./database; }
(dbx)
run < ./database...
# この間にデータベースファイルが壊れた場合
(dbx)
save
...
# run が自動的に行われ、sync イベントが(dbx)
restore
# 発生し、regen が実行される。プログラムの状態を調べる
(dbx)
ignore sigint
(dbx)
when sig sigint { where; cancel; }
プログラムを停止しないでそのスタックトレースを調べるためには、ここで
^C
を押します。コレクタはこれ以外のことも実行できますが、基本的にコレクタの手動標本収集モードが実行する機能は、このように状態を調べます。ここではすでに
^C
を使用したため、プログラムに割り込むにはSIGQUIT
(^\
) を使用します。浮動小数点例外を捕捉する
特定の浮動小数点例外を捕捉します。ここでは、IEEE オーバーフローだけを捕捉しています。
(dbx)
ignore FPE
# デフォルトのハンドラをオフにする
(dbx)
help signals | grep FPE
# サブコードの名前を思い出せない
...
(dbx)
stop sig fpe FPE_FLTUND
...
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |