1. 程式人生 > >在Windows中除錯Chromium-UF

在Windows中除錯Chromium-UF

Debugging Chromium on Windows

先參考get the code獲取如果檢出程式碼並編譯。

開始(Getting started)

你可以使用Visual Studio內建的編譯器或者WinDBG來除錯Chromium。你不必為了使用內建的偵錯程式而去用IDE編譯。Ninja 常用來編譯Chromium,大部分開發者直接在命令列中使用它來編譯Chromium,然後在必要的時候開啟IDE來除錯自己關注的部分。在命令列中開始除錯一個exe:

devenv /debugexe out\Debug\chrome.exe <options to Chromium can go here>

假設你已經安裝了 Visual Studio,並且devenv.exe 路徑也在你的PATH環境變數中。注意路徑中必須使用反斜槓,並且必須包含最後的”.exe”字尾,否則僅僅是打開了Visual Studio,而沒有啟動除錯。

Goma(Google內部的分散式編譯器)預設使用的是 symbol_level = 1,這表示原始碼層的除錯將不可用。如果你想要使用Goma來除錯,你需要明確的設定 symbol_level = 2 & is_win_fastlink = true,但是,偵錯程式可能會出錯,所以使用時,請確保使用最新版本的偵錯程式。

配置檔案(Profiles)

在你除錯的時候,使用不同的配置檔案是個好主意。如果你正在除錯一個Google Chrome編譯版的瀏覽器,或者一個Chromium 編譯版的,因為配置檔案的衝突,你將不能同時執行這兩個版本的瀏覽器。將來可能會解決(Google Chrome 和 Chromium 預設使用不同目錄的配置檔案,所以不會衝突了)。使用命令列選項:

--user-data-dir=c:\tmp\my_debug_profile (replace the path as necessary)

在IDE中,選擇 除錯-屬性,並在chrome工程中,設定以上命令列引數。

Chrome除錯日誌(Chrome debug log)

在啟動除錯的時候,傳入--enable-logging --v=1命令列引數,會啟用Chrome 將除錯日誌寫入檔案。Debug版本的將chrome_debug.log日誌檔案放在out\Debug目錄中。Release版本的放在user data頂層的目錄中,具體與系統平臺相關。更多資訊請參考logginguser data directory

符號伺服器(Symbol server)

如果你正在除錯正式的Google Chrome發行版,使用這個符號伺服器:

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

Visual Studio的設定方法:工具-選項-除錯-符號。如果你在本地設定一個快取目錄將會更快。

關於多程序(Multi-process issues)

因為Chromium的multi-process architecture,使得除錯Chromium變得很有挑戰。當你在偵錯程式中選擇執行的時候,只有主程序將會被除錯。渲染web頁面的(Renderer程序)和外掛的程式碼將執行在另外的程序中,所以就沒有被除錯。ProcessExplorer工具有一個程序樹檢視讓你可以檢視這些程序之間的關係。你也可以在Chrome Task Manager中檢視每個標籤對應的程序id(右擊瀏覽器視窗標題的空白部分選擇開啟)。

單程序模式(Single-process mode)

最簡單的除錯問題的方式就是使用單程序模式。這將會讓你看到程序的整個狀態,而沒有其它額外的工作(儘管它仍然有很多執行緒)。新增命令列引數,來啟用單程序模式:

--single-process

在這個模式下,有一些問題將不會表現出來,一些功能也不能正常執行,還有一些執行緒仍然會產生新的程序,所以,也不是很完美。

手動附加到子程序(Manually attaching to a child process)

你可以使用偵錯程式來附加到正在執行的子程序中來除錯。選擇 工具-附加到程序 並選擇 你想除錯的chrome.exe。在附加之前,確認你在Attach to Process視窗中的Native cod選項中選擇了Native。如果你忘記選擇了,預設它會嘗試用”WebKit”模式附加除錯 JavaScript,並且你會得到一個”當前狀態操作不合法”的錯誤訊息。

現在你可以除錯兩個程序了,就好像一個一樣。當你除錯多個程序的時候,開啟 除錯-視窗-程序視窗 來切換它們。

有時候,你除錯的東西可能只發生在啟動的時候,想要在子程序啟動的時候就看見它,使用:

--renderer-startup-dialog --no-sandbox

你必須禁用沙盒,否則彈出的對話方塊將被禁止顯示。當對話框出現後,選擇 工具-附加到程序 就附加到彈出對話方塊的程序了。現在,你就在除錯Renderer程序了,並且可以單機對話方塊中OK按鈕來繼續執行。

其它程序型別也有這種模式的啟動對話方塊:--gpu-startup-dialog, --ppapi-startup-dialog, --plugin-startup-dialog (for NPAPI)

你還可以使用vs谷歌外掛the vs-chromium plug-in來附加到正確程序。

半自動的附加到子程序(Semi-automatically attaching the debugger to child processes)

下面的引數,將會使子程序迴圈等待60秒的時間來讓偵錯程式附加。如果一旦附加上了,它將繼續執行,沒有異常會丟擲。

--wait-for-debugger-children[=filter]

filter引數選項,可以不提供,針對所有子程序。如果提供了,就匹配子程序的--type引數。包括renderer, plugin (for NPAPI), ppapi, gpu-process, and utility

