如何在到达给定断点之前自动打印 GDB 中的每个执行行? [英] How to print every executed line in GDB automatically until a given breakpoint is reached?
问题描述
我希望能够在 GDB 中设置一个断点,并让它运行到那个点 - 在这个过程中,打印出它逐步通过"的行.
I would like to be able to set a breakpoint in GDB, and have it run to that point - and in the process, print out lines it has "stepped through".
这是一个示例,基于这个简单的文件,其中包含一个 main
和一个函数,每个文件都有两个断点:
Here is an example, based on this simple file with a main
and a function, and two breakpoints for each:
$ cat > test.c <<EOF
#include "stdio.h"
int count=0;
void doFunction(void) {
// two steps forward
count += 2;
// one step back
count--;
}
int main(void) {
// some pointless init commands;
count = 1;
count += 2;
count = 0;
//main loop
while(1) {
doFunction();
printf("%d
", count);
}
}
EOF
$ gcc -g -Wall test.c -o test.exe
$ chmod +x test.exe
$ gdb -se test.exe
...
Reading symbols from /path/to/test.exe...done.
(gdb) b main
Breakpoint 1 at 0x80483ec: file test.c, line 14.
(gdb) b doFunction
Breakpoint 2 at 0x80483c7: file test.c, line 7.
要开始会话,我需要运行 (r
) 程序,然后程序会在第一个断点 (main
) 处停止:
To start the session, I need to run (r
) the program, which will then stop at first breakpoint (main
):
(gdb) r
Starting program: /path/to/test.exe
Breakpoint 1, main () at test.c:14
14 count = 1;
(gdb)
此时 - 例如,我可以点击 continue (c
);并且该过程将运行,不输出任何内容,并在请求的行处中断:
At this point - I can, for instance, hit continue (c
); and the process will run through, not outputing anything, and break at the requested line:
(gdb) c
Continuing.
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
另一方面,我可以使用 step (s
) 或 next (n
) 来逐行执行,而不是 continue;例如:
On the other hand, instead of continue - I can go line by line, either by using step (s
) or next (n
); for instance:
14 count = 1;
(gdb) n
15 count += 2;
(gdb) s
16 count = 0;
(gdb) s
19 doFunction();
(gdb) s
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb) s
9 count--;
(gdb) s
10 }
(gdb) s
main () at test.c:20
20 printf("%d
", count);
(gdb) s
...
(gdb) s
_IO_vfprintf_internal (s=Cannot access memory at address 0xe5853361
) at vfprintf.c:210
210 vfprintf.c: No such file or directory.
in vfprintf.c
(gdb) s
245 in vfprintf.c
(gdb) s
210 in vfprintf.c
(gdb) n
245 in vfprintf.c
...
(gdb) n
2006 in vfprintf.c
(gdb) n
__printf (format=0x80484f0 "%d
") at printf.c:39
39 printf.c: No such file or directory.
in printf.c
(gdb) n
main () at test.c:21
21 }
(gdb) n
19 doFunction();
(gdb) n
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
无论如何,我知道我可以按住 Enter,最后输入的命令(步骤或下一步)将重复(在第二种情况下留下更长的会话,以显示'next' 保持在同一级别,'step' 步入被调用的函数).但是,可以看出,根据是 step 还是 next 运行,可能需要一段时间才能达到结果 - 所以,我不想坐 10 分钟,我的手卡在 Enter 按钮上 :)
Anyways, I am aware that I can keep Enter pressed, and the last entered command (step or next) will repeat (left a bit longer session in the second case, to show that 'next' remains on same level, 'step' steps inside the functions being called). However, as it can be seen, depending on whether step or next runs, it may take a while until a result is reached - and so, I don't want to sit for 10 minutes with my hand stuck on the Enter button :)
所以,我的问题是——我能否以某种方式指示 gdb
在没有用户进一步干预的情况下运行到断点 2"——同时打印出它经过的行,就好像步骤(或下一步)是按下了吗?
So, my question is - can I somehow instruct gdb
to run to 'breakpoint 2' without further user intervention - while printing out the lines it goes through, as if step (or next) was pressed?
推荐答案
嗯,这并不容易 - 但我想我有点明白了 :) 我经历了一堆失败的尝试(发布 这里);相关代码如下.
Well, this wasn't easy - but I think I somewhat got it :) I went through a bunch of failed attempts (posted here); relevant code is below.
基本上,直到断点的下一步/步骤"中的问题是,如果调试器停止(在某个步骤),如何确定您是否打开"断点.另请注意,我使用 GDB 7.2-1ubuntu11(当前适用于 Ubuntu 11.04).所以,它是这样的:
Basically, the problem in a "next/step until breakpoint" is how to determine whether you're "on" a breakpoint or not, if the debugger is stopped (at a step). Note also I use GDB 7.2-1ubuntu11 (current for Ubuntu 11.04). So, it went like this:
- 我首先发现了 便利变量,并认为 - 在那里是程序计数器等可用的,必须有一些 GDB 便利变量给出断点"状态,并且可以直接在 GDB 脚本中使用.但是,在浏览了 GDB 参考索引 之后,我根本找不到任何这样的变量(我的尝试在 nub.gdb)
- 在缺少这种断点状态"内部变量的情况下,唯一要做的就是将 GDB 的 ('stdout') 命令行输出(响应命令)捕获为字符串,并解析它(寻找断点")
- 然后,我发现了 Python API 到 GDB,以及
gdb.execute("CMDSTR", toString=True)
命令 - 这似乎正是捕获输出所需要的:默认情况下,任何输出都会产生by command被发送到gdb的标准输出.如果to_string参数为True,那么输出将被gdb.execute收集并作为字符串返回[1]"!- 所以,首先我尝试制作一个脚本(pygdb-nub.py,gdbwrap) 将利用
gdb.execute
以推荐的方式;在这里失败 - 因为这个:- 错误 627506 – python: gdb.execute([...], to_string=True) 部分打印到 stdout/stderr
- 错误 10808 - 允许 GDB/Python API 捕获和存储 GDB 输出
- I first found about Convenience Variables, and thought - given there are program counters and such available, there must be some GDB convenience variable that gives the "breakpoint" status, and can be used directly in a GDB script. After looking through GDB reference Index for a while, however, I simply cannot find any such variables (my attempts are in nub.gdb)
- In lack of such a "breakpoint status" internal variable - the only thing left to do, is to capture the ('stdout') command line output of GDB (in response to commands) as a string, and parse it (looking for "Breakpoint")
- Then, I found out about Python API to GDB, and the
gdb.execute("CMDSTR", toString=True)
command - which is seemingly exactly what is needed to capture the output: "By default, any output produced by command is sent to gdb's standard output. If the to_string parameter is True, then output will be collected by gdb.execute and returned as a string[1]"!- So, first I tried to make a script (pygdb-nub.py,gdbwrap) that would utilize
gdb.execute
in the recommended manner; failed here - because of this:- Bug 627506 – python: gdb.execute([...], to_string=True) partly prints to stdout/stderr
- Bug 10808 – Allow GDB/Python API to capture and store GDB output
最后,可行的方法是:临时将 GDB 输出从
gdb.execute
重定向到 RAM 中的日志文件(Linux:/dev/shm
);然后读回它,解析它并从 python 打印它——python 还处理一个简单的 while 循环,该循环会一直执行,直到到达断点.And finally, the approach that worked is: temporarily redirecting the GDB output from a
gdb.execute
to a logfile in RAM (Linux:/dev/shm
); and then reading it back, parsing it and printing it from python - python also handles a simple while loop that steps until a breakpoint is reached.具有讽刺意味的是 - 大多数通过重定向日志文件导致此解决方案的错误实际上最近在 SVN 中得到修复;这意味着这些将在不久的将来传播到发行版,并且可以直接使用
gdb.execute("CMDSTR", toString=True)
:/然而,因为我不能冒险构建 GDB现在的来源(并且可能会遇到可能的新不兼容性),这对我来说也足够了:)The irony is - most of these bugs, that caused this solution via redirecting the logfile, are actually recently fixed in SVN; meaning those will propagate to the distros in the near future, and one will be able to use
gdb.execute("CMDSTR", toString=True)
directly :/ Yet, as I cannot risk building GDB from source right now (and possibly bumping into possible new incompatibilites), this is good enough for me also :)这里是相关文件(部分也在 pygdb-fork.gdb,pygdb-fork.py):
Here are the relevant files (partially also in pygdb-fork.gdb,pygdb-fork.py):
pygdb-logg.gdb
是:# gdb script: pygdb-logg.gdb # easier interface for pygdb-logg.py stuff # from within gdb: (gdb) source -v pygdb-logg.gdb # from cdmline: gdb -x pygdb-logg.gdb -se test.exe # first, "include" the python file: source -v pygdb-logg.py # define shorthand for nextUntilBreakpoint(): define nub python nextUntilBreakpoint() end # set up breakpoints for test.exe: b main b doFunction # go to main breakpoint run
pygdb-logg.py
是:# gdb will 'recognize' this as python # upon 'source pygdb-logg.py' # however, from gdb functions still have # to be called like: # (gdb) python print logExecCapture("bt") import sys import gdb import os def logExecCapture(instr): # /dev/shm - save file in RAM ltxname="/dev/shm/c.log" gdb.execute("set logging file "+ltxname) # lpfname gdb.execute("set logging redirect on") gdb.execute("set logging overwrite on") gdb.execute("set logging on") gdb.execute(instr) gdb.execute("set logging off") replyContents = open(ltxname, 'r').read() # read entire file return replyContents # next until breakpoint def nextUntilBreakpoint(): isInBreakpoint = -1; # as long as we don't find "Breakpoint" in report: while isInBreakpoint == -1: REP=logExecCapture("n") isInBreakpoint = REP.find("Breakpoint") print "LOOP:: ", isInBreakpoint, " ", REP
基本上,
pygdb-logg.gdb
加载pygdb-logg.py
python脚本,为设置别名
,并初始化会话 - 其他一切都由 python 脚本处理.这是一个示例会话 - 关于 OP 中的测试源:nub
nextUntilBreakpointBasically,
pygdb-logg.gdb
loads thepygdb-logg.py
python script, sets up the aliasnub
fornextUntilBreakpoint
, and initializes the session - everything else is handled by the python script. And here is a sample session - in respect to the test source in OP:$ gdb -x pygdb-logg.gdb -se test.exe ... Reading symbols from /path/to/test.exe...done. Breakpoint 1 at 0x80483ec: file test.c, line 14. Breakpoint 2 at 0x80483c7: file test.c, line 7. Breakpoint 1, main () at test.c:14 14 count = 1; (gdb) nub LOOP:: -1 15 count += 2; LOOP:: -1 16 count = 0; LOOP:: -1 19 doFunction(); LOOP:: 1 Breakpoint 2, doFunction () at test.c:7 7 count += 2; (gdb) nub LOOP:: -1 9 count--; LOOP:: -1 10 } LOOP:: -1 main () at test.c:20 20 printf("%d ", count); 1 LOOP:: -1 21 } LOOP:: -1 19 doFunction(); LOOP:: 1 Breakpoint 2, doFunction () at test.c:7 7 count += 2; (gdb)
...就像我想要的那样:P 只是不知道它有多可靠(以及是否可以在
avr-gdb
中使用,这就是我需要这个:) Ubuntu 11.04 中的 avr-gdb 版本目前是 6.4,它无法识别 python 命令:()... just as I wanted it :P Just don't know how reliable it is (and whether it will be possible to use in
avr-gdb
, which is what I need this for :) version of avr-gdb in Ubuntu 11.04 is currently 6.4, which doesn't recognize the python command :()嗯,希望这对某人有所帮助,
干杯!Well, hope this helps someone,
Cheers!这里有一些参考:
- GDB:在标准输入上检测到错误
- GDB 无法通过管道获取命令标准输入法
- Re: [Gdb] 如何使用GDB其他输入法?
- gdb 不接受标准输入
- 在 IDE 中使用 gdb - comp.os.linux.development.apps |Google 网上论坛
- rmathew:绝症
- [教程] 在 C (Linux) 中调用外部程序 - GIDForums李>
- shell - 如何使用 shebang (IE #!)?- 堆栈溢出
- 将shell的输出重定向/存储到GDB变量中?- 堆栈溢出
- Corey Goldberg:Python - 重定向或关闭 STDOUT 和 STDERR
- 虚无之崖 › 9. 编写 gdb 脚本
- gdb python 脚本:哪里有
parse_and_eval
不见了?- 堆栈溢出 - shell - 调用 gdb 自动通过正在调试的程序的参数 - 堆栈内存溢出
- 使用 tmpfs 在内存中存储文件/目录 |HowtoForge - Linux Howtos 和教程
- 在文件不存在时触摸文件的简单方法 |蟒蛇 |蟒蛇
- os.fork() 在 cgi-script 中不同?- 蟒蛇
- java - 使用 GDB 编写测试 - 如何捕获输出?- 堆栈溢出
- 使用 GDB 进行调试:如何在 Python 中创建 GDB 命令 - Wiki
- GDB 参考卡
- GDB: error detected on stdin
- GDB has problems with getting commands piped to STDIN
- Re: [Gdb] How do i use GDB other input?
- gdb doesn't accept input on stdin
- Using gdb in an IDE - comp.os.linux.development.apps | Google Groups
- rmathew: Terminal Sickness
- [TUTORIAL] Calling an external program in C (Linux) - GIDForums
- shell - how to use multiple arguments with a shebang (i.e. #!)? - Stack Overflow
- Redirecting/storing output of shell into GDB variable? - Stack Overflow
- Corey Goldberg: Python - Redirect or Turn Off STDOUT and STDERR
- The Cliffs of Inanity › 9. Scripting gdb
- gdb python scripting: where has
parse_and_eval
gone? - Stack Overflow - shell - Invoke gdb to automatically pass arguments to the program being debugged - Stack Overflow
- Storing Files/Directories In Memory With tmpfs | HowtoForge - Linux Howtos and Tutorials
- simple way to touch a file if it does not exist | Python | Python
- os.fork() different in cgi-script? - Python
- java - Writing tests that use GDB - how to capture output? - Stack Overflow
- Debugging with GDB: How to create GDB Commands in Python - Wiki
- GDB reference card
这篇关于如何在到达给定断点之前自动打印 GDB 中的每个执行行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- So, first I tried to make a script (pygdb-nub.py,gdbwrap) that would utilize
- 所以,首先我尝试制作一个脚本(pygdb-nub.py,gdbwrap) 将利用