如何编写 gdb 脚本(使用 python)?示例添加断点,运行,我们碰到了什么断点?
我正在尝试使用 gdb 创建一个小单元测试, 对于由 OpenOCD 控制的嵌入式 MCU(这使我可以通过 gdb 服务器控制我的目标) 。
所以我想通过 gdb 的一些脚本来自动执行此操作。
我想为 gdb 编写某种脚本,或多或少可以执行以下操作:
- 添加几个断点
- 启动程序
- 当我们停止时,它在哪里停止(获取帧信息)
- 退出。
有什么想法吗?
关于如何在 python gdb 脚本中执行此操作的示例会很好。
谢谢 Johan
注意:
假设我们有这个基本结构, 或多或少进入 test_failed() 或 test_success() 取决于函数 start_test() 返回的内容。
void test_failed() {
while(1);
}
void test_success() {
while(1);
}
int main(void) {
int status = start_test();
if( status > 0 ) {
test_failed();
}
test_success();
while(1);
}
在 gdb 中手动执行此操作非常困难,
(gdb) break test_success
Breakpoint 1 at 0x20: file src/main.c, line 9.
(gdb) break test_failed
Breakpoint 2 at 0x18: file src/main.c, line 5.
(gdb) cont
Continuing.
Breakpoint 1, test_success () at src/main.c:9
9 while(1);
(gdb) frame
#0 test_success () at src/main.c:9
9 while(1);
(gdb)
因此我尝试的下一步是将这些 gdb 命令添加到 gdb 启动脚本中,该脚本或多或少看起来像这样。
break test_success
break test_failed
target remote localhost:3333
cont
frame
并开始它
arm-none-eabi-gdb --batch --command=commands.gdb main.elf
这种工作,但不是很好。 我如何使用“新而酷”的Python脚本来做到这一点, gdb好像支持。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
仅供参考,最近的 gdb 版本可以用 Python 编写脚本。您可以从 gdb 命令行调用 python 代码。这打开了一个全新的世界,查看相关文档。从命令行运行:
如果您不喜欢基于文本的信息浏览器,这里有一个(众多?)替代图形浏览器:
这是一个示例 gdb-python 脚本。它将 gdb 附加到第一个发现正在运行的“your_program”。
FYI recent gdb versions are scriptable in Python. You can call python code from the gdb command line. This opens a whole new world, check the relevant documentation. From the command line run:
If you do not like the text-based info browser, here is one (among many?) alternative, graphical browser:
Here is a sample gdb-python script. It attaches gdb to the first "your_program" found running.
我当前正在使用的简化示例:
您可以从 gdb 的提示符执行此脚本,如下所示:
或从命令行:
请参阅完整的 GDB Python API 文档 了解更多信息。
A reduced example that I'm currently using:
You can execute this script from gdb's prompt like this:
Or from the command-line:
See the complete GDB Python API docs for further info.
好吧,我在问问题的时候找到了答案……而且这是一件非常简单的事情。
如果您希望以特定顺序执行“--command”和“--eval”,则不应同时使用它们!
一种更可预测的方法是将所有内容放入commands.gdb 文件中并忽略--eval。
所以它变得像这样:
其中commands.gdb看起来像这样:
但是用像python这样的东西来代替可能会更好。
OK, I found the answer while asking the question... and it and it was a really simple thing.
You should not use both the "--command" and the "--eval" at the same time if you expect them to be executed in a specific order!
A more predicable way is to put everything in the commands.gdb file and ignore --eval.
So it becomes something like this:
Where commands.gdb looks like this:
But it would probably be so much nicer to do this with something like python instead.
只是想指出一些我每次回到这个主题时都感到困惑的事情(注意,我目前使用的是 Ubuntu 14.04,GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1):
首先,有关于它“可以调用
gdb
作为解释器”的引用:..意思是,可以使用 shebang 行
#!/usr/bin/gbd -P
或#!/usr/bin/gbd --python
编写脚本文本文件。 ,然后在里面写入Python代码,然后使其可执行chmod +x pygdbscript
,然后运行./pygdbscript
; ...但正如这篇文章中所示:...,如果我尝试类似的操作,我会得到
gdb: unrecognized option '--python'
。显然这个选项是/曾经是gdb
的某个“archer”分支的一个功能?!因此,要在
gdb
中运行 Python 脚本,实际上有两种方法:.py
;在这里说test.py
:注意,在这种情况下,您只需编写简单的 Python 代码;并且您不需要
import gdb
来访问gdb
对象。您可以使用以下任一命令运行:...这似乎是等效的,因为在脚本指示 gdb 退出之前,其中任何一个的结果都是相同的打印输出:
注意 对于这种情况,像
test.gdb.py
这样的名称也将被解释为纯 Python 脚本,因为那时以.py
结尾。.py
扩展名结尾即可;在这里说test.pygdb
:在这种情况下,
gdb
将脚本解释为gdb
脚本,即使用gdb
> 命令 - 这意味着,无论您想在此处编写什么 Python 代码,必须 都包含在“python
”作为起始行和“end”中
”位于 Python 代码末尾。同样,它将通过任何这些等效调用来调用:...然后输出与前一种情况相同(因为它运行的是相同的 Python 脚本):
并且响应 OP:如果 C 代码OP 位于
/tmp/myprog.c
中 - 添加了int start_test() { return rand() % 50; }
放在上面,否则无法编译 - ,并使用gcc -g myprog.c -o myprog.exe
编译成/tmp/myprog.exe< /代码>;那么您可以使用
myprog.gdb.py
脚本,如下所示:... 然后运行此脚本:
请注意,在此脚本的末尾,
(gdb)
交互提示依然存在,这里可以正常使用;如果您不需要交互式提示,您可以像上面的脚本一样执行gdb.execute("quit");
来强制gdb
在结束时退出脚本执行。另外,有关 gdb Python 中子类化断点类的示例,请参阅 如何在 GDB 中的断点处打印源代码的当前行,而不打印其他内容?
Just wanted to note something that I find confusing whenever I come back to this topic (Note, I'm currently on Ubuntu 14.04, GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1):
First, there are references about it being "possible to invoke
gdb
as an interpreter":... meaning, one would write a script text file with the shebang line
#!/usr/bin/gbd -P
or#!/usr/bin/gbd --python
, then write Python code in it, then make it executablechmod +x pygdbscript
, then run./pygdbscript
; ... but as in this post:..., I get
gdb: unrecognized option '--python'
if I try anything like that. Apparently this option is/was a feature in some "archer" branch ofgdb
?!So, in order to run a Python script in
gdb
, there are actually two ways:.py
; saytest.py
here:Note, in this case, you just write plain Python code; and you do not need to
import gdb
in order to access thegdb
object. This you can run with either of:... which seem to be equivalent, as the result for any of these is the same printout, before
gdb
is instructed to exit by the script:NOTE that for this case, also names like
test.gdb.py
will be interpreted as pure Python scripts, since then end in.py
..py
extension; saytest.pygdb
here:In this case,
gdb
interprets the script as being agdb
script, i.e. withgdb
commands - and that means, that whatever Python code you may want to write in here, must be wrapped in "python
" as a starting line and "end
" at end of the Python code. Again, it would be called with any of these equivalent calls:... and then the output is the same as in the previous case (since it is the same Python script running):
And in response to OP: if the C code in OP is in
/tmp/myprog.c
- with an addedint start_test() { return rand() % 50; }
on top, otherwise it won't compile - , and is compiled with withgcc -g myprog.c -o myprog.exe
into/tmp/myprog.exe
; then you can use amyprog.gdb.py
script like this:... then run this script with:
Note that at the end of this script, the
(gdb)
interactive prompt remains, and you can use it normally here; if you don't need the interactive prompt, you can dogdb.execute("quit");
as in the above scripts to forcegdb
to exit instead at end of script execution.Also, for an example of subclassing breakpoint class in gdb Python, see How to print the current line of source at breakpoint in GDB and nothing else?