DAPを使ってmrubyで作ったバイナリをデバッグする話
DAP(Debug Adapter Protocol)のクライアントを作ったので、これを使って今度はmrubyのデバッグに挑戦する。
やりたいのはmrubyで作った実行ファイルのデバッグ。 スクリプト(.rb)やバイナリファイル(.mrb)ファイルのデバッグはmrdbでできるけど、 実行ファイルやmrbgemの部分をデバッグしたい。
nomitoryというものがあって、これでやっていることそのものなんだけど、DAPを使ってもやってみようということを考えた。
どうやればよいかは、nomitoryの記事で書いてくれているので、その通りに進める。
やりたいこと
ユーザからは、元となる○○.rbの△行目にブレークポイントを設定したり、ステップ実行したりする。 それをC言語用のデバッガに変換してやりとりする。そのあいだのやりとりにはDAPを使う。
できたこと
つくったものその1
- code_fetch_hookから呼び出す関数で、実行しているrubyファイルと行数を保存。
- 変数を返す関数を用意。
つくったものその2
GitHub - masahino/mruby-bin-dap-proxy: DAP(Debug Adapter Protocol) proxy for debugging mruby
- IDEやエディタからのリクエストが.rbに関するものなら、対応するC言語に変換してデバッガに渡す。
- mruby-debugでブレイクポイント設定用の関数を用意しておき、そこに対してsetFunctionBreakpoints。conditionでファイル名と行数を指定。
- C言語のデバッガはlldb限定。lldbとのやりとりもDAPを使うので、使うのはlldb-vscodeコマンド。
- デバッガからの応答やイベントも.rbに関するものと判断したら、対応するrubyファイルの情報に変換してIDEやエディタに戻す。
IDEやエディタ側の準備
VScodeの場合
- ubuntuでしか試せていない
- それ用のextensionを用意する。
- デバッグしたいプログラムにmruby-debugを組込む。
- VScodeで.rbファイルにブレークポイントを設定。
- VScodeでlaunch.jsonを作成し、launchかattach。
その他の環境
DAPなので、呼び出す側で少し頑張れば、いろいろな環境で対応できるのではないか。
拙作のテキストエディタでの実行例が以下。
できてないこと
- stepやnextの実行は、ブレークポイントに変換して実行しているため、stopイベントのreasonがbreakpointとなっている。本来はstepの筈。lldbからのeventの中身を見て、stepに書き換えるべきだと思うが、lldb-vscodeからの全部breakpoint 1.1でイベントが来るので、breakpointの場合との区別がつかない。
- 行指定でしかブレークポイントを設定できない。method指定できない。
- 遅い。
- ブレークポイントを指定する.rbファイルの判定が絶対パス指定のため、パスのマッピングが必要な場合があるかもしれない。
- 想定外の動作でイロイロ落ちる。
- デバッグできるようにするための諸々の準備が大変。
- lldb-vscodeのみ対応。
- などなど
準備したけど使わなかったもの
当初は、mruby-gdbというmrbgemを使おうとした。 3.1.0でコンパイルできるようにしたものがこちら。 エラーが出ないようにしただけなので、修正が適切かどうかは不明。
変数の値をパースするのが面倒になったためmruby-debugに方針転換した。