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".
我希望能够在GDB中设置一个断点,并让它运行到那个点——在这个过程中,打印出它已经“穿过”的行。
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\n", 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.
To start the session, I need to run (r
) the program, which will then stop at first breakpoint (main
):
要开始会话,我需要运行(r)程序,程序在第一个断点(main)处停止:
(gdb) r
Starting program: /path/to/test.exe
Breakpoint 1, main () at test.c:14
14 count = 1;
(gdb)
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:
此时-例如,我可以点击continue (c);这个过程将会运行,而不是输出任何东西,并在要求的行上中断:
(gdb) c
Continuing.
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
On the other hand, instead of continue - I can go line by line, either by using step (s
) or next (n
); for instance:
另一方面,不是继续,我可以逐行逐行,或者使用步骤(s)或next (n);例如:
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\n", 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\n") 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)
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 :)
无论如何,我知道我可以继续输入,并且最后一个输入命令(步骤或下一个)会重复(在第二个例子中留一个长一点的会话,以显示“下一个”仍然在相同的级别上,在被调用的函数内的“步骤”步骤)。然而,正如我们所看到的,这取决于是走一步还是下一段路,可能需要一段时间才能达到结果——所以,我不想把手放在Enter按钮上坐上10分钟:
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?
因此,我的问题是——我是否可以指示gdb在没有进一步用户干预的情况下运行到“断点2”——同时打印它所经过的行,就像按了step(或next)一样?
4 个解决方案
#1
17
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.
嗯,这并不容易,但我想我有点明白了:)我经历了很多失败的尝试(贴在这里);相关代码如下。
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 7.2-1ubuntu11(适用于Ubuntu 11.04)。结果是这样的:
- 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)
- 我首先发现了便利变量,并认为——考虑到有程序计数器之类的可用变量,必须有一些GDB便利变量来提供“断点”状态,并且可以直接在GDB脚本中使用。但是,在查看了一段时间的GDB引用索引之后,我根本找不到任何这样的变量(我的尝试是在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")
- 在缺少这样的“断点状态”内部变量时,惟一要做的事情是将GDB(响应命令)的命令行输出捕获为字符串,并解析它(查找“断点”)
- 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 627506 - python: gdb.execute([…, to_string=True)部分打印到stdout/stderr
- Bug 10808 – Allow GDB/Python API to capture and store GDB output
- Bug 10808 -允许GDB/Python API捕获和存储GDB输出
- 因此,首先我尝试创建一个使用gdb的脚本(pygdb-nub.py,gdbwrap)。按照建议的方式执行;在这里失败——因为这个:Bug 627506 - python: gdb.execute([……, to_string=True)部分打印到stdout/stderr Bug 10808 -允许GDB/Python API捕获和存储GDB输出
- Then, I thought I'd use a python script to
subprocess.Popen
the GDB program, while replacing its stdin and stdout; and then proceed controlling GDB from there (pygdb-sub.py) - that failed too... (apparently, because I didn't redirect stdin/out right) - 然后,我想我应该使用python脚本进行子进程。弹出GDB程序,同时替换它的stdin和stdout;然后从那里继续控制GDB (pygdb-sub.py)——这也失败了……(显然,因为我没有正确地重定向stdin/out)
- Then, I thought I'd use python scripts to be called from GDB (via
source
) which would internally fork into a pty whenevergdb.execute
should be called, so as to capture its output (pygdb-fork.gdb,pygdb-fork.py)... This almost worked - as there are strings returned; however GDB notices something ain't right: "[tcsetpgrp failed in terminal_inferior: Operation not permitted]", and the subsequent return strings don't seem to change. - 然后,我想我应该使用python脚本从GDB(通过源代码)调用,GDB会在GDB时在内部将其转换为pty。应该调用execute,以便捕获其输出(pygdb-fork.gdb、pygdb-fork.py)…这几乎是可行的——因为有返回的字符串;然而,GDB注意到有些事情是不对的:“tcsetpgrp在终止时失败了:操作不允许”,而随后的返回字符串似乎没有改变。
- So, first I tried to make a script (pygdb-nub.py,gdbwrap) that would utilize
- 然后,我发现了Python API到GDB,以及GDB。执行(“CMDSTR”,toString=True)命令——这似乎正是捕获输出所需要的:“默认情况下,命令生成的任何输出都被发送到gdb的标准输出。如果to_string参数为True,则gdb将收集输出。执行并作为字符串[1]返回!因此,首先我尝试创建一个使用gdb的脚本(pygdb-nub.py,gdbwrap)。按照建议的方式执行;在这里失败——因为这个:Bug 627506 - python: gdb.execute([……, to_string=True)部分输出到stdout/stderr Bug 10808 -允许GDB/Python API捕获和存储GDB输出,然后,我想我应该使用Python脚本进行子进程。弹出GDB程序,同时替换它的stdin和stdout;然后从那里继续控制GDB (pygdb-sub.py)——这也失败了……(显然,因为我没有正确地重定向stdin/out)然后,我想我应该使用python脚本从GDB(通过源代码)调用,GDB会在GDB时在内部将其插入到pty中。应该调用execute,以便捕获其输出(pygdb-fork.gdb、pygdb-fork.py)…这几乎是可行的——因为有返回的字符串;然而,GDB注意到有些事情是不对的:“tcsetpgrp在终止时失败了:操作不允许”,而随后的返回字符串似乎没有改变。
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.
最后,有效的方法是:临时重定向GDB输出。执行到RAM中的日志文件(Linux: /dev/shm);然后读取它,解析它并从python中打印它——python还处理一个简单的while循环,直到到达断点。
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 :)
具有讽刺意味的是,大多数这些错误,通过重定向logfile导致了这个解决方案,实际上是最近在SVN中修复的;这意味着这些将在不久的将来传播到发行版,并且人们将能够使用gdb。直接执行(“CMDSTR”,toString=True):/然而,由于我现在不能冒险从源代码构建GDB(并且可能会遇到新的不兼容),这对我来说也足够了:
Here are the relevant files (partially also in pygdb-fork.gdb,pygdb-fork.py):
以下是相关文件(部分也在pygdb-fork.gdb、pygdb-fork.py中):
pygdb-logg.gdb
is:
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
is:
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, "\n", REP
Basically, pygdb-logg.gdb
loads the pygdb-logg.py
python script, sets up the alias nub
for nextUntilBreakpoint
, 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:
基本上,pygdb-logg。gdb加载pygdb-logg。py python脚本,为nextUntilBreakpoint设置别名nub,并初始化会话——其他一切都由python脚本处理。这是一个关于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\n", count);
1
LOOP:: -1
21 }
LOOP:: -1
19 doFunction();
LOOP:: 1
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
... 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 :) EDIT: version of avr-gdb in Ubuntu 11.04 is currently 6.4, which doesn't recognize the python command :()
…正如我想要的:P只是不知道它有多可靠(以及是否有可能在avr-gdb中使用,这正是我需要的:)
Well, hope this helps someone,
Cheers!
希望这能帮到别人,干杯!
Here some references:
这里一些参考:
- GDB: error detected on stdin
- GDB:在stdin上检测到的错误。
- GDB has problems with getting commands piped to STDIN
- GDB在向STDIN传输命令时存在问题
- Re: [Gdb] How do i use GDB other input?
- Re: [Gdb]如何使用Gdb其他输入?
- gdb doesn't accept input on stdin
- gdb不接受stdin上的输入
- Using gdb in an IDE - comp.os.linux.development.apps | Google Groups
- 在IDE .os.linux.development.apps |谷歌组中使用gdb
- rmathew: Terminal Sickness
- rmathew:终端疾病
- [TUTORIAL] Calling an external program in C (Linux) - GIDForums
- 在C (Linux) - gidforum中调用一个外部程序
- shell - how to use multiple arguments with a shebang (i.e. #!)? - Stack Overflow
- shell -如何使用shebang的多个参数(例如#!)?——堆栈溢出
- Redirecting/storing output of shell into GDB variable? - Stack Overflow
- 将shell的输出重定向/存储到GDB变量中?——堆栈溢出
- Corey Goldberg: Python - Redirect or Turn Off STDOUT and STDERR
- Corey Goldberg: Python -重定向或关闭STDOUT和STDERR。
- The Cliffs of Inanity › 9. Scripting gdb
- 虚无缥缈的悬崖9。脚本gdb
- gdb python scripting: where has
parse_and_eval
gone? - Stack Overflow - gdb python脚本:parse_and_eval去哪儿了?——堆栈溢出
- shell - Invoke gdb to automatically pass arguments to the program being debugged - Stack Overflow
- shell -调用gdb来自动将参数传递给正在调试的程序—堆栈溢出
- Storing Files/Directories In Memory With tmpfs | HowtoForge - Linux Howtos and Tutorials
- 使用tmpfs | HowtoForge在内存中存储文件/目录——Linux howto和教程
- simple way to touch a file if it does not exist | Python | Python
- 简单的触摸文件的方法,如果它不存在| Python | Python
- os.fork() different in cgi-script? - Python
- os.fork()在cgi脚本不同吗?Python -
- java - Writing tests that use GDB - how to capture output? - Stack Overflow
- java -使用GDB编写测试-如何捕获输出?——堆栈溢出
- Debugging with GDB: How to create GDB Commands in Python - Wiki
- 使用GDB调试:如何在Python - Wiki中创建GDB命令。
- GDB reference card
- GDB参考卡片
#2
3
Based on the link in @sdaau's answer (http://www.mail-archive.com/gdb@gnu.org/msg00031.html), I created my own script to simply keep sending 's' and reading the output of gdb continuously, while printing output to textfile and terminal, of course, my script can be modified to fit anyone else's needs, however, I hope that the modification I made should fit most people needs.
基于链接@sdaau的回答(http://www.mail-archive.com/gdb@gnu.org/msg00031.html),我创建了自己的脚本将发送“s”保存和阅读gdb不断的输出,同时打印输出文本文件和终端,当然,我的脚本可以修改以适应别人的需求,然而,我希望我做的修改应该符合大多数人的需要。
http://www.codeground.net/coding/gdb-step-into-all-lines-to-get-full-application-flow/
http://www.codeground.net/coding/gdb-step-into-all-lines-to-get-full-application-flow/
wget http://www.codeground.net/downloads/gdbwalkthrough.c
gcc gdbwalkthrough.c -o gdbwalkthrough
./gdbwalkthrough <application full path> [application arguments]
#3
3
What about doing it like this in gdb, using a command file. Change file argument, and loop count as required.
如何使用命令文件在gdb中这样做呢?更改文件参数,并按需要循环计数。
gdb -x run.gdb
run.gdb:
run.gdb:
set pagination off
set logging file gdb.log
set logging on
set $i = 0
file main
break main
break WriteData
# sadly, commands not getting executed on reaching breakpoint 2
commands 2
set $i=1000
print "commands 2 : %d",$i
end
run
while ( $i < 1000 )
step
# next
# continue
set $i = $i + 1
end
#4
1
As a new answer, since the previous is already hogged :) Basically, if the point is to observe execution of source (and/or assembly) code lines as the program as running - as the motivation is often for me when looking into "automatic printout" -- then, basically, a very quick way is to use GDB TUI mode; I quote:
作为一个新回答,因为前面已经占据:)基本上,如果问题是观察执行源(和/或装配)代码行程序一样运行,动机常常为我当调查“自动打印输出”——然后,基本上,一个非常快速的方法是使用GDB TUI模式;我引用:
c - gdb behavior : value optimized out - Stack Overflow #1354762
c - gdb行为:值优化出-堆栈溢出#1354762。
Use the GDB TUI mode. My copy of GDB enables it when I type the minus and Enter. Then type C-x 2 (that is hold down Control and press X, release both and then press 2). That will put it into split source and disassembly display. Then use stepi and nexti to move one machine instruction at a time. Use C-x o to switch between the TUI windows.
使用GDB TUI模式。我的拷贝的GDB使它当我输入-和进入。然后输入C-x 2(按住Control键,按X键,同时释放,然后按2),这将把它放入分割源和拆卸显示中。然后使用stepi和nexti一次移动一个机器指令。使用C-x o在TUI窗口之间切换。
The trick here is that, even if you hit continue
- this time source will be shown and indicated on the TUI; and followed as the program runs:
这里的诀窍是,即使你点击了继续-这个时间源将会在TUI中显示和显示;然后随着程序运行:
... and this for me avoids many situations where I'd have to script the breakpoints in "auto-stepping context" (although there are still such situations).. Docs about TUI: TUI - Debugging with GDB
…对于我来说,这避免了很多情况,我必须在“自动步进上下文”中编写断点(尽管仍然存在这种情况)。关于TUI的文档:TUI -与GDB的调试
Cheers!
干杯!
#1
17
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.
嗯,这并不容易,但我想我有点明白了:)我经历了很多失败的尝试(贴在这里);相关代码如下。
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 7.2-1ubuntu11(适用于Ubuntu 11.04)。结果是这样的:
- 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)
- 我首先发现了便利变量,并认为——考虑到有程序计数器之类的可用变量,必须有一些GDB便利变量来提供“断点”状态,并且可以直接在GDB脚本中使用。但是,在查看了一段时间的GDB引用索引之后,我根本找不到任何这样的变量(我的尝试是在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")
- 在缺少这样的“断点状态”内部变量时,惟一要做的事情是将GDB(响应命令)的命令行输出捕获为字符串,并解析它(查找“断点”)
- 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 627506 - python: gdb.execute([…, to_string=True)部分打印到stdout/stderr
- Bug 10808 – Allow GDB/Python API to capture and store GDB output
- Bug 10808 -允许GDB/Python API捕获和存储GDB输出
- 因此,首先我尝试创建一个使用gdb的脚本(pygdb-nub.py,gdbwrap)。按照建议的方式执行;在这里失败——因为这个:Bug 627506 - python: gdb.execute([……, to_string=True)部分打印到stdout/stderr Bug 10808 -允许GDB/Python API捕获和存储GDB输出
- Then, I thought I'd use a python script to
subprocess.Popen
the GDB program, while replacing its stdin and stdout; and then proceed controlling GDB from there (pygdb-sub.py) - that failed too... (apparently, because I didn't redirect stdin/out right) - 然后,我想我应该使用python脚本进行子进程。弹出GDB程序,同时替换它的stdin和stdout;然后从那里继续控制GDB (pygdb-sub.py)——这也失败了……(显然,因为我没有正确地重定向stdin/out)
- Then, I thought I'd use python scripts to be called from GDB (via
source
) which would internally fork into a pty whenevergdb.execute
should be called, so as to capture its output (pygdb-fork.gdb,pygdb-fork.py)... This almost worked - as there are strings returned; however GDB notices something ain't right: "[tcsetpgrp failed in terminal_inferior: Operation not permitted]", and the subsequent return strings don't seem to change. - 然后,我想我应该使用python脚本从GDB(通过源代码)调用,GDB会在GDB时在内部将其转换为pty。应该调用execute,以便捕获其输出(pygdb-fork.gdb、pygdb-fork.py)…这几乎是可行的——因为有返回的字符串;然而,GDB注意到有些事情是不对的:“tcsetpgrp在终止时失败了:操作不允许”,而随后的返回字符串似乎没有改变。
- So, first I tried to make a script (pygdb-nub.py,gdbwrap) that would utilize
- 然后,我发现了Python API到GDB,以及GDB。执行(“CMDSTR”,toString=True)命令——这似乎正是捕获输出所需要的:“默认情况下,命令生成的任何输出都被发送到gdb的标准输出。如果to_string参数为True,则gdb将收集输出。执行并作为字符串[1]返回!因此,首先我尝试创建一个使用gdb的脚本(pygdb-nub.py,gdbwrap)。按照建议的方式执行;在这里失败——因为这个:Bug 627506 - python: gdb.execute([……, to_string=True)部分输出到stdout/stderr Bug 10808 -允许GDB/Python API捕获和存储GDB输出,然后,我想我应该使用Python脚本进行子进程。弹出GDB程序,同时替换它的stdin和stdout;然后从那里继续控制GDB (pygdb-sub.py)——这也失败了……(显然,因为我没有正确地重定向stdin/out)然后,我想我应该使用python脚本从GDB(通过源代码)调用,GDB会在GDB时在内部将其插入到pty中。应该调用execute,以便捕获其输出(pygdb-fork.gdb、pygdb-fork.py)…这几乎是可行的——因为有返回的字符串;然而,GDB注意到有些事情是不对的:“tcsetpgrp在终止时失败了:操作不允许”,而随后的返回字符串似乎没有改变。
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.
最后,有效的方法是:临时重定向GDB输出。执行到RAM中的日志文件(Linux: /dev/shm);然后读取它,解析它并从python中打印它——python还处理一个简单的while循环,直到到达断点。
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 :)
具有讽刺意味的是,大多数这些错误,通过重定向logfile导致了这个解决方案,实际上是最近在SVN中修复的;这意味着这些将在不久的将来传播到发行版,并且人们将能够使用gdb。直接执行(“CMDSTR”,toString=True):/然而,由于我现在不能冒险从源代码构建GDB(并且可能会遇到新的不兼容),这对我来说也足够了:
Here are the relevant files (partially also in pygdb-fork.gdb,pygdb-fork.py):
以下是相关文件(部分也在pygdb-fork.gdb、pygdb-fork.py中):
pygdb-logg.gdb
is:
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
is:
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, "\n", REP
Basically, pygdb-logg.gdb
loads the pygdb-logg.py
python script, sets up the alias nub
for nextUntilBreakpoint
, 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:
基本上,pygdb-logg。gdb加载pygdb-logg。py python脚本,为nextUntilBreakpoint设置别名nub,并初始化会话——其他一切都由python脚本处理。这是一个关于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\n", count);
1
LOOP:: -1
21 }
LOOP:: -1
19 doFunction();
LOOP:: 1
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
... 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 :) EDIT: version of avr-gdb in Ubuntu 11.04 is currently 6.4, which doesn't recognize the python command :()
…正如我想要的:P只是不知道它有多可靠(以及是否有可能在avr-gdb中使用,这正是我需要的:)
Well, hope this helps someone,
Cheers!
希望这能帮到别人,干杯!
Here some references:
这里一些参考:
- GDB: error detected on stdin
- GDB:在stdin上检测到的错误。
- GDB has problems with getting commands piped to STDIN
- GDB在向STDIN传输命令时存在问题
- Re: [Gdb] How do i use GDB other input?
- Re: [Gdb]如何使用Gdb其他输入?
- gdb doesn't accept input on stdin
- gdb不接受stdin上的输入
- Using gdb in an IDE - comp.os.linux.development.apps | Google Groups
- 在IDE .os.linux.development.apps |谷歌组中使用gdb
- rmathew: Terminal Sickness
- rmathew:终端疾病
- [TUTORIAL] Calling an external program in C (Linux) - GIDForums
- 在C (Linux) - gidforum中调用一个外部程序
- shell - how to use multiple arguments with a shebang (i.e. #!)? - Stack Overflow
- shell -如何使用shebang的多个参数(例如#!)?——堆栈溢出
- Redirecting/storing output of shell into GDB variable? - Stack Overflow
- 将shell的输出重定向/存储到GDB变量中?——堆栈溢出
- Corey Goldberg: Python - Redirect or Turn Off STDOUT and STDERR
- Corey Goldberg: Python -重定向或关闭STDOUT和STDERR。
- The Cliffs of Inanity › 9. Scripting gdb
- 虚无缥缈的悬崖9。脚本gdb
- gdb python scripting: where has
parse_and_eval
gone? - Stack Overflow - gdb python脚本:parse_and_eval去哪儿了?——堆栈溢出
- shell - Invoke gdb to automatically pass arguments to the program being debugged - Stack Overflow
- shell -调用gdb来自动将参数传递给正在调试的程序—堆栈溢出
- Storing Files/Directories In Memory With tmpfs | HowtoForge - Linux Howtos and Tutorials
- 使用tmpfs | HowtoForge在内存中存储文件/目录——Linux howto和教程
- simple way to touch a file if it does not exist | Python | Python
- 简单的触摸文件的方法,如果它不存在| Python | Python
- os.fork() different in cgi-script? - Python
- os.fork()在cgi脚本不同吗?Python -
- java - Writing tests that use GDB - how to capture output? - Stack Overflow
- java -使用GDB编写测试-如何捕获输出?——堆栈溢出
- Debugging with GDB: How to create GDB Commands in Python - Wiki
- 使用GDB调试:如何在Python - Wiki中创建GDB命令。
- GDB reference card
- GDB参考卡片
#2
3
Based on the link in @sdaau's answer (http://www.mail-archive.com/gdb@gnu.org/msg00031.html), I created my own script to simply keep sending 's' and reading the output of gdb continuously, while printing output to textfile and terminal, of course, my script can be modified to fit anyone else's needs, however, I hope that the modification I made should fit most people needs.
基于链接@sdaau的回答(http://www.mail-archive.com/gdb@gnu.org/msg00031.html),我创建了自己的脚本将发送“s”保存和阅读gdb不断的输出,同时打印输出文本文件和终端,当然,我的脚本可以修改以适应别人的需求,然而,我希望我做的修改应该符合大多数人的需要。
http://www.codeground.net/coding/gdb-step-into-all-lines-to-get-full-application-flow/
http://www.codeground.net/coding/gdb-step-into-all-lines-to-get-full-application-flow/
wget http://www.codeground.net/downloads/gdbwalkthrough.c
gcc gdbwalkthrough.c -o gdbwalkthrough
./gdbwalkthrough <application full path> [application arguments]
#3
3
What about doing it like this in gdb, using a command file. Change file argument, and loop count as required.
如何使用命令文件在gdb中这样做呢?更改文件参数,并按需要循环计数。
gdb -x run.gdb
run.gdb:
run.gdb:
set pagination off
set logging file gdb.log
set logging on
set $i = 0
file main
break main
break WriteData
# sadly, commands not getting executed on reaching breakpoint 2
commands 2
set $i=1000
print "commands 2 : %d",$i
end
run
while ( $i < 1000 )
step
# next
# continue
set $i = $i + 1
end
#4
1
As a new answer, since the previous is already hogged :) Basically, if the point is to observe execution of source (and/or assembly) code lines as the program as running - as the motivation is often for me when looking into "automatic printout" -- then, basically, a very quick way is to use GDB TUI mode; I quote:
作为一个新回答,因为前面已经占据:)基本上,如果问题是观察执行源(和/或装配)代码行程序一样运行,动机常常为我当调查“自动打印输出”——然后,基本上,一个非常快速的方法是使用GDB TUI模式;我引用:
c - gdb behavior : value optimized out - Stack Overflow #1354762
c - gdb行为:值优化出-堆栈溢出#1354762。
Use the GDB TUI mode. My copy of GDB enables it when I type the minus and Enter. Then type C-x 2 (that is hold down Control and press X, release both and then press 2). That will put it into split source and disassembly display. Then use stepi and nexti to move one machine instruction at a time. Use C-x o to switch between the TUI windows.
使用GDB TUI模式。我的拷贝的GDB使它当我输入-和进入。然后输入C-x 2(按住Control键,按X键,同时释放,然后按2),这将把它放入分割源和拆卸显示中。然后使用stepi和nexti一次移动一个机器指令。使用C-x o在TUI窗口之间切换。
The trick here is that, even if you hit continue
- this time source will be shown and indicated on the TUI; and followed as the program runs:
这里的诀窍是,即使你点击了继续-这个时间源将会在TUI中显示和显示;然后随着程序运行:
... and this for me avoids many situations where I'd have to script the breakpoints in "auto-stepping context" (although there are still such situations).. Docs about TUI: TUI - Debugging with GDB
…对于我来说,这避免了很多情况,我必须在“自动步进上下文”中编写断点(尽管仍然存在这种情况)。关于TUI的文档:TUI -与GDB的调试
Cheers!
干杯!