GDB JIT 編譯介面整合
GDB JIT 編譯介面整合讓 V8 能夠提供 GDB 來自 V8 執行時期發出的原生程式碼的符號和除錯資訊。
當 GDB JIT 編譯介面停用時,GDB 中的典型回溯包含標記為 ??
的框架。這些框架對應於動態產生的程式碼
#8 0x08281674 in v8::internal::Runtime_SetProperty (args=...) at src/runtime.cc:3758
#9 0xf5cae28e in ?? ()
#10 0xf5cc3a0a in ?? ()
#11 0xf5cc38f4 in ?? ()
#12 0xf5cbef19 in ?? ()
#13 0xf5cb09a2 in ?? ()
#14 0x0809e0a5 in v8::internal::Invoke (construct=false, func=..., receiver=..., argc=0, args=0x0,
has_pending_exception=0xffffd46f) at src/execution.cc:97
然而,啟用 GDB JIT 編譯介面讓 GDB 能夠產生更具資訊性的堆疊追蹤
#6 0x082857fc in v8::internal::Runtime_SetProperty (args=...) at src/runtime.cc:3758
#7 0xf5cae28e in ?? ()
#8 0xf5cc3a0a in loop () at test.js:6
#9 0xf5cc38f4 in test.js () at test.js:13
#10 0xf5cbef19 in ?? ()
#11 0xf5cb09a2 in ?? ()
#12 0x0809e1f9 in v8::internal::Invoke (construct=false, func=..., receiver=..., argc=0, args=0x0,
has_pending_exception=0xffffd44f) at src/execution.cc:97
GDB 仍未知的框架對應於沒有來源資訊的原生程式碼。請參閱 已知限制 以取得更多詳細資料。
GDB JIT 編譯介面在 GDB 文件中指定:https://sourceware.org/gdb/current/onlinedocs/gdb/JIT-Interface.html
先決條件 #
- V8 v3.0.9 或更新版本
- GDB 7.0 或更新版本
- Linux 作業系統
- 具有 Intel 相容架構 (ia32 或 x64) 的 CPU
啟用 GDB JIT 編譯介面 #
GDB JIT 編譯介面目前預設從編譯中排除,並在執行時期停用。若要啟用它
- 使用已定義的
ENABLE_GDB_JIT_INTERFACE
建立 V8 函式庫。如果您使用 scons 建立 V8,請使用gdbjit=on
執行它。 - 在啟動 V8 時傳遞
--gdbjit
旗標。
若要檢查您是否已正確啟用 GDB JIT 整合,請嘗試在 __jit_debug_register_code
上設定中斷點。這個函式會被呼叫以通知 GDB 有關新的程式碼物件。
已知限制 #
JIT 介面的 GDB 端目前 (截至 GDB 7.2) 無法非常有效地處理程式碼物件的註冊。每次後續註冊都會花費更多時間:有 500 個已註冊物件時,每次後續註冊會花費超過 50 毫秒,有 1000 個已註冊程式碼物件時,會花費超過 300 毫秒。這個問題已 回報給 GDB 開發人員,但目前沒有可用的解決方案。為了降低對 GDB 的壓力,目前的 GDB JIT 整合實作以兩種模式運作:預設和完整(由
--gdbjit-full
旗標啟用)。在預設模式中,V8 僅通知 GDB 有關附加來源資訊的程式碼物件(這通常包含所有使用者指令碼)。在完整模式中,則通知所有產生的程式碼物件(存根、IC、跳板)。在 x64 上,GDB 無法在沒有
.eh_frame
區段的情況下適當地解開堆疊 (問題 1053)GDB 未收到關於從快照反序列化的程式碼的通知 (問題 1054)
僅支援 Intel 相容 CPU 上的 Linux 作業系統。對於不同的作業系統,應產生不同的 ELF 標頭或使用完全不同的物件格式。
啟用 GDB JIT 介面會停用壓縮 GC。這樣做是為了減輕 GDB 的負擔,因為註銷和註冊每個移動的程式碼物件會產生相當大的負擔。
GDB JIT 整合僅提供近似的來源資訊。它不提供任何關於局部變數、函式的引數、堆疊配置等的資訊。它無法逐步執行 JavaScript 程式碼或在給定的行上設定中斷點。不過,可以透過函式名稱在函式上設定中斷點。