Rubyの拡張ライブラリィとDBM(GDBM)をデバッグする
Ruby-DBMのテストが通らない原因をいろいろと調べていたのだが、DBMインタフェースの実装として使用しているGDBM(GNU DBM)に問題がある可能性が非常に高くなったので、こいつのデバッグをしてみることにした。
Windows用のGDBMの実装は通常にビルドした場合、動的リンク可能なライブラリィつまりはDLLとして配置されるので、今回の場合
ruby.exe -> dbm.so -> gdbm.dll
と呼ばれてくるはずのgdbm.dllをデバッグしてやる訳だ。
デバッグするためにはそのための情報(デバッグデータベース)が必要だが、デバッグ用の情報を出力するためにはコンパイラとリンカに予めそのことを教えてやる必要がある。最初はMakeFileを書き換えて対応しようと思ったのだが、私にそこまでの(MakeFile書き換えの)知識はまだ無いので、今回はVisual Studio上でプロジェクトを作ってデバッグビルドを行うことでデバッグ情報の生成を行うことにした。
プロジェクトといってもWin32 DLL用の空のプロジェクトを作り、そこに必要なソース、インクルードファイルを読み込ませるだけの簡単なものだ(一部のヘッダファイルは外部ディレクトリから読み込む必要があるので、都度プロジェクトに追加していく)
※コンパイル、リンク時のパラメタとして幾つか気をつけることがあるのだが失念してしまった。
ビルドが成功したならば、デバッグ用のバイナリ(gdbm.dll)とデバッグデータベース(gdbm.pdb)が出来るので、これをrubyインタプリタとdbm.soから見える場所にコピーしておけば準備完了。
デバッグを開始するには、Rubyからスクリプト実行をして適当な場所(データベースをアクセスする直前など)で実行を止める。
この例では日記で何度も取上げているRubyMineによるデバッグセッションのブレークポイントを利用して実行を止めているが、通常のrubyデバッガを使っても問題無いはずだ。
あとはVisual Studioでgdbm.dllをビルドしたプロジェクトから、「デバッグ > プロセスにアタッチ」でRubyインタプリタ(ruby.exe)をアタッチするだけ。
アタッチが完了した所でRubyインタプリタの実行を再開することにより、拡張ライブラリィ(dbm.so)からgdbm.dllのファンクションが呼ばれるとVisual Studioに制御が移り、デバッグが可能となる。