作为研究项目的一部分,我正在尝试编写一个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。)
更新
我决定给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
这表现出相当奇怪的行为。上述版本命中第一个断点,执行相关命令,然后忽略所有以下断点。如果我注释掉只是第二个断点,它的相关命令,以及相应的frame variable x
,continue
,那么断点1和3都会被命中并执行相应的命令。只注释掉第一个或第三个断点及其相关命令frame variable x
,continue
会导致仅第一个未注释的断点被命中,并且其相关命令会运行。简而言之,似乎在两个连续的代码行上有断点会导致第一行之后的所有断点被忽略。
有谁知道这里发生了什么?有没有办法让我在每一条线上都有一个断点并让它们全部被击中?这个问题是否与上述gdb问题有关?
答案 0 :(得分:1)
我仍然没有想出为什么 gdb和lldb按照他们的方式行事,但我确实设计了另一种方法来实现我想要的。我编写了一个脚本,使用两个命名管道与lldb进行通信,其中脚本的stdout链接到lldb的stdin,反之亦然,因此脚本可以发送lldb命令(frame variable -L
,bt
,{{1}然后获取lldb的输出并解析它。该脚本当然可以循环所需的所有内容,因此可以绕过我无法正常循环gdb或lldb命令文件的问题。