Ruby拡張ライブラリをデバッグする

静的リンクもしくは動的リンクでデバッグする方法があるようです。

今回は動的リンクでやってみました。
題材はpcaprubというRubyからpcapファイルを使うためのライブラリです。
ライブラリを使うa.rbから、test.pcapファイルを読み込むためにpcaprubを使います。

デバッグシンボルはあったほうがデバッグしやすいので、
拡張ライブラリを-gつきでコンパイルしておきます

gdbを起動します

$ gdb ruby 

とりあえずmainにブレークポイントをはって、起動します

(gdb) b main
(gdb) r a.rb test.pcap

Ruby は dln_loadでライブラリを読み込むようです
そこにもブレークポイントをはって、実行を再開します

(gdb) b dln_load
(gdb) c

ライブラリのロード部分でブレークします
encdb.soが読み込まれました

Breakpoint 2, dln_load (file=0x737400 "/home/yu74n/.../enc/encdb.so") at dln.c:1250

確認してみましょう*1

(gdb) i sharedlibrary
From                To                  Syms Read   Shared Object Library
(*snip*)
0x00007ffff619b680  0x00007ffff619c2b8  Yes         /home/yu74n/.../enc/encdb.so

デバッグしたい拡張ライブラリが現れるまでスキップします

(gdb) c
Continuing.

Breakpoint 2, dln_load (file=0x8a9b90 "/home/yu74n/.../pcaprub.so") at dln.c:1250

現れたので確認してみます

(gdb) i sharedlibrary
0x00007ffff5d918c0  0x00007ffff5d94058  Yes         /home/yu74n/.../pcaprub.so

ありましたね

あとはデバッグしたい場所にブレークポイントをはると
ブレークします

(gdb) b rbpcap_next_packet
Breakpoint 3 at 0x7ffff5d92520: file pcaprub.c, line 802.
(gdb) c
Continuing.

Breakpoint 3, rbpcap_next_packet (self=8914880) at pcaprub.c:802
warning: Source file is more recent than executable.
802	{	

ソースを見てみます

(gdb) l
797	* If the next_packet() is unsuccessful, Null is returned.
798	*/
799	
800	static VALUE
801	rbpcap_next_packet(VALUE self)
802	{	
803		rbpcap_t *rbp;
804		rbpcapjob_t job;
805		char eb[PCAP_ERRBUF_SIZE];
806		int ret;	

*1:ブレークしてしばらくnextで進んだ後に実行してください