dbx コマンドによるデバッグ ホーム目次前ページへ次ページへ索引


第 19 章

共有ライブラリのデバッグ

dbx は動的にリンクされた共有ライブラリのデバッグを完全にサポートしています。ただし、これらのライブラリが -g オプションを使用してインストールされていることが前提になります。

この章は、次の各節から構成されています。

動的リンカー

動的リンカーは "rtld"、"実行時 ld"、または "ld.so" とも呼ばれ、実行中のアプリケーションに共有オブジェクト (ロードオブジェクト) を組み込むように準備します。rtld が稼働状態になるのは主に次の 2 つの場合です。

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 printf
run

新しいプログラムが読み込まれるたびに 、dbxrtld がリンクマップの作成を完了した場所までプログラムを自動的に実行します。dbx はリンクマップを読み取り、ベースアドレスを格納します。その後、プロセスは終了し、メッセージとプロンプトが表示されます。dbx は、これらの動作中にメッセージを表示しません。

この時点で、ベース読み込みアドレスとともに libc.so のシンボルテーブルを調べることができるため、printf のアドレスがわかります。

rtld によってリンクマップが作成されるのを待機し、リンクマップの先頭にアクセスするまでの dbx の動作を「rtld ハンドシェーク」と呼びます。rtld がリンクマップを作成し、dbx がすべてのシンボルテーブルを読み取ると、イベント syncrtld が発生します。

修正と継続

dlopen() で読み込んだ共有オブジェクトに fix と continue を使用する場合、開き方を変更しないと fix と continue が正しく機能しません。モード RTLD_NOW | RTLD_GLOBAL または RTLD_LAZY | RTLD_GLOBAL を使用します。

動的にリンクしたライブラリにブレークポイントを設定する

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