イベント管理は、デバッグ中のプログラムで特定のイベントが発生したときに特定のアクションを実行する、dbx の一般的な機能です。dbx を使用すると、イベント発生時に、プロセスの停止、任意のコマンドの発行、または情報を表示することができます。イベントのもっとも簡単な例はブレークポイントです。その他のイベントの例として、障害、信号、システムコール、dlopen() の呼び出し、およびデータの変更などがあります (「データ変更ブレークポイントを設定する」を参照)。
この付録の内容は次のとおりです。
イベント管理は「ハンドラ」の概念に基づくもので、 この名前はハードウェアの割り込みハンドラからきたものです。通常、ハンドラは各イベント管理コマンドによって作成されます。これらのコマンドは、「イベント指定」と関連する一連のアクションで構成されます。(「イベント指定の設定」参照)。イベント指定は、ハンドラを発生させるイベントを指定します。
イベントが発生し、ハンドラが引き起こされると、イベント指定に含まれる任意の修飾子に従って、ハンドラはイベントを評価します (「イベント指定のための修飾子」参照)。修飾子によって課された条件にイベントが適合すると、ハンドラの関連アクションが実行されます (つまり、ハンドラが起動します)。
プログラムイベントを dbx アクションに対応付ける例は、特定の行にブレークポイントを設定するものです。
ハンドラを作成するもっとも一般的な形は、when コマンドを使用するものです。
when event-specification {action; ... } |
この章の例は、when を使用した表現でコマンド (stop、step、ignore など) を記述する方法を示します。これらの例は、when とその配下にある「ハンドラ」機構の柔軟性を示すものですが、常に同じ働きをするとはかぎりません。
dbx では、イベント機構によって、豊富な種類のブレークポイントが用意されていますが、内部でも多くのイベントが使用されています。これらの内部イベントのいくつかで停止することによって、dbx の内部の動作を簡単に中断することができます。さらに、これらの場合の処理状態を変更すると、中断できる機会が増えます。付録 A プログラム状態の変更と「安全な呼び出し」を参照してください。
場合によっては、dbx は自身を保護して中断を妨げることがありますが、すべての場合ではありません。一部のイベントは下位レベルのイベントという観点で実装されています。たとえば、すべてのステップ実行は fault FLTTRACE イベントに基づきます。そのため、コマンド stop fault FLTTRACE を発行すると、ステップ実行が停止します。
デバッグに続く段階では、dbx はユーザーイベントを処理できません。これは、ユーザーイベントにより精密な内部統合が妨げられるからです。このような段階には次のものが含まれます。
プログラムの起動時に rtld が実行された場合 (「動的リンカー」を参照)
プロセスの開始と終了時
fork()() 関数と exec()() 関数のあと (「fork 機能後のプロセス追跡」と 「exec 機能後のプロセス追跡」を参照)
dbx がユーザープロセスのヘッドを初期化する必要がある場合の呼び出し時 (proc_heap_init())
dbx がスタックのマップされたページを確実に利用できるようにする必要がある場合の呼び出し時 (ensure_stack_memory())
多くの場合、stop コマンドの代わりに when コマンドを使用して、情報を表示することができます。このコマンドを使用しない場合は、対話によって情報を取得する必要があります。
dbx は次のようにして自身を保護します。
sync、syncrtld、および prog_new イベントに stop コマンドを許可しない
rtld ハンドシェーク時および前述の段階で stop コマンドを無視する
次に例を示します。...stopped in munmap at 0xff3d503c 0xff3d503c: munmap+0x0004: ta %icc,0x00000008 dbx76: warning: 'stop' ignored -- while doing rtld handshake
$firedhandlers 変数での記録を含む停止効果のみが無視されます。カウントやフィルタはアクティブなままになります。このような場合で停止させるには、event_safety 環境変数を off に設定します。
イベントハンドラを作成するには、when、stop、trace の各コマンドを使用します (詳細については、「when コマンド」、「stop コマンド」、および 「trace コマンド」を参照)。
共通の when 構文は、stop を使用して簡単に表現できます。
when event-specification { stop -update; whereami; } |
event-specification は、イベント管理コマンド stop、when、trace にて使用され、関心のあるイベントを指定します (「イベント指定の設定」参照)。
trace コマンドのほとんどは、when コマンド、ksh 機能、イベント変数を使用して手動で作成することができます。これは、スタイル化されたトレーシング出力を希望する場合、特に有益です。
コマンドが実行される度に、ハンドラ id (hid) 番号を返します。事前定義変数 $newhandlerid を介してこの番号にアクセスすることができます。
次のコマンドを使用して、イベントハンドラを操作することができます。各コマンドの詳細については、それぞれの節を参照してください。
status – ハンドラを表示します (「status コマンド」参照)。
delete – 一時ハンドラを含むすべてのハンドラを削除します (「delete コマンド」参照)。
clear – ブレークポイントの位置に基づいてハンドラを削除します (「clear コマンド」参照)。
handler -enable – ハンドラを有効にします (「handler コマンド」参照)。
handler -disable – ハンドラを無効にします。
cancel – 信号を取り消し、プロセスを継続させます (「cancel コマンド」参照)。
イベントハンドラはカウンタを備えており、制限値と実際のカウンタを保持します。 イベントが発生するたびにカウンタをインクリメント (1 つ増加) し、ハンドラに関連付けられたアクションが実行されるのは、カウントが制限値に達したときのみで、その時点でカウンタは自動的に 0 にリセットされます。デフォルトの制限値は 1 です。プロセスを再実行する際は常に、すべてのイベントカウンタがリセットされます。
stop、when、trace コマンドで -count 修飾子を使用して、カウント制限を設定することができます (「-count n -count infinity」参照)。このほか、handler コマンドを使用して、個々のイベントハンドラを操作できます。
handler [ -count | -reset ] hid new-count new-count-limit |
イベント指定は、stop、stopi、when、wheni、trace、tracei コマンドで、イベントタイプとパラメータを表すために使用します。その書式は、イベントタイプを表すキーワードと省略可能なパラメータで構成されます。指定子の意味は、一般的にすべてのコマンドで同一です。例外については、コマンドの説明 (「stop コマンド」、「trace コマンド」、「when コマンド」を参照) に記載されています。
ブレークポイントとは、アクションが発生する位置であり、その位置でプログラムは実行を停止します。次に、ブレークポイントイベントに対するイベント仕様を説明します。
関数が入力され、最初の行が実行される直前。先行ログ後の最初の実行可能コードは、実際のブレークポイントの位置として使用されます。この行は、局所変数を初期化する行になることがあります。C++ のコンストラクターの場合、すべてのベースクラスのコンストラクターの実行後に実行されます。-instr 修飾子が使用される場合 (「-instr」参照) は、関数の最初の命令が実行される直前です。function 仕様は、仮パラメータを含むことができるため、多重定義関数名、またはテンプレートインスタンスの指定に役立ちます。たとえば、次のようにします。
stop in mumble(int, float, struct Node *) |
in function と -in function 修飾子とを混同しないでください。
指定の行が実行される直前。filename を指定した場合は、指定ファイルの指定の行が実行される直前。ファイル名には、ソースファイル名またはオブジェクトファイル名を指定します。引用符は不要ですが、ファイル名に特殊文字が含まれる場合は、必要な場合もあります。指定の行がテンプレートコードに含まれる場合、ブレークポイントは、そのテンプレートのすべてのインスタンス上に置かれます。
指定のアドレスの指示が実行される直前。このイベントは stopi コマンド (「stopi コマンド」参照) または -instr イベント修飾子 (「-instr」参照) のみ利用可能です。
このイベントにより、ファイルで定義されたすべての関数にブレークポイントが設定されます。stop infile コマンドは、funcs -f filename コマンドと同様に、同じ関数のリストを繰り返します。
.h ファイル内のメソッド定義、テンプレートファイル、または .h ファイル内のプレーン C コード (regexp コマンドで使用される種類など) は、ファイルの関数定義に寄与する場合がありますが、これらの定義は除外されます。
指定されたファイル名が、オブジェクトファイルの名前の場合 (その場合、名前は .o で終了する)、ブレークポイントは、そのオブジェクトファイルで発生する関数すべてに設定されます。
stop infile list.h コマンドは、list.h ファイルで定義されたメソッドのすべてのインスタンスにブレークポイントを設定することはしません。そうするためには、inclass または inmethod のようなイベントを使用します。
fix コマンドは、関数をファイルから削除する、または追加する場合があります。stop infile コマンドは、ファイル内の関数のすべての古いバージョンと、将来追加されるすべての関数にブレークポイントを設定します。
ネストされた関数や Fortran ファイルのサブルーチンには、ブレークポイントは設定されません。
clear コマンドを使用して、infile イベントによって作成された組にある単一のブレークポイントを無効にできます。
in function と同じ働きを、function と名付けられたすべての多重定義関数、およびテンプレートインスタンスのすべてに対してします。
すべてのクラスに対して、in function または function と名付けられたメンバー関数と同じ働きをします。
in function と同じ働きを、classname のベースではなく、classname のメンバーであるすべてのメンバー関数に対してします。-norecurse はデフォルトです。-recurse が指定された場合、基底クラスが含まれます。
object-expression で示されるアドレスにある特定のオブジェクトに対して呼び出されたメンバー関数が呼び出されました。stop inobject ox はほぼ次のものと同じですが、inclass とは異なり、ox の動的タイプのベースが含まれます。-recurse はデフォルトです。-norecurse が指定された場合、基底クラスが含まれます。
stop inclass dynamic_type(ox) -if this==ox |
メモリーアドレスへのアクセスまたは変更が必要なイベントのイベント指定の例を示します。
address-expression で指定されたメモリーがアクセスされたとき。
mode はメモリーのアクセス方法を指定します。次の文字 (複数可) で構成されます。
指定したアドレスのメモリーが読み取られたことを示します。
メモリーへの書き込みが実行されたことを示します。
メモリーが実行されたことを示します。
さらに mode には、次のいずれかの文字も指定することができます。
アクセス後にプロセスを停止します (デフォルト)。
アクセス前にプロセスを停止します。
いずれの場合も、プログラムカウンタは副作用アクションの前後で違反している命令をポイントします。「前」と「後」は副作用を指しています。
address-expression は、その評価によりアドレスを生成できる任意の式です。シンボル式を使用すると、監視される領域のサイズが自動的に推定されます。このサイズは、byte-size-expression を指定することにより、上書されます。シンボルを使用しない、型を持たないアドレス式を使用することもできますが、その場合はサイズを指定する必要があります。たとえば、次のようにします。
stop access w 0x5678, sizeof(Complex) |
access コマンドには、2 つの一致する範囲が重複しない、という制限があります。
access イベント仕様は、modify イベント仕様の代替です。
variable の値は変更されました。change イベントは、次のコードとほとんど同じ働きをします。
when step { if [ $last_value !=$[variable]] then stop else last_value=$[variable] } |
このイベントはシングルステップを使用して実装されます。パフォーマンス速度を上げるには、access イベント (「access mode address-expression [, byte-size-expression ]」参照) を使用します。
最初に variable がチェックされると、変更が検出されない場合でも 1 つのイベントが発生します。この最初のイベントによって variable の最初の値にアクセスできるようになります。あとから検出された variable の値への変更によって別のイベントが発生します。
condition-expression によって示される条件が真と評価されます。condition-expression には任意の式を使用できますが、整数型に評価されなければなりません。cond イベントは、次のコードとほとんど同じ働きをします。
stop step -if conditional_expression
次に、システムイベントに対するイベント指定について説明します。
これらのイベントは、dlopen() または dlclose() の呼び出しが正常終了したあとに発生します。dlopen() または dlclose() の呼び出しにより、複数のライブラリが読み込まれることがあります。これらのライブラリのリストは、事前定義済み変数 $dllist で常に入手できます。$dllist の中の最初のシェルの単語は実際には「+」または「-」で、それぞれライブラリが追加されているか、削除されているかを示します。
lib-path は、該当する共有ライブラリの名前です。これを指定した場合、そのライブラリが読み込まれたり、読み込みが取り消されたりした場合にだけイベントが起動します。その場合、$dlobj にライブラリの名前が格納されます。また、$dllist も利用できます。
lib-path が / で始まる場合は、パス名全体が比較されます。それ以外の場合は、パス名のベースだけが比較されます。
lib-path を指定しない場合、イベントは任意の dl 動作があるときに必ず起動します。$dlobj は空になりますが、$dllist は有効です。
fault イベントは、指定の障害に遭遇したとき、発生します。障害は、アーキテクチャー依存です。dbx に対して知られる次の一連の障害は、proc(4) マニュアルページで定義されています。
障害 |
内容の説明 |
---|---|
FLTILL |
不正命令 |
FLTPRIV |
特権付き命令 |
FLTBPT* |
ブレークポイントトラップ |
FLTTRACE* |
トレーストラップ (ステップ実行) |
FLTACCESS |
メモリーアクセス (境界合わせなど) |
FLTBOUNDS |
メモリー境界 (無効なアドレス) |
FLTIOVF |
整数オーバーフロー |
FLTIZDIV |
整数ゼロ除算 |
FLTPE |
浮動小数点例外 |
FLTSTACK |
修復不可能なスタックフォルト |
FLTPAGE |
修復可能なページフォルト |
FLTWATCH* |
ウォッチポイントトラップ |
FLTCPCOVF |
CPU パフォーマンスカウンタオーバーフロー |
BPT、TRACE、BOUNDS は、ブレークポイントとステップ実行を実現するため、dbx で使用されます。これらを操作すると、dbx の動作に影響を及ぼす場合があります。
FLTBPT および FLTTRACE は、ブレークポイントやシングルステップ実行などの dbx の基本機能を妨げることがあるため、無視されます (「イベントの安全性」を参照)。
これらの障害は、/sys/fault.h から抜粋されています。fault には前述の名前を大文字または小文字で指定できるほか、実際のコードも指定できます。また、コードの名前には、接頭辞 FLT- を付けることがあります。
fault イベントは、Linux プラットフォームでは使用できません。
lwp_exit イベントは、lwp が終了したとき、発生します。$lwp には、イベントハンドラを維持している間に終了した LWP (軽量プロセス) の id が含まれます。
lwpexit イベントは、Linux プラットフォームでは使用できません。
sig signal イベントは、デバッグ中のプログラムに信号が初めて送られたとき、発生します。signal は、10 進数、または大文字、小文字の信号名のいずれかです。接頭辞は任意です。このイベントは、catch および ignore コマンドからは完全に独立しています。ただし、catch コマンドは次のように実現することができます。
function simple_catch { when sig $1 { stop; echo Stopped due to $sigstr $sig whereami } } |
sig イベントを受け取った時点では、プロセスはまだそれを見ることができません。指定の信号を持つプロセスを継続する場合のみ、その信号が転送されます。
指定の sub-code を持つ指定の信号が child に初めて送られたとき、sig signalsub-code イベントが発生します。信号同様、sub-code は 10 進数として、大文字または小文字で入力することができます。接頭辞は任意です。
指定されたシステムコールが起動された直後で、プロセスがカーネルモードに入ったとき。
dbx の認識するシステムコールは procfs(4) の認識するものに限られます。これらのシステムコールはカーネルでトラップされ、/usr/include/sys/syscall.h に列挙されます。
これは、ABI の言うところのシステムコールとは違います。ABI のシステムコールの一部は部分的にユーザーモードで実装され、非 ABI のカーネルトラップを使用します。ただし、一般的なシステムコールのほとんど (シグナル関係は除く) は syscall.h と ABI で共通です。
sysin イベントは、Linux プラットフォームでは使用できません。
/usr/include/sys/syscall.h 内のカーネルシステムコールトラップのリストは、Solaris OS のプライベートインタフェースの一部です。これはリリースによって異なります。dbx が受け付けるトラップ名 (コード) およびトラップ番号のリストは、dbx がサポートするバージョンの Solaris OS によってサポートされているすべてを含みます。dbx によってサポートされている名前が特定のリリースの Solaris OS でサポートされている名前と性格に一致することはありえないため、syscall.h 内のいくつかの名前は利用可能でない場合があります。すべてのトラップ番号 (コード) は dbx で受け入れられ、予測どおりに動作しますが、既知のシステムコールトラップに対応しない場合は、警告が発行されます。
指定されたシステムコールが終了し、プロセスがユーザーモードに戻る直前。
sysout イベントは、Linux プラットフォームでは使用できません。
引数がないときは、すべてのシステムコールがトレースされます。ここで、modify イベントや RTC (実行時検査) などの特定の dbx は、子プロセスにその目的でシステムコールを引き起こすことがあることに注意してください。トレースした場合にそのシステムコールの内容が示されることがあります。
次に、実行進行状況に関するイベントのイベント仕様について説明します。
next イベントは、関数がステップされないことを除いては、step イベントと同様です。
このイベントは、現在表示されている関数の戻りのブレークポイントです。表示されている関数を使用するのは、いくつかの up を行なったあとに returns イベント指定を使用できるようにするためです。通常の returns イベントは常に一時イベント (-temp) で、動作中のプロセスが存在する場合にだけ作成できます。
returns function イベントは、特定の関数がその呼び出し場所に戻るたびに発生します。これは一時イベントではありません。戻り値は示されませんが、SPARC プラットフォームでは $o0、Intel プラットフォームでは $eax を使用して、必須戻り値を調べることができます。
$o0
$eax
$rax, $rdx
このイベントは、次のコードとほとんど同じ働きをします。
when in func { stop returns; } |
step イベントは、ソース行の先頭の命令が実行されると発生します。たとえば、次のようにシンプルに表現することができます。
when step { echo $lineno: $line; }; cont |
step イベントを有効にするということは、次に cont コマンドが使用されるときに自動的にステップ実行できるように dbx に命令することと同じです。
step (および next) イベントは一般的なステップコマンド終了時に発生しません。step コマンドは step イベントで次のように実装されます。alias step="when step -temp { whereami; stop; }; cont"
次に、その他のタイプのイベントに対するイベント仕様を説明します。
dbx がプロセスを正常に接続した直後。
dbx がプロセスを切り離す直前。
デバッグ中のプロセスが終了しようとしています。これは次の理由によって発生します。
システムコール _exit(2) が呼び出し中 (これは、明示的に呼び出されたとき、または main() のリターン時に発生します)。
終了シグナルが送信されようとするとき。
dbx コマンド kill によってプロセスが強制終了されつつあるとき。
プロセスの最終段階は、必ずではありませんが通常はこのイベントが発生したときに利用可能になり、プロセスの状態を確認することができます。このイベントのあとにプログラムの実行を再開すると、プロセスは終了します。
lastrites イベントは、Linux プラットフォームでは使用できません。
prog_gone イベントは、dbx がデバッグ中のプロセスと関連しなくなるときに発生します。事前定義済み変数 $reason に、signal、exit、kill、または detach のいずれかが設定されます。
follow exec の結果、新規のプログラムがロードされると、prog_new イベントが発生します。
このイベントのハンドラは常に存在しています。
プロセスが停止したとき。特に stop ハンドラによりユーザーがプロンプトを受け取るときのようにプロセスが停止すると、このイベントが起動します。次に例を示します。
display x when stop {print x;} |
デバッグ対象のプロセスが exec() で実行された直後。a.out で指定されたメモリーはすべて有効で存在しますが、あらかじめ読み込まれるべき共有ライブラリはまだ読み込まれていません。たとえば printf は dbx に認識されていますが、まだメモリーにはマップされていません。
stop コマンドにこのイベントを指定しても期待した結果は得られません。when コマンドに指定してください。
sync イベントは、Linux プラットフォームでは使用できません。
syncrtld イベントは、sync のあとに発生します (被デバッグ側が共有ライブラリをまだ処理していない場合は attach のあと)。すなわち、動的リンカーの起動時コードが実行され、あらかじめ読み込まれている共有ライブラリすべてのシンボルテーブルが読み込まれたあと、ただし、.init セクション内のコードがすべて実行される前に発生します。
stop コマンドにこのイベントを指定しても期待した結果は得られません。when コマンドに指定してください。
thr_create イベントは、スレッドまたは thread_id の指定されたスレッドが作成されたときに発生します。たとえば、次の stop コマンドでスレッド ID t@1 はスレッド作成を示しますが、スレッド ID t@5 は作成済みスレッドを示しています。
stop thr_create t@5 -thread t@1 |
thr_exit イベントは、スレッドが終了したときに発生します。指定したスレッドの終了を取り込むには、次のように stop コマンドで -thread オプションを使用します。
stop thr_exit -thread t@5 |
処理されない、または予期されない例外がアプリケーションから投げ出されると、throw イベントが発生します。
throw イベントは、Linux プラットフォームでは使用できません。
例外 type が throw イベントで指定されると、そのタイプの例外のみが throw イベントを発生させます。
-unhandled は、投げ出されたが、それに対するハンドラがない例外を示す、特別な例外タイプです。
-unexpected は、それを投げ出した関数の例外仕様を満たさない例外を示す、特別な例外タイプです。
デバッグ中のプログラムが seconds 間実行されると、timer イベントが発生します。このイベントで使用されるタイマーは、collector コマンドで共有されます。解像度はミリ秒であるため、秒の浮動小数点値 (0.001 など) が使用可能です。
イベント指定のため修飾子は、ハンドラの追加属性を設定します。もっとも一般的な種類はイベントフィルタです。修飾子はイベント指定のキーワードのあとに指定しなければなりません。修飾語はすべて ' -' で始まります (その前にブランクが置かれます)。各修飾子の構成は次のとおりです。
イベント仕様で指定されたイベントが発生したとき、条件が評価されます。イベントは、条件が非ゼロと評価された場合にだけ発生すると考えられます。
-if が、in または at などの単独のソース位置に基づくイベントで使用された場合、cond はその位置に対応するスコープで評価されます。そうでない場合は、必要なスコープによって正しく修飾する必要があります。
-resumeone 修飾子は、-if 修飾子とともにイベント仕様内でマルチスレッドプログラムに対して使用して、条件に関数呼び出しが含まれている場合に 1 つのスレッドのみを再開することができます。詳細については、「条件付イベントでのフィルタの使用」を参照してください。
イベントは、最初の指定 function の命令に達したときから関数が戻るまでの間に発生した場合にのみ開始されます。関数の再帰は無視されます。
-count n および -count infinity 修飾子は、0 からのハンドラカウントを持ちます (「イベントカウンタ」参照)。イベントが発生するたび、n に達するまでカウントはインクリメントします。一度それが生じると、ハンドラはファイアし、カウンタはゼロにリセットされます。
プログラムが実行または再実行されると、すべてのイベントのカウントがリセットされます。より具体的に言えば、カウントは sync イベントが発生するとリセットされます。
カウントは debug -r コマンド (「debug コマンド」参照) または attach -r コマンド (「attach コマンド」参照) を使用して新しいプログラムのデバッグを開始したときにリセットされます。
一時ハンドラを作成します。イベントが発生すると、一時イベントは削除されます。デフォルトではハンドラは、一時イベントではありません。ハンドラが計数ハンドラ (-count が指定されたイベント) の場合はゼロに達すると自動的に破棄されます。
一時ハンドラをすべて削除するには delete -temp を実行します。
イベントを命令レベルで動作させます。これにより、ほとんどの ' i' で始まるコマンドは不要となります。この修飾子は、イベントハンドラの 2 つの面を修飾します。
出力されるどのメッセージもソースレベルの情報ではなく、アセンブリレベルを示す。
イベントの細分性が命令レベルになる。たとえば step -instr は、命令レベルのステップ実行を意味する。
イベントを引き起こしたスレッドが thread_id と一致する場合にかぎり、アクションが実行されます。プログラムの実行を繰り返すうちに特定スレッドの thread_id が変わってしまうことがあります。
イベントを引き起こしたスレッドが lwp_id と一致する場合にかぎり、アクションが実行されます。イベントを引き起こしたスレッドが lwp_id と一致する場合にかぎり、アクションが実行されます。プログラムの実行を繰り返すうちに特定スレッドの lwp_id が変わってしまうことがあります。
ハンドラが正規の status コマンドに示されないようにします。隠されたハンドラを表示するには、status -h を使用してください。
通常、すべてのハンドラは、新しいプログラムが読み込まれると廃棄されます。-perm 修飾子を使用すると、ハンドラはデバッグセッションが終わっても保存されます。delete コマンド単独では、永続ハンドラは削除されません。永続ハンドラを削除するには、delete -p を使用してください。
キーワード駆動型である。
主に、空白によって区切られた「単語」に分割される点など、すべて ksh の規約に基づいている。
下位互換性のため、式の中には空白を含むことができます。そのため、式の内容があいまいになることがあります。たとえば、次の 2 つのコマンドがあるとします。
when a -temp when a-temp |
前述の例では、アプリケーションで temp という名前の変数が使用されていても、dbx は -temp を修飾子としてイベント指定を解釈します。下の例では、a-temp がまとめて言語固有の式解析プログラムに渡され、a および temp という変数が存在しなければ、エラーになります。オプションを括弧で囲むことにより、解析を強制できます。
読み取り専用の ksh 事前定義済み変数がいくつか用意されています。次に示す変数は常に有効です。
変数 |
定義 |
---|---|
$ins |
現在の命令の逆アセンブル |
$lineno |
現在の行番号 (10 進数) |
$vlineno |
現在の表示行番号 (10 進数) |
$line |
現在の行の内容 |
$func |
現在の関数の名前 |
$vfunc |
現在の表示関数の名前 |
$class |
$func が所属するクラスの名前 |
$vclass |
$vfunc が所属するクラスの名前 |
$file |
現在のファイルの名前 |
$vfile |
現在表示しているファイルの名前 |
$loadobj |
現在のロードオブジェクトの名前 |
$vloadobj |
現在表示している現在のロードオブジェクトの名前 |
$scope |
逆引用符表記での現在の PC のスコープ |
$vscope |
現在表示している逆引用符表記での PC のスコープ |
$funcaddr |
$func のアドレス (16 進数) |
$caller |
$func を呼び出している関数の名前 |
$dllist |
dlopen イベントまたは dlclose イベントのあと、ロードされた、またはアンロードされた直後のロードオブジェクトのリストが格納されます。dllist の中の先頭の単語は実際には「+」または「-」です。これは、dlopen と dlclose のどちらが発生したかを示します。 |
$newhandlerid |
最後に作成されたハンドラの ID。この変数は、ハンドラを削除するコマンドのあとの未定義の値です。ハンドラを作成した直後に変数を使用します。dbx では、複数のハンドラを作成する 1 つのコマンドに対してすべてのハンドラ ID を取り込むことはできません。 |
$firedhandlers |
停止の原因となった最近のハンドラ ID のリストです。リストにあるハンドラには、status コマンドの出力時に「*」が付きます。 |
$proc |
現在デバッグ中のプロセスの ID |
$lwp |
現在の LWP の ID |
$thread |
現在のスレッドの ID |
$newlwp |
新しく作成した LWP の lwp ID |
$newthread |
新しく作成したスレッドのスレッド ID |
$prog |
デバッグ中のプログラムの絶対パス名 |
$oprog |
$prog の前の値は、$prog が「-」に戻るときに exec() に続いて、デバッグしていたものに戻る場合に使用します。$prog がフルパス名に展開され、$oprog がコマンド行または debug コマンドに指定されているプログラムパスを含みます。exec() が 2 回以上呼び出されると、オリジナルのプログラムには戻れません。 |
$exec32 |
dbx バイナリが 32 ビットの場合は true です。 |
$exitcode |
プログラムの最後の実行状態を終了します。この値は、プロセスが実際には終了していない場合、空文字列になります。 |
$booting |
イベントがブートプロセス中に起こると、true に設定されます。新しいプログラムは、デバッグされるたびに、共有ライブラリのリストと位置を確認できるよう、まず実行されます。プロセスはそのあと終了します。ブートはこのようなシーケンスで行われます。 ブートが起こっても、イベントはすべて使用可能です。この変数は、デバッグ中に起こる sync および syncrtld イベントと、通常の実行中に起こるイベントを区別するときに使用してください。 |
たとえば、whereami は次のように実装できます。
function whereami { echo Stopped in $func at line $lineno in file $(basename $file) echo "$lineno\t$line" } |
本体の実行中、$handlerid にはそれが属する when コマンドの ID が格納されます。次のコマンドは同じ結果になります。
when X -temp { do_stuff; } when X { do_stuff; delete $handlerid; } |
一部の変数は、以下の表に示すように、when コマンドの本文内および特定のイベント対してのみ有効です。
表 B–1 sig イベントに固有の変数
変数 |
内容の説明 |
---|---|
$sig |
イベントを発生させたシグナル番号 |
$sigstr |
$sig の名前 |
$sigcode |
適用可能な場合、$sig のサブコード |
$sigcodestr |
$sigcode の名前 |
$sigsender |
必要であれば、シグナルの送信者のプロセス ID |
表 B–2 exit イベントに固有の変数
変数 |
内容の説明 |
---|---|
$exitcode |
_exit(2) または exit(3) に渡された引数の値、または main の戻り値 |
表 B–3 dlopen および dlclose イベントに固有の変数
変数 |
内容の説明 |
---|---|
$dlobj |
dlopen または dlclose されたロードオブジェクトのパス名 |
表 B–4 sysin および sysout イベントに固有の変数
変数 |
内容の説明 |
---|---|
$syscode |
システムコールの番号 |
$sysname |
システムコールの名前 |
表 B–5 proc_gone イベントに固有の変数
変数 |
内容の説明 |
---|---|
$reason |
シグナル、終了、強制終了、または切り離しのいずれか。 |
表 B–6 thr_create イベントに固有の変数
変数 |
内容の説明 |
---|---|
$newthread |
新しく作成されるスレッドの ID (t@5 など) |
$newlwp |
新しく作成される LWP の ID (l@4 など) |
表 B–7 watch イベントに有効な変数
変数 |
内容の説明 |
---|---|
$watchaddr |
アドレスが書き込まれたり、読みだされたり、実行されたりします。 |
$watchmode |
次のいずれかです。r は読み込み、w は書き込み、x は実行。そのあとに次のいずれかが続きます。a は後、b は前。 |
次に、イベントハンドラの設定例をあげます。
array[99] でデータ変更ブレークポイントを設定するには、次のように入力します。
(dbx) stop access w &array[99] (2) stop access w &array[99], 4 (dbx) run Running: watch.x2 watchpoint array[99] (0x2ca88[4]) at line 22 in file "watch.c" 22 array[i] = i; |
(dbx) when step { echo at line $lineno; } |
たとえば、
<dbx> trace step -in foo |
は、次のようなスクリプトと等価です。
# create handler in disabled state when step -disable { echo Stepped to $line; } t=$newhandlerid # remember handler id when in foo { # when entered foo enable the trace handler -enable "$t" # arrange so that upon returning from foo, # the trace is disabled. when returns { handler -disable "$t"; }; } |
小規模なプログラムで何行実行されたかを調べます。
(dbx) stop step -count infinity # step and stop when count=inf (2) stop step -count 0/infinity (dbx) run ... (dbx) status (2) stop step -count 133/infinity |
ここでは、プログラムを停止させているのではなく、明らかにプログラムが終了しています。実行された行の数は 133 です。このプロセスは非常に低速です。この方法が有効なのは、何度も呼び出される関数にブレークポイントを設定している場合です。
特定の行で実行された命令の数を数えます。
(dbx) ... # get to the line in question (dbx) stop step -instr -count infinity (dbx) step ... (dbx) status (3) stop step -count 48/infinity # 48 instructions were executed |
ステップ実行している行で関数呼び出しが行われる場合、最終的にそれらの呼び出しもカウントされます。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 中にリセットする必要がある場合、プログラムを実行するたびに自動的にリセットを行うハンドラを書くことができます。
(dbx) when sync { sh regen ./database; } (dbx) run < ./database... # during which database gets clobbered (dbx) save ... # implies a RUN, which implies the SYNC event which (dbx) restore # causes regen to run |
プログラムの実行中にその状態をすばやく調べます。
(dbx) ignore sigint (dbx) when sig sigint { where; cancel; } |
プログラムを停止しないでそのスタックトレースを調べるためには、ここで ^C を押します。
コレクタはこれ以外のことも実行できますが、基本的にコレクタの手動標本収集モードが実行する機能は、このように状態を調べます。ここではすでに ^C を使用したため、プログラムに割り込むには SIGQUIT (^\) を使用します。
特定の浮動小数点例外を捕捉します。ここでは、IEEE オーバーフローだけを捕捉しています。
(dbx) ignore FPE # turn off default handler (dbx) help signals | grep FPE # can’t remember the subcode name ... (dbx) stop sig fpe FPE_FLTUND ... |