開發軟體時,開發人員必須處理程式當機問題,以及找出 錯誤來源Fuchsia 提供一組有助找出及診斷的工具 以便解決元件相關問題 核心程式碼中偵錯。
分析當機事件
Fuchsia 在開機時啟動名為 crashanalyzer
的程式,藉此回報計畫
當機並列印至系統記錄中當機執行緒的回溯追蹤記錄。雖然您可以直接在執行階段查看記錄,但回溯內容會使用堆疊記憶體位址參照編碼,而非指向程式來源檔案中的對應行。
[klog][I] devmgr: crash_analyzer_listener: analyzing exception type 0x108
[klog][I] <== fatal exception: process crasher[42410] thread initial-thread[42424]
[klog][I] <== fatal page fault, PC at 0x1e1888dbbbd7
[klog][I] CS: 0 RIP: 0x1e1888dbbbd7 EFL: 0x10246 CR2: 0
[klog][I] RAX: 0 RBX: 0x1 RCX: 0x721ad98697c6 RDX: 0x77accb36f264
[klog][I] RSI: 0 RDI: 0 RBP: 0x2781c4816f90 RSP: 0x2781c4816f80
[klog][I] R8: 0 R9: 0 R10: 0 R11: 0x246
[klog][I] R12: 0x773bf11dcda0 R13: 0x773bf11dcdd0 R14: 0x16 R15: 0x78050d69
[klog][I] errc: 0x6
[klog][I] bottom of user stack:
[klog][I] 0x00002781c4816f80: f11dcda0 0000773b 9ccd2b38 000039b2 |....;w..8+...9..|
[klog][I] 0x00002781c4816f90: c4816fd0 00002781 88dbbba7 00001e18 |.o...'..........|
[klog][I] 0x00002781c4816fa0: 00000008 00000000 9ccd2b38 000039b2 |........8+...9..|
[klog][I] 0x00002781c4816fb0: f11dcf70 0000773b f11dcf70 0000773b |p...;w..p...;w..|
[klog][I] 0x00002781c4816fc0: cb36f570 000077ac f11dcdd0 0000773b |p.6..w......;w..|
[klog][I] 0x00002781c4816fd0: c4816ff0 00002781 cb2b0d0f 000077ac |.o...'....+..w..|
[klog][I] 0x00002781c4816fe0: 00000054 00000000 f11dcf70 0000773b |T.......p...;w..|
[klog][I] 0x00002781c4816ff0: f11dcfe0 0000773b 00000000 00000000 |....;w..........|
[klog][I] arch: x86_64
[klog][I] dso: id=a94c78564173530d51670b6586b1aa471e004f06 base=0x7d3506a49000 name=libfdio.so
[klog][I] dso: id=a61961ba9776a67a00fb322af9ebbdcfd1ce3f62 base=0x77accb297000 name=libc.so
[klog][I] dso: id=760f1e6e47d3dd8b6a19150aa47241279ec75a9c base=0x721ad9863000 name=<vDSO>
[klog][I] dso: id=b18462140c6784a53736105bbf3021852eeda68c base=0x1e1888dbb000 name=app:crasher
[klog][I] bt#01: pc 0x1e1888dbbbd7 sp 0x2781c4816f80 (app:crasher,0xbd7)
[klog][I] bt#02: pc 0x1e1888dbbba7 sp 0x2781c4816fa0 (app:crasher,0xba7)
[klog][I] bt#03: pc 0x77accb2b0d0f sp 0x2781c4816fe0 (libc.so,0x19d0f)
[klog][I] bt#04: pc 0 sp 0x2781c4817000
[klog][I] bt#05: end
這是因為根據預設,除錯符號會在建構期間從核心二進位檔中移除。如要正確分析當機記錄,您必須將這些符號重新套用至回溯追蹤,以便查看原始碼行號的呼叫堆疊。當您呼叫 ffx log
指令時,開發人員工具
透過名為 symbolizer
的額外二進位檔處理原始記錄檔
將本機建構設定中的符號重新套用至
。
ffx log
您看到的輸出內容會包含重新套用至 Backtrace 的符號:
[klog][I] devmgr: crash_analyzer_listener: analyzing exception type 0x108
... same output as "raw" backtrace ...
start of symbolized stack:
[klog][I] #01: blind_write at ../../src/developer/forensics/crasher/cpp/crasher.c:21
[klog][I] #02: main at ../../src/developer/forensics/crasher/cpp/crasher.c:137
[klog][I] #03: start_main at ../../zircon/third_party/ulib/musl/src/env/__libc_start_main.c:49
[klog][I] #04: unknown, can't find pc, sp or app/library in line
end of symbolized stack
有了適當符號化的回溯追蹤,您就能直接在原始碼中找出當機的網站。
逐行偵錯
光是知道程式當機的地方,可能不夠充分
診斷問題。有時需要逐步完成
甚至是檢查記憶體中的變數狀態為了支援這項功能
Fuchsia 針對名為 zxdb
的核心程式碼提供偵錯工具。
zxdb
工具是用戶端,可連線至目標裝置上執行的 debug_agent
元件。您可以使用 zxdb
指令來設定
debug_agent
可附加至特定程序並設定中斷點。偵錯
zxdb
會附加至執行中的程序,可讓您逐步完成
以及檢查堆疊框架
設定偵錯工作階段需要下列高階步驟:
- 在目標裝置上執行
debug_agent
元件。 - 執行
zxdb
用戶端,並連線至目標裝置。 - 設定
zxdb
的位置以尋找偵錯符號。
啟動偵錯工作階段最簡單的方法,是使用 ffx debug connect
指令,上述所有操作都會在您的 Fuchsia 本機版本環境中執行。
不過,如果您需要設定
所以需要分開管理
偵錯工作階段啟用後,系統會帶您前往 [zxdb]
提示,以便您發出偵錯工具指令。您可以使用 zxdb
來設定要附加的 debug_agent
並使用名稱篩選器套用至處理程序,並設定待處理中斷點
比對程序正在執行。
以下範例會在主執行緒上設定待處理中斷點,在 並等待執行「hello-world」程序開始日期:
[zxdb] attach hello-world
Waiting for process matching "hello-world"
[zxdb] break main
Breakpoint 1 (Software) on Global, Enabled, stop=All, @ main
Pending: No matches for location, it will be pending library loads.
將偵錯工具附加到處理程序後,即可使用 zxdb
指令
控管及檢查程序狀態以下是一些
常用指令:
step
|
瀏覽執行緒中的下一行程式碼 |
next
|
逐步執行執行緒中的下一行程式碼 |
continue
|
繼續執行,直到下一個中斷點、例外狀況或結束 |
frame
|
列出或選取目前的堆疊框架 |
print
|
評估運算式並輸出結果 |
練習:使用 Fuchsia 偵錯工具
在本練習中,您將使用 Fuchsia 偵錯工具 (zxdb
) 檢查 echo
元件的執行中例項,並瞭解當機的原因。
啟動模擬器
如果您尚未擁有執行中的執行個體,請透過網路啟動 FEMU 支援服務:
ffx emu start workstation_eng.x64 --headless
啟動偵錯工作階段
模擬器啟動後,使用下列指令啟動 zxdb
偵錯工作階段:
ffx debug connect
指令:
ffx debug connect
Connecting (use "disconnect" to cancel)...
Connected successfully.
👉 To get started, try "status" or "help".
[zxdb]
連線成功後,zxdb
提示字元就會開始接受指令。
附加至元件
啟動元件前,請先設定 zxdb
以附加至
echo
。這樣就能在程序開始時立即附加偵錯工具:
[zxdb] attach echo
在 greeting()
函式上設定中斷點:
[zxdb] break greeting
偵錯工具準備就緒後,請啟動新的 echo
元件執行個體:
ffx component run /core/ffx-laboratory:echo fuchsia-pkg://fuchsiasamples.com/echo-example#meta/echo.cm
探索偵錯工作階段
到達 greeting()
的中斷點時,執行作業就會停止並偵錯工具
等待新指令。使用 list
指令顯示執行作業的位置
目前已暫停:
[zxdb] list
17
18 // Return a proper greeting for the list
▶ 19 std::string greeting(std::vector<std::string>& names) {
20 // Join the list of names based on length
21 auto number_of_names = names.size();
22 switch (number_of_names) {
23 case 0:
24 return "Nobody!";
25 case 1:
26 return join(names, "");
27 case 2:
28 return join(names, " and ");
29 default:
使用 next
指令逐步進入 greeting()
函式:
[zxdb] next
print
指令會輸出目前堆疊中所有變數的狀態
相框。顯示 names
目前的值:
[zxdb] print names {"Alice", "Bob", "Spot"}
使用 next
逐步執行 greeting()
函式幾次:
[zxdb] next
如要讓程式繼續執行至結束,請使用 continue
指令:
[zxdb] continue
結束偵錯工作階段,返回終端機:
[zxdb] exit
加入一些當機程式碼
接著,您要在 main()
中新增一些程式碼,造成元件停止運作
或是恐慌。如要模擬這種行為,只需新增 strlen(nullptr)
參照即可
收集到引數後:
echo/main.cc
:
int main(int argc, const char* argv[], char* envp[]) {
// ...
// Simulate a crash
std::strlen(nullptr);
// Print a greeting to syslog
std::cout << "Hello, " << echo::greeting(arguments) << "!" << std::endl;
return 0;
}
建構更新後的套件並發布至 fuchsiasamples.com
存放區:
bazel run //fuchsia-codelab/echo:pkg.publish -- \
--repo_name fuchsiasamples.com
使用 zxdb
啟動新的偵錯工作階段:
ffx debug connect
針對當機時的堆疊框架進行偵錯
設定要附加至 echo
元件的偵錯工具:
[zxdb] attach echo
啟動新的元件執行個體:
ffx component run /core/ffx-laboratory:echo fuchsia-pkg://fuchsiasamples.com/echo-example#meta/echo.cm --recreate
這次,偵錯工具偵測到例外狀況已擲回並停止執行作業:
Attached Process 1 state=Running koid=1164808 name=echo.cm
════════════════════════════════════════════════
Page fault reading address 0x0 (second chance)
════════════════════════════════════════════════
Process 1 (koid=1164808) thread 1 (koid=1164810)
Faulting instruction: 0x43e0fd349210
🛑 strlen(const char*) • strlen.c:21
[zxdb]
使用 frame
指令檢查當機時的堆疊追蹤:
[zxdb] frame
▶ 0 strlen(…) • strlen.c:21
1 main(…) • main.cc:27
2 «libc startup» (-r expands)
3 «libc startup» (-r expands)
4 $elf(_start) + 0x11
請注意,堆疊追蹤中的第 1 行代表 main.cc
中
發生當機情形,對應 nullptr
參照。
目前的堆疊框架 (頁框 0) 位於系統程式庫的深處,但 只要在指令前加上頁框編號 擷取及寫入堆疊追蹤
如要輸出當機點的引數值,請按照下列方式傳遞影格編號:
[zxdb] frame 1 print arguments {"Alice", "Bob", "Spot"}
退出偵錯工作階段,返回終端機:
[zxdb] exit
刪除執行個體
使用下列指令清除 echo
執行個體:
ffx component destroy /core/ffx-laboratory:echo