デバッガモジュールは、一群の dcmd および walker を提供し、これらのモジュールを mdb(1) に読み込んで、実行時リンカーのさまざまな内部データ構造を検査するために使用できます。実行時リンカーの内部データ構造を理解するには、実行時リンカー内部に関する知識が必要であり、また、これはリリースごとに異なる可能性があります。しかし、これらの情報は、動的にリンクされたプロセスの基本的な構成要素を明らかにし、さまざまなデバッグを助けます。
次の例では、mdb(1) とこのデバッガモジュールの使用方法に関するシナリオをいくつか紹介します。
$ cat main.c
#include <dlfcn.h>
main()
{
void * handle;
void (* fptr)();
if ((handle = dlopen("foo.so.1", RTLD_LAZY)) == NULL)
return (1);
if ((fptr = (void (*)())dlsym(handle, "foo")) == NULL)
return (1);
(*fptr)();
return (0);
}
$ cc -o main main.c -R. -ldl
|
mdb(1) がデバッガモジュール ld.so を自動的に読み込まなかった場合は、明示的に読み込んでください。それにより、デバッガモジュールの機能を確認できます。
$ mdb main > ::load ld.so > ::dmods -l ld.so ld.so ----------------------------------------------------------------- dcmd Dl_handle - display Dl_handle structure dcmd Dyn - display Dynamic entry dcmd List - display entries in a List dcmd ListRtmap - display a List of Rt_Map's dcmd Lm_list - display ld.so.1 Lm_list structure dcmd Permit - display Permit structure dcmd Rt_map - display ld.so.1 Rt_map structure dcmd Rt_maps - display list of Rt_map structures walk List - walk List structure walk Rt_maps - walk list of Rt_map structures > ::bp main > :r |
プロセス内の動的オブジェクトは、リンクマップ Rt_map として表現され、このリンクマップは、リンクマップリスト上で管理されています。プロセスのすべてのリンクマップは、Rt_maps を使用して表示できます。
> ::Rt_maps
Objects on linkmap: <base>
rtmap* ADDR NAME
---------------------------------------------
0xff3b0030 0x00010000 main
0xff3b0434 0xff3a0000 /usr/lib/libdl.so.1
0xff3b0734 0xff280000 /usr/lib/libc.so.1
Objects on linkmap: <ld.so.1>
rtmap* ADDR NAME
---------------------------------------------
0xff3f7c68 0xff3c0000 /usr/lib/ld.so.1
|
個々のリンクマップは、Rt_map を使用して表示できます。
> 0xff3b0030::Rt_map
Rt_map located at: 0xff3b0030
NAME: main
ADDR: 0x00010000 DYN: 0x000209d8
NEXT: 0xff3b0434 PREV: 0x00000000
.....
LIST: 0xff3f60cc [ld.so.1`lml_main]
|
オブジェクトの .dynamic セクションは、Dyn dcmd を使用して表示できます。次の例は、最初の 4 つのエントリを表示しています。
> 0x000209d8,4::Dyn Dyn located at: 209d8 0x209d8 NEEDED 0x000001d7 Dyn located at: 209e0 0x209e0 NEEDED 0x000001e2 Dyn located at: 209e8 0x209e8 INIT 0x00010870 Dyn located at: 209f0 0x209f0 FINI 0x000108c0 |
mdb(1) は、遅延ブレークポイントを設定するときにとても有用です。次の例では、関数 foo() にブレークポイントを設定しています。 foo.so.1 に対して dlopen(3DL) が実行されるまでは、このシンボルはデバッガにとって未知であるにもかかわらず、遅延ブレークポイントを設定すると、動的オブジェクトが読み込まれたときに、実ブレークポイントが設定されます。
> ::bp foo.so.1`foo > :r > mdb: You've got symbols! > mdb: stop at foo.so.1`foo mdb: target stopped at: foo.so.1`foo: save %sp, -0x68, %sp |
この時点で、新しいオブジェクトが読み込まれました。
> *ld.so`lml_main::Rt_maps rtmap* ADDR NAME --------------------------------------------- 0xff3b0030 0x00010000 main 0xff3b0434 0xff3a0000 /usr/lib/libdl.so.1 0xff3b0734 0xff280000 /usr/lib/libc.so.1 0xff3b0c1c 0xff370000 ./foo.so.1 0xff3b1030 0xff350000 ./bar.so.1 |
foo.so.1 のリンクマップは、dlopen(3DL) から返されたハンドルを示しています。Dl_handle を使用して、ハンドルの構造体を展開できます。
> 0xff3b0c1c::Rt_map
Rt_map located at: 0xff3b0c1c
NAME: ./foo.so.1
ADDR: 0xff370000 DYN: 0xff3805c8
NEXT: 0xff3b1030 PREV: 0xff3b0734
FCT: 0xff3f6080
.......
PERMIT: 0xff3b0f94 HANDLE: 0xff3b0f38
> 0xff3b0f38::Dl_handle
Dl_handle located at: ff3b0f38
permit: 0xff3b0f7c
usercnt: 1 permcnt: 2
depends: 0xff3b0f44 [0xff3b0fc4, 0xff3b1358]
parents: 0xff3b0f4c [0x00000000, 0x00000000]
|
ハンドルの依存関係は、dlsym(3DL) 要求を満たすハンドルのオブジェクトを表現するリンクマップのリストです。
> 0xff3b0f44::ListRtmap Listnode data next Rt_map name --------------------------------------------- 0xff3b0fc4 0xff3b0c1c 0xff3b1358 ./foo.so.1 0xff3b1358 0xff3b1030 0x00000000 ./bar.so.1 |
上の例は、デバッガモジュールの機能の基礎的な紹介になっていますが、正確なコマンド、使用方法、および出力は、リリースごとに異なる可能性があります。お使いのシステムで利用できる正確な機能については、それぞれのマニュアルまたはヘルプを参照してください。