| 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. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |