控制线程执行

使用 zxdb 时,您可以控制线程的执行,以帮助您进行调试。 在调试时,您可以通过以下方式控制执行:

  • 线程

    线程是进程中的执行单元。它表示可以独立执行的单个指令序列。

    如需了解如何在 zxdb 中通过线程控制执行,请参阅 线程

  • 堆栈帧

    堆栈帧是调用函数时分配的调用堆栈的一部分。它存储函数执行所需的信息,例如:

    • 局部变量:在函数内声明的变量。
    • 参数:传递给函数的值。
    • 返回地址:函数完成后要返回的代码中的位置。

    如需了解如何在 zxdb 中通过堆栈帧控制执行,请参阅 堆栈帧

线程

在 zxdb 中,一个 thread 是一个 名词,您可以将其与 zxdb 动词一起使用。

如需列出当前进程中的线程,请执行以下操作:

thread
  # State   Koid Name
▶ 1 Blocked 1323 initial-thread
  2 Running 3462 worker-thread

在某些情况下,您可能会注意到某个线程被标记为 Blocked,这意味着该线程在系统调用中停止。通常,当您调试异步应用时,这可能也表示等待时间。

线程控制命令仅适用于已暂停的线程,而不适用于已阻塞或正在运行的线程。您可以通过多种方式暂停线程:

  • 一个 断点 停止了线程。
  • 使用 pause 命令。

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)

    退出函数并在调用后立即停止。

    finish
    
  • next (n)

    前进到下一行,跳过函数调用。

    next
    
  • nexti

    前进到下一条指令,但跳过目标架构的调用指令。

    nexti
    
  • ss

    列出当前行的函数调用,并进入所选调用。这会自动完成任何首先发生的其他调用。

    ss
      1 std::string::string
      2 MyClass::MyClass
      3 HelperFunctionCall
      4 MyClass::~MyClass
      5 std::string::~string
      quit
    >
    
  • step (s)

    前进到下一行代码。如果函数调用发生在下一行之前,则会进入该函数,并且执行会在该函数的开头停止。

    您还可以提供实参子字符串来匹配特定的函数调用。 系统会跳过不包含实参子字符串的函数名称,并且 只会进入匹配的函数。

    step
    [zxdb] step MyFunction
    
  • stepi

    准确前进一条机器指令。

    stepi
    
  • until (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 表示堆栈的顶部,表示执行结束。堆栈的底部(即最高的堆栈帧编号)表示执行开始。

您可以使用 updown 命令浏览帧列表。

例如,使用 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