Unit testing 如何编写gdb脚本(使用python)?示例添加断点,运行,我们遇到了什么断点?
我试图用gdb创建一个小单元测试, 对于由控制的嵌入式mcu(通过gdb服务器控制我的目标) 因此,我想通过一些gdb脚本来实现这一点的自动化 我想为gdb编写某种脚本,或多或少地做到这一点:Unit testing 如何编写gdb脚本(使用python)?示例添加断点,运行,我们遇到了什么断点?,unit-testing,scripting,gdb,openocd,gdb-python,Unit Testing,Scripting,Gdb,Openocd,Gdb Python,我试图用gdb创建一个小单元测试, 对于由控制的嵌入式mcu(通过gdb服务器控制我的目标) 因此,我想通过一些gdb脚本来实现这一点的自动化 我想为gdb编写某种脚本,或多或少地做到这一点: 添加两个断点 启动程序 当我们停下来时,它停在哪里(获取帧信息) 退出 有什么想法吗 举一个关于如何在python gdb脚本中实现这一点的例子就好了 谢谢 约翰 注: 假设我们有这个基本结构, 或多或少进入测试失败()或测试成功() 取决于函数start_test()返回的内容 在gdb中手动执行此操
注: 假设我们有这个基本结构, 或多或少进入测试失败()或测试成功() 取决于函数start_test()返回的内容 在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似乎支持。好的,我在问问题时找到了答案。。。这真的很简单 如果希望以特定顺序执行“-command”和“-eval”,则不应同时使用它们 一种更容易预测的方法是将所有内容放在commands.gdb文件中并忽略--eval 所以它变成了这样:
arm-none-eabi-gdb --batch --command=commands.gdb main.elf
break test_success
break test_failed
target remote localhost:3333
cont
frame
(gdb) source script.py
其中commands.gdb如下所示:
arm-none-eabi-gdb --batch --command=commands.gdb main.elf
break test_success
break test_failed
target remote localhost:3333
cont
frame
(gdb) source script.py
但是,用类似python的东西来实现这一点可能会更好。仅供参考,最近的gdb版本可以用python编写脚本。您可以从gdb命令行调用python代码。这将打开一个全新的世界,请查看相关文档。从命令行运行:
dnf/yum/apt-get install gdb-doc
info gdb extending python
如果您不喜欢基于文本的信息浏览器,这里有一个(在许多浏览器中?)可供选择的图形浏览器:
yelp 'info:gdb' # , go to "Extending"
下面是一个示例gdb python脚本。它将gdb连接到发现正在运行的第一个“your_程序”
#!/usr/bin/python
import subprocess
import string
def backquotes(cmdwords):
output = subprocess.Popen(cmdwords, stdout=subprocess.PIPE).communicate()[0]
return output.strip()
pid = backquotes(['pgrep', 'your_program'])
gdb.execute("attach " + str(pid))
我目前使用的一个简化示例:
类调试打印断点(gdb.Breakpoint):
调试_id=frozenset({37153420})
def停止(自):
top=gdb.最新的_帧()
someVector=top.read_var('aVectorVar'))
访问gd标准C++中的STD:()和:():
first=someVector[''M_impl'][''M_start']
last=someVector[''M_impl'][''M_finish']
值=[]
而第一次最后:
values.append(int(first.dereference()['intID']))
第一个=第一个+1
如果未设置(值)和调试ID:
return False#skip:我们要查找的项目中没有一项可以通过堆栈向量中的ID找到
打印(“找到其他伴随ID:{}”。格式(值))
返回True#返回gdb的提示
#确保已加载共享库
gdb.execute(“启动”)
#设置断点,该断点恰好位于某个共享库中,因此前面使用了“start”
调试打印断点(“source.cpp:42”)
gdb.执行(“继续”)
您可以从gdb的提示符执行此脚本,如下所示:
arm-none-eabi-gdb --batch --command=commands.gdb main.elf
break test_success
break test_failed
target remote localhost:3333
cont
frame
(gdb) source script.py
或从命令行:
$ gdb --command script.py ./executable.elf
有关更多信息,请参阅完整部分。只想指出一些我在回到这个主题时感到困惑的事情(注意,我目前使用的是Ubuntu 14.04、GNU gdb(Ubuntu 7.7.1-0ubuntu5~14.04.3)7.7.1): 首先,有人提到它“可以作为解释器调用
gdb
”:
#编写一个脚本文本文件/usr/bin/gbd-P
或#/usr/bin/gbd--python
,然后在其中编写python代码,然后使其可执行chmod+x pygdbscript
,然后运行/pygdbscript
。。。但正如本文所述:
gdb:unrecognedoption'-python'
。显然,这个选项是/曾经是gdb
?“archer”分支的一个特性
因此,为了在
gdb
中运行Python脚本,实际上有两种方法:
- 用扩展名
命名脚本文件;在这里说.py
:test.py
def Something():
打印(“来自python的你好”)
某物
gdb.执行(“退出”);
注意,在本例中,您只需编写简单的Python代码;并且您不需要导入gdb
来访问gdb
对象。您可以使用以下任一选项运行此命令:
gdb-x test.py
gdb-x=test.py
gdb——命令test.py
gdb--command=test.py
gdb-command test.py
gdb-command=test.py
。。。这似乎是等效的,因为在脚本指示退出之前,gdb
的结果是相同的打印输出:
$ gdb -x=test.py
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
...
For help, type "help".
Type "apropos word" to search for commands related to "word".
hello from python
注意对于这种情况,类似于test.gdb.py
的名称也将被解释为纯Python脚本,因为它们以.py
结尾
- 为脚本命名其他名称-只要它不以
扩展名结尾;在这里说.py
:test.pygdb
gdb
将脚本解释为一个gdb
脚本,即使用gdb
命令-这意味着,无论您想在这里编写什么Python代码,都必须用“Python
”作为起始行,并在Python代码的末尾用“end
”包装。同样,它将通过以下任何等效调用调用:
gdb-x test.pygdb
gdb-x=test.pygdb
gdb--命令test.pygdb
gdb—命令=test.pygdb
gdb-命令test.pygdb
gdb-command=test.pygdb
。。。然后输出与前一种情况相同(因为它运行的是同一个Python脚本):
以及对OP的响应:如果OP中的C代码位于
/tmp/myprog.C