DAPを使ってmrubyで作ったバイナリをデバッグする話

DAP(Debug Adapter Protocol)のクライアントを作ったので、これを使って今度はmrubyのデバッグに挑戦する。

masahino123.hatenablog.com

やりたいのはmrubyで作った実行ファイルのデバッグスクリプト(.rb)やバイナリファイル(.mrb)ファイルのデバッグはmrdbでできるけど、 実行ファイルやmrbgemの部分をデバッグしたい。

nomitoryというものがあって、これでやっていることそのものなんだけど、DAPを使ってもやってみようということを考えた。

magazine.rubyist.net

どうやればよいかは、nomitoryの記事で書いてくれているので、その通りに進める。

やりたいこと

ユーザからは、元となる○○.rbの△行目にブレークポイントを設定したり、ステップ実行したりする。 それをC言語用のデバッガに変換してやりとりする。そのあいだのやりとりにはDAPを使う。

できたこと

つくったものその1

GitHub - masahino/mruby-debug

  • 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の場合

VSCodeでのmrubyデバッグ

その他の環境

DAPなので、呼び出す側で少し頑張れば、いろいろな環境で対応できるのではないか。

拙作のテキストエディタでの実行例が以下。

mrbmacs

できてないこと

  • 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に方針転換した。