GDB和LLDB都无法在简单的C文件中可靠地执行断点命令

作为研究项目的一部分,我正在尝试编写一个gdb命令文件,该文件在任意C源文件中输出每行代码的某些信息,直到程序终止.这似乎可以通过while循环轻松完成,在循环中输出我想要的任何数据,然后在循环结束时调用“next”. (我知道我希望“步骤”进入函数调用;此刻我并不关心.)

但是,除了每行输出的数据外,我还想在某些断点处执行特殊命令.这似乎可以通过“命令”轻松完成.但是,我遇到的问题是while循环和断点命令都不能同时工作.

这是我正在使用的非常简单的C文件,用于测试目的:

int global;

int main() {
  int x;
  x=-1;
  global = 5;
  return(0);
}

我用gcc -g -o simple simple.c编译它.然后我运行gdb -x commands.txt.如果commands.txt的内容如下:

set confirm off

exec-file simple
file simple

set logging file gdb_output.txt
set logging on
set pagination off

#Special commands I want to execute on certain breakpoints
break 5
command
  echo COMMAND 1 ACTIVATED\n
end

break 6
command
  echo COMMAND 2 ACTIVATED\n
end

break 7
command
  echo COMMAND 3 ACTIVATED\n
end

run

next
next
next
continue

quit

…然后gdb_output.txt的内容如下所示:

Breakpoint 1 at 0x4004da: file simple.c, line 5.
Breakpoint 2 at 0x4004e1: file simple.c, line 6.
Breakpoint 3 at 0x4004eb: file simple.c, line 7.

Breakpoint 1, main () at simple.c:5
5     x=-1;
COMMAND 1 ACTIVATED

Breakpoint 2, main () at simple.c:6
6     global = 5;
COMMAND 2 ACTIVATED

Breakpoint 3, main () at simple.c:7
7     return(0);
COMMAND 3 ACTIVATED
8   }
[Inferior 1 (process 29631) exited normally]

但是,如果我编辑命令文件以尝试作为循环执行,则替换

next
next
next
continue

while true
  next
end

但是让脚本的其余部分完全相同,那么我为第6行和第7行的断点指定的命令永远不会执行,运行修改后的命令文件后gdb_output.txt的内容就是证明:

Breakpoint 1 at 0x4004da: file simple.c, line 5.
Breakpoint 2 at 0x4004e1: file simple.c, line 6.
Breakpoint 3 at 0x4004eb: file simple.c, line 7.

Breakpoint 1, main () at simple.c:5
5     x=-1;
COMMAND 1 ACTIVATED

Breakpoint 2, main () at simple.c:6
6     global = 5;

Breakpoint 3, main () at simple.c:7
7     return(0);
8   }
__libc_start_main (main=0x4004d6 <main()>, argc=1, argv=0x7fffffffe128, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe118) at ../csu/libc-start.c:325
325 ../csu/libc-start.c: No such file or directory.
[Inferior 1 (process 29652) exited normally]
commands.txt:30: Error in sourced command file:
The program is not being run.

我知道它当前形式的循环是有问题的,因为它将一直调用“next”直到程序终止(因此它永远不会到达脚本底部的“quit”),但这似乎不应该停止运行断点命令 – 但这似乎正在发生. (如果正在执行断点命令,我可以调整我的while循环,一旦它达到C程序退出点之前设置的断点,就会终止.)

这是GDB中的错误,还是我误解了什么?如果这种结构从根本上不起作用,那么有没有办法在程序运行的每一步执行一系列GDB命令,直到程序终止,同时还执行在某些断点处指定的命令 – 或者这在根本上是不可能的一个GDB脚本?

(我的gdb版本是7.11.1,如果重要的话,我的操作系统是Linux.)

UPDATE

我决定给lldb一个镜头并遇到一些更令人困惑的问题(使用与上面相同的C文件,使用相同的命令编译).这是我的lldb脚本:

target create --no-dependents --arch x86_64 simple

breakpoint set --file simple.c --line 5
breakpoint command add
  script print "COMMAND 1 ACTIVATED"
DONE

breakpoint set --file simple.c --line 6
breakpoint command add
  script print "COMMAND 2 ACTIVATED"
DONE

breakpoint set --file simple.c --line 7
breakpoint command add
  script print "COMMAND 3 ACTIVATED"
DONE

run

frame variable x
continue

frame variable x
continue

frame variable x
continue

quit

这表现出相当奇怪的行为.上述版本命中第一个断点,执行相关命令,然后忽略所有以下断点.如果我只注释掉第二个断点,它的相关命令和相应的帧变量x,则继续,然后断点1和3都被命中并执行相应的命令.只注释第一个或第三个断点及其相关的命令和帧变量x,continue会导致第一个未注释的断点被命中,并且其相关的命令运行.简而言之,似乎在两个连续的代码行上有断点会导致第一行之后的所有断点被忽略.

有谁知道这里发生了什么?有没有办法让我在每一条线上都有一个断点并让它们全部被击中?这个问题是否与上述gdb问题有关?

最佳答案 我仍然没有弄清楚为什么gdb和lldb按照他们的方式行事,但我确实设计了另一种方法来实现我想要的.我编写了一个脚本,使用两个命名管道与lldb进行通信,其中脚本的stdout链接到lldb的stdin,反之亦然,因此脚本可以发送lldb命令(帧变量-L,bt,step等)然后获取lldb的输出并解析它.该脚本当然可以循环所有它想要的,所以这绕过了我无法正确循环gdb或lldb命令文件的问题.

点赞