目前的道路
一年前,Chrome 宣布初步支援 這項工具針對 Chrome 開發人員工具中的 原生 WebAssembly 偵錯
我們展示了基本的步伐支援,並探討一些商機 使用 DWARF 資訊而非 來源對應日後開放使用:
- 解析變數名稱
- 美化排版類型
- 評估原始語言中的運算式
- ...還有更多!
今天我們很高興向大家展示大家承諾使用的功能 Emscripten 和 Chrome 開發人員工具團隊的成長 尤其是 C 和 C++ 應用程式
正式開始前,別忘了這目前是 Beta 版 只有透過最新版所有工具 您必須自行承擔風險。如果遇到任何問題,請回報給 https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350.
讓我們先從上次相同的簡單的 C 範例開始:
#include <stdlib.h>
void assert_less(int x, int y) {
if (x >= y) {
abort();
}
}
int main() {
assert_less(10, 20);
assert_less(30, 20);
}
如要編譯,我們會使用最新的 Emscripten,並傳遞 -g
旗標,就像在原始文章中一樣,納入偵錯資訊:
emcc -g temp.c -o temp.html
現在,我們就能從 localhost HTTP 伺服器提供產生的網頁 (適用於 例如 serve) 請使用最新的 Chrome Canary 開啟應用程式。
這次,我們需要與 Chrome 整合的輔助擴充功能。 並協助解讀所有偵錯資訊 WebAssembly 檔案中編碼請前往以下網頁進行安裝: 連結:goo.gle/wasm-debugging-extension
您也應該在 DevTools 的「Experiments」中啟用 WebAssembly 偵錯功能。開啟 Chrome 開發人員工具,按一下位於⚙ 依序點選「開發人員工具」窗格右上角的「實驗」面板 然後勾選「WebAssembly Debugging:啟用 DWARF 支援」。
關閉「設定」後,開發人員工具會建議重新載入,以便套用設定,因此我們就這麼做吧。一次性 設定。
接下來,我們可以返回「來源」面板,啟用「遇到例外狀況時暫停」(⏸ 圖示),然後勾選「遇到已偵測到的例外狀況時暫停」,並重新載入網頁。您應該會看到開發人員工具在例外狀況時暫停:
根據預設,它會停止在由 Emscripten 產生的黏合程式碼上,但會停留在
右圖顯示了「Call Stack」檢視畫面,代表
並可以前往先前叫用的 C 行
abort
:
現在,您查看「範圍」檢視畫面會顯示原始名稱
以及 C/C++ 程式碼中變數的值,您不再需要
瞭解 $localN
這類的破壞性名稱是什麼意思,以及它們與
所編寫的原始碼
這不僅適用於整數等原始值,也適用於複合值 例如結構、類別、陣列等!
豐富類型支援
一起來看看較複雜的範例。這次我們將使用以下 C++ 程式碼繪製 Mandelbrot 分形:
#include <SDL2/SDL.h>
#include <complex>
int main() {
// Init SDL.
int width = 600, height = 600;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window;
SDL_Renderer* renderer;
SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, &window,
&renderer);
// Generate a palette with random colors.
enum { MAX_ITER_COUNT = 256 };
SDL_Color palette[MAX_ITER_COUNT];
srand(time(0));
for (int i = 0; i < MAX_ITER_COUNT; ++i) {
palette[i] = {
.r = (uint8_t)rand(),
.g = (uint8_t)rand(),
.b = (uint8_t)rand(),
.a = 255,
};
}
// Calculate and draw the Mandelbrot set.
std::complex<double> center(0.5, 0.5);
double scale = 4.0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::complex<double> point((double)x / width, (double)y / height);
std::complex<double> c = (point - center) * scale;
std::complex<double> z(0, 0);
int i = 0;
for (; i < MAX_ITER_COUNT - 1; i++) {
z = z * z + c;
if (abs(z) > 2.0)
break;
}
SDL_Color color = palette[i];
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawPoint(renderer, x, y);
}
}
// Render everything we've drawn to the canvas.
SDL_RenderPresent(renderer);
// SDL_Quit();
}
如您所見 這個例子裡有 50 行程式碼 外部 API,像是 SDL 程式庫 圖形和複數 C++ 標準程式庫。
我將使用與上述相同的 -g
標記來編譯,以便納入偵錯資訊,同時也會要求 Emscripten 提供 SDL2 程式庫,並允許任意大小的記憶體:
emcc -g mandelbrot.cc -o mandelbrot.html \ -s USE_SDL=2 \ -s ALLOW_MEMORY_GROWTH=1
透過瀏覽器造訪產生的網頁時,可以看到 一些隨機色彩的碎形形狀:
再次開啟開發人員工具時,可以看到原始 C++ 檔案。不過,這次程式碼中沒有錯誤 (呼!),因此我們改為在程式碼開頭設定一些中斷點。
當我們重新載入網頁時,偵錯工具會直接在我們的 C++ 來源:
右側可以看到所有變數,但只有 width
和 height
目前已經初始化,所以並沒有太多
現在讓我們在 Mandelbrot 主要迴圈中設定另一個中斷點,然後繼續執行
目前,palette
已填入一些隨機的顏色。
我們可以同時展開陣列本身和
SDL_Color
結構並檢查其元件,以驗證是否
沒有問題 (例如,「Alpha 版」管道一律會
直到完全不透明度為止)。同樣地,我們也可以展開並查看
儲存在 center
變數中複數的虛構部分。
如果您想存取的深層巢狀屬性 前往「Scope」檢視畫面,您可以使用「Console」(控制台)。 以及評估與否!不過請注意,較複雜的 C++ 運算式不會 。
我們可以暫停執行幾次,看看內部 x
的變化情形,方法是再次查看「範圍」檢視畫面、將變數名稱加入監控清單、在控制台中評估,或是將滑鼠游標懸停在原始程式碼中的變數上:
從這裡,我們可以逐步執行或略過 C++ 陳述式,並觀察其他變數的變化情形:
好的,當有偵錯資訊可用時,上述功能就很實用,但 對於不是以偵錯功能建構的程式碼 有哪些選項?
原始 WebAssembly 偵錯
舉例來說,我們要求 Emscripten 為
與其自己從原始碼進行編譯,至少
因為偵錯工具目前無法尋找相關聯的來源。
讓我們再次一步步進入 SDL_RenderDrawColor
:
我們將回到原始的 WebAssembly 偵錯體驗。
雖然這看起來有點嚇人,而且大多數網頁開發人員都不需要處理,但有時您可能需要對沒有偵錯資訊的建構程式庫進行偵錯,可能是因為這是您無法控制的 3rd 方程式庫,或是您遇到只會在實際環境中發生的錯誤。
為協助處理這些情況,我們也對基本偵錯體驗進行了一些改善。
首先,如果您之前使用過原始 WebAssembly 偵錯功能
請注意,整個反組譯碼現在會顯示在單一檔案中
更猜測 Sources 項目 wasm-53834e3e/
wasm-53834e3e-7
可能對應的函式。
新建名稱產生配置
我們也改善了反組譯檢視畫面中的名稱。先前看到的畫面 只是數字索引,而在函式中,則完全沒有名稱。
現在我們產生名稱的方法與其他拆解工具類似
WebAssembly 名稱部分的提示,
匯入/匯出路徑,最後,如果其他連線失敗
這些值取決於項目的類型和索引,例如 $func123
。你可以
以剛才的螢幕擷取畫面為例
以及更易於理解的堆疊追蹤
當沒有可用的類型資訊時,您可能很難檢查基本類型以外的任何值。舉例來說,指標會顯示為一般整數,而您無法得知記憶體中儲存了什麼。
記憶體檢查
先前您只能展開 WebAssembly 記憶體物件 (在「Scope」檢視畫面中以 env.memory
表示)
包括個別位元組這在一些簡單的情況下運作良好,但不太適合擴充,而且不允許以位元組值以外的格式重新解讀資料。我們也新增了線性記憶體檢查器這項功能,可協助您解決這個問題。
如果您在 env.memory
上按一下滑鼠右鍵,現在應該會看到名為「檢查記憶體」的新選項:
點擊完畢後,畫面會顯示記憶體檢查器, 您可以在十六進位和 ASCII 檢視中檢查 WebAssembly 記憶體, 然後前往特定地址 不同格式:
進階情況和注意事項
剖析 WebAssembly 程式碼
開啟開發人員工具時,WebAssembly 程式碼會「降級」至未最佳化的版本,以便進行偵錯。這個版本的速度較慢,因此您無法在 DevTools 開啟時使用 console.time
、performance.now
和其他方法來評估程式碼的速度,因為您取得的數字根本無法代表實際效能。
相反地,您應使用開發人員工具的「效能」面板,該面板會以全速執行程式碼,並提供各函式所花費時間的詳細分析:
或者,您也可以在 開發人員工具關閉後執行應用程式 檢查完成後再開啟即可檢查控制台。
我們日後將會改善剖析情境,但目前主要是 注意所有事項想進一步瞭解 WebAssembly 分層情境,請參閱 WebAssembly 編譯管道的說明文件。
在不同機器 (包括 Docker/主機) 上建構及偵錯
在 Docker、虛擬機器或遠端建構伺服器上進行建構時 您可能會遇到來源檔案路徑 您用於建構作業的檔案系統路徑 Chrome 開發人員工具在這種情況下,檔案會顯示在「Sources」面板中,但無法載入。
為修正這個問題,我們在 C/C++ 擴充功能選項。您可以使用它重新對應任意路徑,並協助開發人員工具找出來源。
舉例來說,如果主體機器上的專案位於路徑底下
C:\src\my_project
,但是在下列位置的 Docker 容器中建構:
該路徑以 /mnt/c/src/my_project
表示,
即可在偵錯期間將這些路徑指定為前置字串:
系統會選擇第一個相符的前置字元。如果您熟悉其他 C++
此選項與 set substitute-path
指令類似
或 LLDB 中的 target.source-map
設定
對最佳化的版本進行偵錯
與其他語言一樣,最佳化功能停用時,偵錯功能的運作效果最佳。最佳化作業可能會將函式內嵌至另一個函式、重新排序 或者移除程式碼的某些部分, 可能混淆偵錯工具,因此您就是使用者。
如果您不介意較受限的偵錯體驗,但仍想對經過最佳化的版本進行偵錯,那麼除了函式內嵌功能外,大部分的最佳化功能都會正常運作。我們會設法解決
日後,請改用 -fno-inline
您在編譯任何 -O
層級最佳化時,請停用該功能,例如:
emcc -g temp.c -o temp.html \ -O3 -fno-inline
分離偵錯資訊
偵錯資訊會保留許多程式碼詳細資料,包括定義的類型、變數、函式、範圍和位置,以及任何對偵錯工具有用的資訊。因此,它通常會比程式碼本身還大。
為加快 WebAssembly 模組的載入和編譯作業,您可能會想要將這些偵錯資訊拆分為個別的 WebAssembly 檔案。如要在 Emscripten 中執行這項操作,請傳遞 -gseparate-dwarf=…
標記,並附上所需的檔案名稱:
emcc -g temp.c -o temp.html \ -gseparate-dwarf=temp.debug.wasm
在這種情況下,主應用程式只會儲存檔案名稱 temp.debug.wasm
,當您開啟 DevTools 時,輔助擴充功能就能找到並載入該檔案。
搭配上述最佳化功能使用時,這項功能甚至可用於發布幾乎已最佳化的應用程式正式版本,並在日後使用本機端檔案進行偵錯。在這種情況下,我們還需要覆寫已儲存的網址,以便擴充功能找到側邊檔案,例如:
emcc -g temp.c -o temp.html \ -O3 -fno-inline \ -gseparate-dwarf=temp.debug.wasm \ -s SEPARATE_DWARF_URL=file://[local path to temp.debug.wasm]
待續...
太好了,那是很多新功能的誕生!
有了這些全新整合功能,Chrome 開發人員工具就成為可行且強大的偵錯工具,不僅適用於 JavaScript,也適用於 C 和 C++ 應用程式,讓您更輕鬆地使用各種技術建構的應用程式,並將其帶入共用的跨平台網頁。
不過,我們的旅程尚未結束。可望 從這裡開始:
- 清除偵錯過程中的粗糙邊緣。
- 新增對自訂類型格式設定器的支援。
- 我們正在努力改善 剖析。
- 新增程式碼涵蓋率支援功能,讓項目更容易找到 未使用的程式碼
- 改善對主控台評估作業中運算式的支援功能。
- 新增支援更多語言。
- …還有更多!
同時,請在自己的程式碼上試用目前的 Beta 版,並將發現的問題回報至 https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350。
下載預覽頻道
建議您使用 Chrome Canary、Dev 或 Beta 版做為預設的開發瀏覽器。透過這些預覽版本,您可以存取開發人員工具中的最新功能、測試最先進的網路平台 API,以及找出網站的問題,以免使用者發現問題。
與 Chrome 開發人員工具團隊聯絡
請使用下列選項,討論文章中的新功能和變更,或任何與開發人員工具相關的內容。
- 歡迎透過 crbug.com 提出建議或意見。
- 在開發人員工具中,依序按一下「更多選項」「說明」>「回報開發人員工具的問題」,即可回報開發人員工具的問題。
- 請在 Twitter 上傳送訊息給 @ChromeDevTools。
- 在 「開發人員工具」新功能 YouTube 影片或 「開發人員工具」秘訣 YouTube 影片中留言。