使用 zxdb 時,您可以控制執行緒的執行作業,協助您進行偵錯。偵錯時,您可以使用下列項目控制執行作業:
執行緒
執行緒是程序中的執行單位。代表可獨立執行的單一指令序列。
如要在 zxdb 中透過執行緒控制執行作業,請參閱「執行緒」。
堆疊框架
堆疊框架是呼叫函式時配置的呼叫堆疊區段。當中儲存函式執行所需的資訊,例如:
- 區域變數:在函式中宣告的變數。
- 參數:傳遞至函式的值。
- 回傳位址:函式完成後要返回的程式碼位置。
如要在 zxdb 中透過堆疊框架控制執行作業,請參閱「堆疊框架」。
執行緒
在 zxdb 中,thread 是可與 zxdb 動詞搭配使用的名詞。
如要列出目前程序中的執行緒:
thread
# State Koid Name
▶ 1 Blocked 1323 initial-thread
2 Running 3462 worker-thread
在某些情況下,您可能會發現執行緒標示為 Blocked,表示執行緒在系統呼叫時停止。通常在偵錯非同步應用程式時,這也可能表示等待時間。
執行緒控制指令僅適用於暫停的執行緒,不適用於遭封鎖或執行的執行緒。暫停執行緒的方法有很多種:
pause 執行緒
舉例來說,如要使用 pause 指令暫停執行緒 2:
thread 2 pause
🛑 syscalls-x86-64.S:67
65 m_syscall zx_port_create 60 2 1
66 m_syscall zx_port_queue 61 2 1
▶ 67 m_syscall zx_port_wait 62 3 0
68 m_syscall zx_port_cancel 63 3 1
69 m_syscall zx_timer_create 64 3 1
當執行緒暫停時,zxdb 會顯示目前的原始碼位置。如果執行緒處於系統呼叫中 (如上述範例),原始碼位置會解析為產生系統呼叫的組合語言巨集檔案中的位置。
如果您在執行 pause 時沒有提供任何額外背景資訊,zxdb 會暫停目前附加的所有程序的所有執行緒。
例如:
pause
508 const zx_port_packet_t* packet))
509
▶ 510 BLOCKING_SYSCALL(port_wait, zx_status_t, /* no attributes */, 3, (handle, deadline, packet),
511 (_ZX_SYSCALL_ANNO(use_handle("Fuchsia")) zx_handle_t handle, zx_time_t deadline,
512 zx_port_packet_t* packet))
🛑 $elf(SYSCALL_zx_port_wait) + 0x7 • syscalls.inc:510
continue 執行緒
暫停執行緒並開始偵錯問題後,您可能想要continue執行緒。繼續執行表示恢復執行作業,直到程式正常完成為止。
舉例來說,如要 continue 執行執行緒 1:
thread 1 continue
如果您在執行 continue 時未提供任何額外內容,zxdb 會繼續執行所有附加程序的所有執行緒。
例如:
continue
逐步執行執行緒
暫停執行緒後,您可以控制執行緒的執行作業。你可以使用下列任一指令:
finish(fi)結束函式,並在呼叫後立即停止。
finishnext(n)前進至下一行,略過函式呼叫。
nextnexti前進至下一個指令,但略過目標架構的呼叫指令。
nextiss列出目前行上的函式呼叫,並逐步執行所選呼叫。系統會自動結束先接聽的通話。
ss 1 std::string::string 2 MyClass::MyClass 3 HelperFunctionCall 4 MyClass::~MyClass 5 std::string::~string quit >step(s)前進至下一行程式碼。如果函式呼叫發生在下一行之前,系統會進入該函式,並在函式開頭停止執行。
您也可以提供引數子字串,比對特定函式呼叫。系統會略過不含引數子字串的函式名稱,並只逐步執行相符的函式。
step [zxdb] step MyFunctionstepi正好前進一個機器指令。
stepiuntil(u)指定行位置後,繼續執行執行緒,直到抵達該位置為止。舉例來說,如要執行到目前檔案的第
45行,請輸入:until 45您也可以執行程式,直到執行作業返回指定的堆疊框架為止:
frame 2 until
堆疊框架
堆疊框架是函式呼叫。當函式呼叫另一個函式時,系統會建立新的影格。列出執行緒的影格會傳回呼叫堆疊。
如要列出目前執行緒中的堆疊框架:
frame
▶ 0 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:203
1 fxl::CommandLineFromArgcArgv() • command_line.h:224
2 main() • main.cc:174
使用堆疊框架時,0 表示堆疊頂端,也就是執行作業的結尾。堆疊底部 (即堆疊影格編號最高的位置) 表示執行作業的開始。
瀏覽堆疊框架
您可以使用 up 和 down 指令瀏覽影格清單。
舉例來說,使用 up 從目前的影格 0 導覽至影格 1:
up
1 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:204
舉例來說,使用 down 從目前的影格 1 導覽至影格 0:
[zxdb] down
0 fxl::CommandLineFromIteratorsFindFirstPositionalArg<const char *const *>() • command_line.h:185
您也可以使用 frame 指令搭配影格編號,前往特定影格:
frame 1
詳情請參閱 backtrace
在某些情況下,您可能想查看堆疊框架未提供的額外位址資訊。backtrace 指令與 frame 相同,但會提供更詳細的地址資訊和函式參數。
如要列出目前執行緒中的堆疊框架,但提供更詳細的資訊,請使用 backtrace:
backtrace
▶ 0 fxl::CommandLineFromIteratorsFindFirstPositionalArg<const char *const *>() • command_line.h:185
IP = 0x10f982cf2ad0, BP = 0x66b45a01af50, SP = 0x66b45a01af38
first = (const char* const*) 0x59f4e1268dc0
last = (const char* const*) 0x59f4e1268dc8
first_positional_arg = (const char* const**) 0x0
1 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:204
IP = 0x10f982cf2ac0, BP = 0x66b45a01af50, SP = 0x66b45a01af40
first = <'first' is not available at this address. >
last = <'last' is not available at this address. >
...
使用 list 查看原始碼
每個堆疊框架都有程式碼位置。使用 list 指令查看原始碼。
您可以列出特定堆疊框架的指令指標周圍的程式碼。
舉例來說,如要 list 堆疊框架指令指標周圍的原始碼 3:
frame 3 list
如果您在沒有內容的情況下使用 list,zxdb 會列出目前堆疊框架指令指標附近的原始碼:
list
183 inline CommandLine CommandLineFromIteratorsFindFirstPositionalArg(
184 InputIterator first, InputIterator last,
▶ 185 InputIterator* first_positional_arg) {
186 if (first_positional_arg)
187 *first_positional_arg = last;
list 的其他用途
此外,您可以使用 list 列出特定事項:
函式
使用 list 列出函式:
list MyClass::MyFunc
檔案
使用 list 列出特定檔案:
list --all myfile.cc:1
顯示行號的檔案
使用 list 列出特定檔案和特定行號:
list foo.cc:43