Windowsでのデバッグ

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.logout\Debugに作成する。リリースビルドではChromiumアプリディレクトリに置くが、これはOS依存。ロギングユーザデータディレクトリ?を参照。

Symbolサーバ

公式のGoogle Chromeリリースビルドをデバッグするなら、以下のシンボルサーバが使える。

 
https://chromium-browser-symsrv.commondatastorage.googleapis.com

Visual Studioでは、Debugging > SymbolsTools > 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&lt;.*&gt;::.*</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_PATHC:\out\Debugを追加する。

copy_installer.batの最初に書いてある文書を読むこと。このファイルは再度実行しても問題ない。

メモリリークを見つける

Windowsのヒープマネージャは役立つデバッグフラグを持っている。すべてのメモリ割り当てのスタックトレースをキャプチャする。WinDbgとUMDHでこれらスタックとレースをプロセスからscrapeできる。

UMDHは偉大。ヒープ状態のスナップショットをキャプチャし、スタックトレースをシンボル化し使用集計をユニークスタックトレースへまとめる。

gflagsをつかってユーザスタックトレースデータベースを有効にできる。とても遅くなるがブラウザプロセスだけやればよい。

"!gflag"デバッグ拡張でユーザスタックデータベースを有効にできるが、ブレークポイントがヒットした時点ではすでに遅い。正しいやり方は以下。

  1. GFlags.exeを起動
  2. (イメージごとの)ユーザスタックトレースデータベースを有効に
  3. デバッガー下でChromeを起動
  4. chrome.dllがロードしたときブレークするブレークポインタを設定 "sxe ld chrome.dll"
  5. ステップ実行しChrome.dllを初期化
  6. GFlags.exeでスタックトレースデータベースを無効化
  7. chromeを継続実行し、必要ならデバッガから切り離す
GFlags.exe
GFlags.exeでユーザモードスタックトレースデータベースを設定

ブラウザのメモリリークで困っているなら、以下のコマンドでダンプを吐き出す。

 
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()メッセージを見れる。
Page last modified on June 17, 2019, at 11:30 PM
Powered by PmWiki