gdb的多线程调试

一些术语
all-stop mode      全停模式
single-stepping    单步执行
scheduler-locking  调度锁
schedule-multiple  多进程调度
record mode        记录模式
replay mode        回放模式

inferior
GDB用 inferior 来表示每个程序执行,inferior 与进程对应,也可用于没有进程的target。
Inferiors在进程运行之前创建,在进程退出之后保留。Inferior 也有自己的标记,这个标记与PID不同。
通常,每个inferior都有自己的不同地址空间,一些嵌入式 targets 可以在一个地址空间的不同部分运行不同的 inferior。
每个 inferior 内可以有多个线程运行。

(gdb) info threads
(gdb) thread n
(gdb) set scheduler-locking [off|on|step]
(gdb) set schedule-multiple [off|on]
(gdb) show scheduler-locking
(gdb) show schedule-multiple

在开始之前先说一些技巧吧:
1  如果你在程序没运行前想设置 scheduler-locking 的状态,总是给出如下的提示:
   Target 'exec' cannot support this command.
   那你可以先在 main 函数处打个断点,break main ,等待运行后停在断点处,再执行你的设置。
   其实可以在任何断点停住的地方进行设置。

2  在线程的代码里设置了断点,那遇到断点所有的线程都会停止。且自动切换到断点所在线程。
   info threads 列出的线程列表里,当前线程前边有个 * 号。


5.5.1 All-Stop Mode

In all-stop mode,  whenever your program stops under GDB for any reason,  all threads of  execution
stop,  not just the current thread.  This allows you to examine the overall state of  the  program,
including switching between threads, without worrying that things may change underfoot.

在全停模式下,当你的程序由于任何原因在 GDB 下停止时,不止当前的线程停止,所有的执行线程都停止。这样允许你检查程
序的整体状态,包括线程之间的切换,不用担心当下会有什么改变。

Conversely, whenever you restart the program,  all threads start executing.  This is true even when
single-stepping with commands like step or next.

相反,重启程序,所有的线程开始执行。即时使用像 step 或者 next 这样的单步命令,也是如此。

In particular,  GDB cannot single-step all threads in lockstep.  Since thread scheduling is  up  to
your debugging target’s operating system (not controlled by GDB),  other threads may  execute  more
than one statement while the current thread completes a single step.  Moreover,  in  general  other
threads stop in the middle of a statement,  rather than at a clean  statement  boundary,  when  the
program stops.

特别是,GDB 不能步调一致的单步执行所有线程。因为线程调度是操作系统负责的,当前线程完成一个单步额同时其它线程可能执行了
多个语句。此外,程序停止时,通常其它线程停止在语句的中间,而不是在一个清晰的语句边界,

You might even find your program stopped in another thread after continuing or even single-stepping.
This happens whenever some other thread runs into a breakpoint,  a signal,  or an exception  before
the first thread completes whatever you requested.

执行继续或者单步后,你甚至可能发现程序在另一个线程中停止了,这个停止发生在第一个线程完成你的请求的任何操作之前(括号内为
个人理解,比如你请求了一个断点,就是说断点停住的时候所有线程已经停止了),每当有其它线程运行到一个断点,信号,或者特例。

Whenever GDB stops your program, due to a breakpoint or a  signal,  it  automatically  selects  the
thread where that breakpoint or signal happened.  GDB alerts you  to  the  context  switch  with  a
message such as ‘[Switching to Thread n]’ to identify the thread.

每当 GDB 停止程序,处理断点或者信号,它自动选择断点或者信号发生的线程。GDB 通过 “[Switching to Thread n]” 之类的
消息提醒上下文的切换,以标识线程。

On some OSes,  you can modify GDB’s default behavior by locking the OS scheduler to  allow  only  a
single thread to run.

在一些操作系统,可以通过锁定系统调度而只允许一个线程执行的方法修改 GDB 的默认习惯。

set scheduler-locking mode
Set the scheduler locking mode. It applies to normal execution, record mode, and replay mode. If it
is off, then there is no locking and any thread may run at any time.  If on,  then only the current
thread may run when the inferior is resumed.  The  step  mode  optimizes  for  single-stepping;  it
prevents other threads from preempting the current thread while you are stepping, so that the focus
of debugging does not change unexpectedly.  Other threads never get a chance to run when you  step,
and they are completely free to run when you use commands like  ‘continue’,  ‘until’,  or ‘finish’.
However,  unless another thread hits a breakpoint during its timeslice,  GDB does  not  change  the
current thread away from the thread that you are debugging.  The replay mode behaves  like  off  in
record mode and like on in replay mode.

设置调度锁模式。应用于正常执行,记录模式和回放模式。如果是 off ,那么不锁定,任何线程可在任何时间运行(但是一旦遇到断点,
所有的线程都会停住)。如果是 on ,仅当前线程在 inferior 被恢复(就是断点继续)时执行。step 模式优化单步执行;执行单步
调试时防止其它线程抢占当前线程,以便调试的焦点不会意外改变。执行单步(next或step)时其它线程没有机会运行,执行continue,
until, 或者 finish 后线程被完全释放执行。但是,除非另一个线程在时间片内击中断点,GDB 不离开当前正在调试的线程。回放
模式在记录模式下表现的像关闭,在回放模式下表现的像打开。

show scheduler-locking
Display the current scheduler locking mode.

显示当前的调度锁模式。

By default, when you issue one of the execution commands such as continue, next or step, GDB allows
only threads of the current inferior to run. For example, if GDB is attached to two inferiors, each
with two threads,  the continue command resumes only the two threads of the current inferior.  This
is useful, for example, when you debug a program that forks and you want to hold the parent stopped
(so that, for instance, it doesn’t run to exit),  while you debug the child.  In other  situations,
you may not be interested in inspecting the current state of any of the processes GDB  is  attached
to, and you may want to resume them all until some breakpoint is hit.  In the latter case,  you can
instruct GDB to allow all threads of all the  inferiors  to  run  with  the  set  schedule-multiple
command.

默认情况下,当你发出一个执行命令,如 continue, next, 或 step,GDB 仅允许当前 inferior 的线程运行。比如,如果 GDB
被依附到两个 inferior,每个有2个线程,continue 仅恢复当前 inferior 的2个线程。这是有用的,比如,调试钩子程序,想停
止父进程(比如让它不运行就退出)当你调试子进程时。在其它情况下,你可能对被GDB依附的程序的当前状态不感兴趣,你可能想恢复所
有的进程,直到断点被击中。最后一种情况,你可以使用 set schedule-multiple 命令,指示 GDB 允许所有 inferior 的所有
线程运行。

set schedule-multiple
Set the mode for allowing threads of multiple processes to be resumed when an execution command  is
issued. When on, all threads of all processes are allowed to run. When off, only the threads of the
current process are resumed.  The default is off.  The scheduler-locking mode takes precedence when
set to on, or while you are stepping and set to step.

设置当执行命令时(是否)允许多个进程的线程被恢复的模式。如果是 on ,所有进程的线程被允许执行。如果是 off ,仅当前进程的
线程被恢复。默认值是 off 。 scheduler-locking 模式设置为 on 时, 或者设置为 step 并且正在执行单步调试,这时
scheduler-locking 优先。

show schedule-multiple
Display the current mode for resuming the execution of threads of multiple processes.
显示用于恢复多进程线程执行的当前模式。

posted on 2018-12-03 16:26  ddev  阅读(2141)  评论(0编辑  收藏  举报