dbx コマンドによるデバッグ | ![]() ![]() ![]() ![]() ![]() |
第 19 章
共有ライブラリのデバッグ
dbx
は動的にリンクされた共有ライブラリのデバッグを完全にサポートしています。ただし、これらのライブラリが-g
オプションを使用してインストールされていることが前提になります。動的リンカー
動的リンカーは "
rtld
"、"実行時ld
"、または "ld.so
" とも呼ばれ、実行中のアプリケーションに共有オブジェクト (ロードオブジェクト) を組み込むように準備します。rtld
が稼働状態になるのは主に次の 2 つの場合です。
- プログラムの起動時 - プログラムの起動時、
rtld
はまずリンク時に指定されたすべての共有オブジェクトを動的に読み込みます。ldd
(1) を使用すれば、プログラムによって読み込まれる共有オブジェクトを調べることができます。これらは「あらかじめ読み込まれた」共有オブジェクトで、一般にlibc.so、libC.so、libX.so
などがあります。- アプリケーションから呼び出しがあった場合 - アプリケーションでは、関数呼び出し
dlopen
(3) とdlclose
(3) を使用して共有オブジェクトやプレーンな実行可能ファイルの読み込みや読み込みの取り消しを行います。共有オブジェクト (.so
) や通常の実行可能ファイル (a.out
) のことを、dbx
では「ロードオブジェクト」といいます。
dbx
における loadobject は共有オブジェクト (.so
) または実行可能ファイル (a.out
) を表します。リンクマップ
動的リンカーは、読み込んだすべてのオブジェクトのリストを、link map というリストで管理します。このリストは、デバッグするプログラムのメモリーに保存され、
librctld_db.so
で間接的にアクセスできます。これはデバッガ用に用意された特別なシステムライブラリです。起動手順と
.init
セクション
.init
セクションは、共有オブジェクトの読み込み時に実行される、その共有オブジェクトのコードの一部分です。たとえば、.init
セクションは、C++ 実行時システムがすべての静的初期化関数を呼び出すときに使用します。動的リンカーは最初にすべての共有オブジェクトにマップインし、それらのオブジェクトをリンクマップに登録します。その後、動的リンカーはリンクマップに含まれる各オブジェクトの
.init
セクションを順に実行します。syncrtld イベントは、これら 2 つの動作の間に発生します。プロシージャ・リンケージ・テーブル
PLT は、共有オブジェクトの境界間の呼び出しを容易にするために
rtld
によって使用される構造体です。たとえば、printf
の呼び出しはこの間接テーブルによって行います。その方法の詳細については、SVR4 ABI に関する汎用リファレンスマニュアルおよびプロセッサ固有のリファレンスマニュアルを参照してください。複数の PLT 間で
step
コマンドとnext
コマンドを操作するために、dbx
は各ロードオブジェクトの PLT テーブルを追跡する必要があります。テーブル情報はrtld
ハンドシェークと同時に入手されます。読み込み済みの共有オブジェクトのデバッグサポート
読み込み済みの共有オブジェクトにブレークポイントを設定するには、
dbx
にそのルーチンのアドレスを渡す必要があります。dbx
がルーチンのアドレスを受け取るには、共有オブジェクトベースアドレスが必要です。たとえば以下のような簡単な処理でもdbx
で行うには特別な配慮が必要です。
stop in printfrun新しいプログラムが読み込まれるたびに 、
dbx
はrtld
がリンクマップの作成を完了した場所までプログラムを自動的に実行します。dbx
はリンクマップを読み取り、ベースアドレスを格納します。その後、プロセスは終了し、メッセージとプロンプトが表示されます。dbx
は、これらの動作中にメッセージを表示しません。この時点で、ベース読み込みアドレスとともに
libc.so
のシンボルテーブルを調べることができるため、printf
のアドレスがわかります。
rtld
によってリンクマップが作成されるのを待機し、リンクマップの先頭にアクセスするまでのdbx
の動作を「rtld
ハンドシェーク」と呼びます。rtld
がリンクマップを作成し、dbx
がすべてのシンボルテーブルを読み取ると、イベントsyncrtld
が発生します。修正と継続
dlopen()
で読み込んだ共有オブジェクトに fix と continue を使用する場合、開き方を変更しないと fix と continue が正しく機能しません。モードRTLD_NOW | RTLD_GLOBAL
またはRTLD_LAZY | RTLD_GLOBAL
を使用します。動的にリンクしたライブラリにブレークポイントを設定する
dbx
はdlopen
またはdlclose
の発生を自動的に検出し、読み込まれたオブジェクトの記号テーブルを読み込みます。dlopen()
で共有オブジェクトを読み込むと、そのオブジェクトにブレークポイントを設定できます。またプログラムのその他の任意の場所で行う場合と同様にデバッグも可能です。共有オブジェクトを
dlclose()
で読み込み解除しても、dbx
はそのオブジェクトに設定されていたブレークポイントを記憶しているので、たとえアプリケーションを再実行しても、共有オブジェクトがdlopen()
で再び読み込まれれば再びそのブレークポイントを設定しなおします。(dbx
のバージョン 5.0 より以前のものは、代わりにブレークポイントに '(defunct)' とマーキングします。これはユーザーが削除して置き換える必要があります。)ただし、
dlopen ()
で共有オブジェクトが読み込まれるのを待たなくても共有オブジェクトにブレークポイントを設定したり、その関数やソースコードを検索することはできます。デバッグするプログラムがdlopen()
で読み込む共有オブジェクトの名前がわかっていれば、dbx
をアレンジしてその記号テーブルを、次のコマンドで dbx にあらかじめ読み込んでおくことができます。
loadobjects -p /usr/java1.1/lib/libjava_g.soこれで、
dlopen()
で読み込む前でも、この読み込みオブジェクト内でモジュールと関数を検索してその中にブレークポイントを設定できます。読み込みが済んだら、dbx
はブレークポイントを自動的に設定します。
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |