https://www.chromium.org/developers/how-tos/debugging-on-windows
始める
Visual StudioやWinDBGが使える。ビルドするのにIDEは必要ないが、デバッグでは使える。デバッグを開始するには以下のコマンドを実行。
devenv /debugexe out\Debug\chrome.exe <options to Chromium can go here>
Visual Studioがインストールされていてパスが通っていることが前提、depot_toolsにパスが通っている必要はない。devenv.exeでなくdevenv.comのほうがいいのかもしれない。chrome.exeは後々chrome.dllやcontent.dllなどの大きなPDBをもつモジュールをロードし、とても重くなる。他のプロセスも実行するのでデバッグは難しくなる。
Goma(Googleの内部配布ビルド)ではsymbol_level=1になっていて、ソースコードレベルでのデバッグができない。Gomaをフルデバッグしたい場合はSymbol_level=2とis_win_fastlink=1が必要。しかしこれはデバッガのバグを引き起こすかもしれない。最新のデバッガを使うようにするべき。
Profiles
デバッグ用に別のプロファイルを使うのがいい。Google ChromeのブランドビルドやChromiumをデバッグしているならプロファイルが衝突し、同時に実行することができない、また安定ビルドのブラウザが未来のプロファイルを参照してしまうかもしれない。(Google ChromeとChromiumのプロファイルは今は衝突しない)。プロファイル指定のコマンドラインは以下。
--user-data-dir=c:\tmp\my_debug_profile (replace the path as necessary)
IDEを使うならデバッグタブに移動し、コマンド引数に追加する。
Chromeデバッグログ
--enable-logging --v=1
でChromeのデバッグログを有効にできる。デバッグビルドはchrome_debug.log
をout\Debug
に作成する。リリースビルドではChromiumアプリディレクトリに置くが、これはOS依存。ロギングとユーザデータディレクトリ?を参照。
Symbolサーバ
公式のGoogle Chromeリリースビルドをデバッグするなら、以下のシンボルサーバが使える。
https://chromium-browser-symsrv.commondatastorage.googleapis.com
Visual Studioでは、Debugging > SymbolsのTools > Optionsにある。ローカルキャッシュを持てば速くなる。
マルチプロセス問題
Chromiumはマルチプロセスなのでデバッグが大変になる。デバッガで実行するとき、メインのブラウザプロセスだけがデバッグ対象になる。レンダラやプラグインは他のプロセスなのでデバッグ対象にならない。ProcessExplorerではプロセスをツリー上に表示できる。ChromeのタブごとのプロセスIDが確認できる。
シングルプロセスモード
もっとも簡単な方法はシングルプロセスモードを使う方法。これでプログラムのすべての状況をしることができる。シングルプロセスモードを使うには以下のコマンドラインフラグを指定する。
--single-process
このやり方は完全ではない。問題が現象しないかもしれないし、いくつかの機能を動かないかもしれない。
子プロセスに手動でアタッチ
デバッガで実行中の子プロセスにアタッチできる。Tools > Attachでchrome.exeにアタッチする。ネイティブコードのみが選択されていることを確認すること。これを忘れると、"WebKit"モードでJavascriptへのアタッチを試みて、エラー"An operation is not legal in the current state"が発生する。
これで2つのプロセスを1つのようにデバッグできる。多数のプロセスをデバッグするならDebug > Windows > Processedを開き切り替えられる。
スタートアップでのみ実行されるコードをデバッグするには以下を使う。
--render-startup-dialog --no-sandbox
サンドボックスは無効にしないとダイアログが表示されない。ダイアログが表示されたら、Tools > Attach to Processしてプロセスにアタッチする。他のプロセスの場合、以下のような引数を使う。
--gpu-startup-dialog --ppapi-startup-dialog --plugin-startup-dialog
vs-chromiumプラグインで正しいプロセスにアタッチできる。
子プロセスの準自動アタッチ
以下のフラグを指定すると子プロセスはあ60秒ビジーループで待つ。
--wait-for-debugger-children[=filter]
filterがあれば、--typeパラメータをフィルタする。renderer
,plugin
(for NPAPI),ppapi
,gpu-process
and utility
.
以下のオプションで、レンダラプロセスの個数を指定できる。
--renderer-process-limit=1
イメージファイル実行オプション
Image File Execution Options(IFEO)は機能しない。CreateProcess()はデバッガプロセスのハンドルを返すため。サンドボックスとの問題もある。
Visual Studioヒント
デバッグヴィジュアライザー
TODO
ささいな関数にステップインしない
ステップインしない関数を正規表現で指定できる。以下のフォルダの設定ファイル.natstepfilter
を編集する。
- For Visual Studio 2015: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Packages\Debugger\Visualizers (for all users) or %USERPROFILE%\My Documents\Visual Studio 2015\Visualizers (for the current user only)
- For Visual Studio 2017 Pro: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Packages\Debugger\Visualizers (for all users) or %USERPROFILE%\My Documents\Visual Studio 2017\Visualizers (for the current user only)
以下の内容を追加
<?xml version="1.0" encoding="utf-8"?> <StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010"> <Function><Name>operator new</Name><Action>NoStepInto</Action></Function> <Function><Name>operator delete</Name><Action>NoStepInto</Action></Function> <!-- Skip everything in std --> <Function><Name>std::.*</Name><Action>NoStepInto</Action></Function> <!-- all methods on WebKit OwnPtr and variants, ... WTF::*Ptr<*>::* --> <Function><Name>WTF::.*Ptr<.*>::.*</Name><Action>NoStepInto</Action></Function> </StepFilter>
このファイルはデバッグ実行時(F5)に読み込まれるのでVisual Studioを再起動する必要はない。
V8とChromium
V8はデバッグをサポートする豊富なコマンドラインフラグを持っている。Chromiumのコマンドラインで--js-flags
経由で渡すことができる。
chrome.exe --js-flags="--trace_exception --heap_stats"
このコマンドラインフラグはデバッグ版のV8にしか存在しない。すべてのV8フラグを見るには以下を行う。
chrome.exe --js-flags="--help"
グラフィックのデバッグ
レンダリングのGPU加速はツールを使って容易にデバッグできる。以下を参照
他のマシンでデバッグ
他のマシンにデバッグ環境を構築すると有益なこともある。他のマシン(デバッグマシン)にデバッグ環境を構築するには最初にビルドマシンでmini_installerターゲットをビルドする。(
ninja -C out\Debug mini_installer@@)。次にデバッグマシンで以下の事を行う。
- ビルドマシンのビルドボリュームをマウントするかUNCで見えるようにする。
- コマンドプロンプトを開き、ローカルディスクに移動する。
src\tools\win\copy-installer.bat
を先ほどのマウントポイントから実行する。これはインストーラやDLL、PDBをデバッグマシンのC:\out
またはC:\build
にコピーする(コンポーネントビルドしたかどうかで異なる)。C:\out\Debug\mini_installer.exe
を必要ならフラグを添えて実行し、タスクマネージャでインストーラがchrome.exeを実行するまで監視。_NT_SYMBOL_PATH
にC:\out\Debug
を追加する。
copy_installer.bat
の最初に書いてある文書を読むこと。このファイルは再度実行しても問題ない。
メモリリークを見つける
Windowsのヒープマネージャは役立つデバッグフラグを持っている。すべてのメモリ割り当てのスタックトレースをキャプチャする。WinDbgとUMDHでこれらスタックとレースをプロセスからscrapeできる。
UMDHは偉大。ヒープ状態のスナップショットをキャプチャし、スタックトレースをシンボル化し使用集計をユニークスタックトレースへまとめる。
gflagsをつかってユーザスタックトレースデータベースを有効にできる。とても遅くなるがブラウザプロセスだけやればよい。
"!gflag"
デバッグ拡張でユーザスタックデータベースを有効にできるが、ブレークポイントがヒットした時点ではすでに遅い。正しいやり方は以下。
GFlags.exe
を起動- (イメージごとの)ユーザスタックトレースデータベースを有効に
- デバッガー下でChromeを起動
- chrome.dllがロードしたときブレークするブレークポインタを設定
"sxe ld chrome.dll"
- ステップ実行しChrome.dllを初期化
GFlags.exe
でスタックトレースデータベースを無効化- chromeを継続実行し、必要ならデバッガから切り離す
ブラウザのメモリリークで困っているなら、以下のコマンドでダンプを吐き出す。
umdh -p:<my browser pid> > chrome-browser-leak-umdh-dump.txt
典型的には「ささいな」犯人が見つかる。
その他いろいろ
- アプリケーションべりファイアはマイクロソフトのフリーツール。ツールの実行にはサンドボックスの無効化が必要(
--no-sandbox
)。そうしてアプリが認証したプロセスをデバッガで実行する。つまりレンダープロセスやプラグインプロセスはデバッガで実行する必要がある、そうしないと変な風になる。上述した方法でアタッチする必要がある。 CreateFile()
にブレークポイントを設定するには以下のようにする。
{,,kernel32.dll}_CreateFileW@28
{,,kernel32.dll}
はDLLを指定する(コンテキストオペレータ)。_
プリフィックスはextern "C"を意味する。- @28は
_stdcall
を意味する。関数の終わりでスタックがポップする。つまり引数のバイト数。
- SysInternalsのDebugViewやsawbuckで通常POSIXではstderrへいくLOG()メッセージを見れる。