はじめに
特に必要に迫られたという事ではないが、デバッガについて色々調べている過程で、標準以外のnetcoreデバッガを見つけたので記事にしておく。
リポジトリリンクは以下。
https://github.com/Samsung/netcoredbg
vscode上のnetcoreappデバッグについて
さて、vscodeでのC#アプリのデバッグはomnisharp-vscodeという拡張が担当しているが、これがどういう仕組みで動いているかというと、C#用デバッガが、Debug Adapter Protocol(DAP)というHTTP(のようなもの)+JSONなプロトコルを使用して、vscodeと通信してあれこれしている。詳細はDAP公式ページを参照。
Language Server Protocol(LSP)のデバッガ版だと思えば良いと思う。設計者が同じMSだし。
ちなみにDAPと同じような役割を持つプロトコルがgdbにもあり、そちらはGDB/MIと呼ばれている。デバッガ関連のドキュメントでちょくちょくMIという名前が出てくるのはこれが由来。
GDB/MIの方が当然歴史は長いが、DAPがHTTP(のようなもの)+JSONであるのに対し、MIが行ベースのやり取りなので、jsベースのvscodeでは、DAPのようなプロトコルの方が扱いやすいというのが、DAPを作った動機だろうと推測される。
さて、現在omnisharp-vscodeでは、デバッガに当たる部分にvsdbgというものを使用している。しかしこのvsdbg、機能的には問題ないのだが、ソースが公開されていない。
各種ドキュメントを見るに、恐らくVisual Studioの一部としてビルドされていると思われるので、分離もしにくく、またしたところであまりメリット無さそうという判断なのかもしれない。
そういうわけで、実際の細かい挙動はあまり把握できないので、実際にどう動いているのかという所はわからずじまいとなる。
そこで代替実装はないかと探したところ、netcoredbgというものが見つかった(SamsungといえばTizenがあるのでそれ関連?)。
こちらはオープンソースで、かつaCute(eclipse上でc#を使うための拡張)でも使用されていると聞いたので、実績も期待できる。というわけで、こちらを動かしてみる。
バイナリの準備
netcoredbgはスタンドアローンのプログラムになっているが、バイナリの取得方法についてはいくつか方法があるので記述する。
なお、バイナリの動作確認は/path/to/netcoredbg --help
でヘルプが表示されればOKということになる。
公式ビルド
githubのリリースページからバイナリをDLして展開する。
ソースからビルド
ソースからコンパイルして使う場合、以下の手順でバイナリをビルドする。要はcmakeとdotnet sdkという理解でOK。
準備(Windows)
以下のソフトが必要
- Visual Studio 2019以降
- VC++とWindows SDKを有効にしておく
- cmake
- VSが2019以降の場合、3.14以降が必要
- git
- .NET SDKとdotnet/runtimeのソースコードを取得するため
-
最新安定版の.NET SDK
- .NET SDKのダウンロードをしたくない場合
準備(Linux)
- clang
- cmake
- autotools
- ninjaでも可かもしれない
- git
- .NET SDKとdotnet/runtimeのソースコードを取得するため
-
最新安定版の.NET SDK
- .NET SDKのダウンロードをしたくない場合
ビルド
必要なソフトが揃ったら、以下の手順でビルドする
- ビルド出力ディレクトリを作成
-
build
ディレクトリ等 - ツリーの外でも可
-
- カレントディレクトリを作成したディレクトリに変更
-
cmake -G [ジェネレーター] -DCMAKE_INSTALL_PREFIX=/path/to/install/dir [ソースルートディレクトリ]
でConfigure- この時にどこにインストールするか決まるので注意
- ジェネレーター引数(
-G [ジェネレーター]
)は無くても可 -
-G
で使える引数は、cmake --help
で閲覧可能 - この時、ソースルートに
.dotnet
と.coreclr
というディレクトリ名でcoreclrのソースとdotnetバイナリがダウンロードされるため、既存のものを利用したい場合は-DCORECLR_DIR
と-DDOTNET_DIR
で指定すること
- ソースルートディレクトリに戻る
-
cmake --build [ビルド出力ディレクトリ]
でビルド -
cmake --build [ビルド出力ディレクトリ] --target install
でバイナリが-DCMAKE_INSTALL_PREFIX
で指定したディレクトリにコピーされる
VSCodeでの使用
vscode上で使用する場合、launch.json
のエントリに以下のように指定する
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/path/to/debuggee.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false,
"pipeTransport": {
"pipeCwd": "${workspaceFolder}",
"pipeProgram": "cmd",
"pipeArgs": ["/c"],
"debuggerPath": "/path/to/netcoredbg"
}
}
]
}
前後に設定が色々書いてあるが、重要なのはpipeTransport
の部分である。
ここに、pipeProgramとpipeArgsには、デバッガを起動するシェルを指定するものという理解でいいと思う。詳しくは、vscode-cpptoolsのドキュメントに書いてある。
後は通常通りvscodeのデバッグを実行すれば、netcoredbgを用いてデバッグが実行される。
サポートされる機能
netcoredbgでは、ブレークポイントで停止したり、条件付きのブレークポイントの設置等、基本的な機能はサポートされているが、それでも全ての機能をサポートしているわけではない。何ができて何ができないか、という詳細は以下のページを参照。
https://github.com/Samsung/netcoredbg/wiki/Features
目立ったところでは、"全ての例外でブレークする"という機能がまだ動かない(ハンドルされてない例外でのブレークは可能)。
また、サポートされるのはあくまでもnetcoreapp*
のデバッグのみで、net4*
なアプリに対してのデバッグはできないので注意が必要。正確には起動自体はできるものの、ブレークポイント等の機能が利用できない。
ログ出力
さて、細かい挙動を確認したい場合や、トラブルシューティングしたい場合、ログ出力が必要となる。
標準入出力はDAPでやり取りするため使えないので、別途ログ出力機構を利用する必要がある。
DAP部分のログ出力
netcoredbgでログ出力したい場合は、launch.jsonにlogging
オプションを追加する。具体的には以下のようになる。
{
"version": "0.2.0",
"configurations": [
{
..
"logging": {
"engineLogging":true
}
}
]
}
上記設定を適用すると、vscodeのデバッグウィンドウにDAPのやり取りログが出力される
netcoredbg内部のログ出力
"engineLogging"では、主にプロトコル部分のログ出力を取得可能だが、netcoredbg自体の内部的な動作をログ出力したい場合、netcoredbgのコマンド引数に--log=file
を指定する。
具体的には以下のようになる。
{
"version": "0.2.0",
"configurations": [
{
..
"pipeTransport": {
..
"debuggerPath": "/path/to/netcoredbg --log=file"
}
}
]
}
上記を指定すると、[tmpディレクトリ]/netcoredbg_*
という名前でログファイルが出力される。なお、ファイル名に開始時点の時刻情報が入るため、複数回実行する場合はファイル数の増大に注意すること。また、ローリング(ファイルサイズに応じて新しくファイルを作成すること)機能はないため、ファイルサイズの増大に注意すること。
終わりに
まあ正直な話、vsdbg自体に機能的な不満はあまりないので、大抵の人は使う必要は無いと思う。だが、デバッガの具体的な挙動が知りたい場合、あるいはvsdbgでは動作しないような特殊環境でデバッグしたい場合、netcoredbgのようなツールが有用になるだろうと思う。
更に、デバッギングについてのあれやこれやを知りたい場合、netcoredbgのリンク集が参考になるかもしれない