如何自动化 GDB 调试会话的最佳方法?

91

GDB是否有内置的脚本机制,我应该编写expect脚本,还是有更好的解决方案?

每次我都将发送相同的命令序列,并将每个命令的输出保存到文件中(最可能使用GDB的内置日志记录机制,除非有更好的建议)。


子集:https://dev59.com/DGYr5IYBdhLWcg3wH23K - Ciro Santilli OurBigBook.com
3个回答

109

基本上,在这个示例中,我想在代码的特定位置获取一些变量值,并在程序崩溃之前将它们输出。因此,首先是一个小程序,保证会在几个步骤后崩溃test.c

#include <stdio.h>
#include <stdlib.h>

int icount = 1; // default value

main(int argc, char *argv[])
{
  int i;

  if (argc == 2) {
    icount = atoi(argv[1]);
  }

  i = icount;
  while (i > -1) {
    int b = 5 / i;
    printf(" 5 / %d = %d \n", i, b );
    i = i - 1;
  }

  printf("Finished\n");
  return 0;
}

程序接受命令行参数的唯一原因是能够选择在崩溃之前的步骤数量,并展示gdb在批处理模式下忽略--args。我使用以下方式进行编译:

gcc -g test.c -o test.exe

那么,我准备了以下脚本 - 这里的主要技巧是为每个断点分配一个command,最终将continue(也可以参见Automate gdb:show backtrace at every call to function puts)。我称此脚本为test.gdb

# http://sourceware.org/gdb/wiki/FAQ: to disable the
# "---Type <return> to continue, or q <return> to quit---"
# in batch mode:
set width 0
set height 0
set verbose off

# at entry point - cmd1
b main
commands 1
  print argc
  continue
end

# printf line - cmd2
b test.c:17
commands 2
  p i
  p b
  continue
end

# int b = line - cmd3
b test.c:16
commands 3
  p i
  p b
  continue
end

# show arguments for program
show args
printf "Note, however: in batch mode, arguments will be ignored!\n"

# note: even if arguments are shown;
# must specify cmdline arg for "run"
# when running in batch mode! (then they are ignored)
# below, we specify command line argument "2":
run 2     # run

#start # alternative to run: runs to main, and stops
#continue

请注意,如果您打算在批处理模式下使用它,必须在结尾处使用runstart等类似命令来“启动”脚本。

将此脚本放在适当的位置后,我可以在批处理模式下调用gdb,并在终端中生成以下输出:

$ gdb --batch --command=test.gdb --args ./test.exe 5
Breakpoint 1 at 0x804844d: file test.c, line 10.
Breakpoint 2 at 0x8048485: file test.c, line 17.
Breakpoint 3 at 0x8048473: file test.c, line 16.
Argument list to give program being debugged when it is started is "5".
Note, however: in batch mode, arguments will be ignored!

Breakpoint 1, main (argc=2, argv=0xbffff424) at test.c:10
10    if (argc == 2) {
$1 = 2

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$2 = 2
$3 = 134513899

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$4 = 2
$5 = 2
 5 / 2 = 2 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$6 = 1
$7 = 2

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$8 = 1
$9 = 5
 5 / 1 = 5 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$10 = 0
$11 = 5

Program received signal SIGFPE, Arithmetic exception.
0x0804847d in main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;

请注意,虽然我们指定了第5个命令行参数,但循环仍然只会旋转两次(这是脚本中run规范的规定);如果run没有任何参数,它只旋转一次(程序的默认值),从而确认--args ./test.exe 5被忽略了。

然而,由于现在输出在单个调用中进行,并且没有任何用户交互,可以使用重定向将命令行输出轻松地捕获到文本文件中,例如:

gdb --batch --command=test.gdb --args ./test.exe 5 > out.txt

c - GDB auto stepping - automatic printout of lines, while free running?中,还有一个使用Python自动化GDB的示例。


1
对我来说太多bug了。在command中使用detach会导致gdb崩溃,在command中使用continue会出现奇怪的“Selected thread is running.”警告。 - phil294
这很有趣,但我想知道在这里使用它的用例是什么,使得它比插入打印语句更可取。 - Bob Anderson

81

gdb 运行后会执行文件 .gdbinit。因此,您可以将命令添加到该文件中并查看是否正常。 以下是一个示例 .gdbinit,用于打印所有 f() 调用的回溯:

set pagination off
set logging file gdb.txt
set logging on
file a.out
b f
commands
bt
continue
end
info breakpoints
r
set logging off
quit

3
有没有一种环境变量可以设置,使得 GDB 在启动时运行不同的文件? - Anonymous
29
没有,但有一个命令行选项:--command=FILE,-x 从文件中执行 GDB 命令。 - matt

23
如果对于带有文件的-x命令行选项感觉太复杂,可以使用多个-ex选项。
这是一个示例,用于跟踪运行中的程序,在崩溃时显示(并保存)回溯信息。
sudo gdb -p "$(pidof my-app)" -batch \
  -ex "set logging on" \
  -ex continue \
  -ex "bt full" \
  -ex quit

一个独立程序可以作为替代启动。
gdb -batch \
      -ex "set logging on" \
      -ex continue \
      -ex "bt full" \
      -ex quit
      --args \
      program --arg --another


“sudo”这个词有点不太幸运,而且这似乎并没有回答这个问题… - cedric
如果您需要跟踪正在运行的进程,就需要使用 sudo。但是,如果您仅启动独立应用程序,则不需要它。 - Treviño
需要哪些特权(-> 如果sudo可以使跟踪工作正常),取决于ptrace_scope sysctl:https://www.kernel.org/doc/Documentation/security/Yama.txt - domen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接