使用這個引數時,限制產生renderer程序的數量或許懟你會有幫助:

--renderer-process-limit=1

映像檔案執行引數(Image File Execution Options)

Using Image File Execution Options (IFEO) will not work because CreateProcess() returns the handle to the debugger process instead of the intended child process. There are also issues with the sandbox.

Visual Studio小技巧(Visual Studio hints)

視覺化除錯(Debug visualizers)

Chrome’s custom debug visualizers should be added to the pdb files and automatically picked up by Visual Studio. The definitions are in //tools/win/DebugVisualizers if you need to modify them (the BUILD.gn file there has additional instructions).

設定不需要單步進入的函式(Don’t step into trivial functions)

The debugger can be configured to automatically not step into functions based on regular expression. Edit default.natstepfilter in the following directory:

  • 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)

Add regular expressions of functions to not step into. Remember to regex-escape and XML-escape them, e.g. < for < and . for a literal dot. Example:

<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>

This file is read at start of a debugging session (F5), so you don’t need to restart Visual Studio after changing it.
More info: Andy Pennel’s Blog, microsoft email thread

除錯V8(V8 and Chromium)

V8 supports many command-line flags that are useful for debugging. V8 command-line flags can be set via the Chromium command-line flag –js-flags; for instance:

chrome.exe --js-flags="--trace_exception --heap_stats"

Note that some V8 command-line flags exist only in the debug build of V8. For a list of all V8 flags try:

chrome.exe --js-flags="--help"

圖形除錯(Graphics debugging)

GPU Acceleration of rendering can be more easily debugged with tools. See:

在另一臺機器上除錯(Debugging on another machine)

Sometimes it’s useful to debug installation and execution on a machine other than your primary build box. To run the installer on said other machine, first build the mini_installer target on your main build machine (e.g., ninja -C out\Debug mini_installer). Next, on the debug machine:

  • Make the build machine’s build volume available on the debug machine either by mounting it locally (e.g., Z:) or by crafting a UNC path to it (e.g., \builder\src)
  • Open up a command prompt and change to a local disk
  • Run src\tools\win[copy-installer.bat](https://code.google.com/p/chromium/codesearch#chromium/src/tools/win/copy-installer.bat) in the remote checkout by way of the mount (e.g., Z:\PATHTOCHECKOUT\src…) or UNC path (e.g., \builder\src…). This will copy the installer, DLLs, and PDBs into your debug machine’s C:\out or C:\build (depending on if you’re rocking the component=shared_library build or not)
  • Run C:\out\Debug\mini_installer.exe with the flags of your choice to install Chrome. This can take some time, especially on a slow machine. Watch the Task Manager and wait until mini_installer.exe exits before trying to launch Chrome (by way of the shortcut(s) created by the installer)
  • For extra pleasure, add C:\out\Debug to your _NT_SYMBOL_PATH environment variable

Consider reading the documentation at the top of copy-installer.bat to see how you can run it. It tries to be smart and copy the right things, but you may need to be explicit (e.g., “copy-installer.bat out Debug”). It is safe to re-run the script to copy only modified files (after a rebuild, for example).

查詢記憶體洩漏(Find memory leaks)

The Windows heap manager has a really useful debug flag, where it can be asked to capture and store a stack trace with every allocation. The tool to scrape these stack traces out of processes is UMDH, which comes with WinDbg.

UMDH is great. It will capture a snapshot of the heap state as many times as you like, and it’ll do it fairly quickly. You then run it again against either a single snapshot, or a pair of snapshots, at which time it’ll symbolize the stack traces and aggregate usage up to unique stack traces.

Turning on the user stack trace database for chrome.exe with gflags.exe makes it run unbearably slowly; however, turning on the user stack trace database on for the browser alone is just fine.

While it’s possible to turn on the user stack database with the “!gflag” debugging extension, it’s too late to do this by the time the initial debugger breakpoint hits. The only reasonable way to do this is to

  1. Launch GFlags.exe,
  2. Enable the user stack trace database (per image below),
  3. Launch Chrome under the debugger.
  4. Set a breakpont when chrome.dll loads with “sxe ld chrome.dll”.
  5. Step up, to allow Chrome.dll to initialize.
  6. Disable the stack trace database in GFlags.exe.
  7. Continue chrome, optionally detaching the debugger.

GFlags.exe settings for user mode stack trace database.

If you then ever suffer a browser memory leak, you can snarf a dump of the process with

umdh -p:<my browser pid> > chrome-browser-leak-umdh-dump.txt

which can then typically be “trivially” analyzed to find the culprit.

其它(Miscellaneous)

  • Application Verifier is a free tool from Microsoft. For the tool to run, you must disable the sandbox (–no-sandbox) and run all app-verified processes in a debugger. This means that you must run the renderer and plugin processes in a debugger or they will fail in mysterious ways. Use any of the methods mentioned above to attach to the renderer processes when they run.
  • To put a breakpoint on CreateFile(), add this break point:

    {,,kernel32.dll}[email protected]28
    {,,kernel32.dll}specifies the DLL (context operator).
    _ prefix means extern "C".
    @28 postfix means _stdcall with the stack pop at the end of the function. i.e. the number of arguments in BYTES.
  • You can use DebugView from SysInternals or sawbuck to view LOG() messages that normally goes to stderr on POSIX.