当前位置:首页>python>GDB高级调试技巧-使用Python脚本实例:函数返回特定值就暂停

GDB高级调试技巧-使用Python脚本实例:函数返回特定值就暂停

  • 2026-09-02 20:14:50
GDB高级调试技巧-使用Python脚本实例:函数返回特定值就暂停

一.前言

    嵌入式开发中GDB进行调试是必备手段,GDB拥有强大的脚本集成能力,尤其是支持Python脚本,可以使用Python 扩展GDB。注意:GDB构建时需要配置--with-python选项才会支持Python脚本,一般使用现成的二进制GDB工具, 这个选项是会配置的。

    利用脚本我们能实现自动化测试,提高调试效率等。这里就来分享在GDB调试中Python脚本的使用,分享一些实例,更多信息可以直接参考GDB的文档。

二.GDB中的Python简介

    以下介绍GDB中Python的一些基础内容。

2.1获取帮助

GDB环境中,输入help python显示如下

(gdb) help pythonpython, pyEvaluate a Python command.The command can be given as an argument, for instance:python print (23)If no argument is given, the following lines are read and usedas the Python commands. Type a line containing "end" to indicatethe end of the command.(gdb) 

输入python help (gdb)可以查看Python API帮助

(gdb) python help (gdb)Help on package gdb:NAMEgdb - # Copyright (C) 2010-2020 Free Software Foundation, Inc.PACKAGE CONTENTSFrameDecoratorFrameIteratorcommand (package)framesfunction (package)printer (package)printingprompttypesunwinderxmethodSUBMODULESevents

2.2Data文件

    GDB有时会读取辅助数据文件。这些文件存储在称为数据目录data directory的目录中。

这个目录可以通过GDB环境的show data-directory命令查看,通过set data-directory directory命令设置

例如

(gdb) show data-directoryGDB's data directory is ".../directory /opt/riscv-toolchain/10.2.0/share/gdb".(gdb) set data-directory /opt/riscv-toolchain/10.2.0/share/gdb(gdb) 

也可以在执行GDB时指定--data-directory选项, 例如

riscv64-unknown-elf-gdb --data-directory=/opt/riscv-toolchain/10Quit/share/gdb

而该目录的默认配置是在构建配置时的--with-gdb-datadir选项指定的, 如果指定为‘--prefix’ 或‘--exec-prefix’对应的二进制文件目录, 则该目录会随着GDB的安装路径自动变化。

Python脚本的牧人搜索路径就是上述

Datadirectory下的python

比如我这里的

root@qinyunti:~/# ls /opt/riscv-toolchain/10.2.0/share/gdbpython syscalls  system-gdbinitroot@qinyunti:~/# ls /opt/riscv-toolchain/10.2.0/share/gdb/python/gdb/FrameDecorator.py __init__.py  command    function  printing.py  types.py     xmethod.pyFrameIterator.py __pycache__  frames.py  printer   prompt.py    unwinder.pyroot@qinyunti:~/# 

注意上述的两个子目录command function

data-directory/python/gdb/command 或 data-directory/python/gdb/function中的命令或者函数会自动在GDB启动时导入。

root@qinyunti:~/# ls /opt/riscv-toolchain/10.2.0/share/gdb/python/gdb/command/__init__.py __pycache__  explore.py  frame_filters.py  pretty_printers.py  prompt.py  type_printers.py  unwinders.py  xmethods.pyroot@qinyunti:~/# ls /opt/riscv-toolchain/10.2.0/share/gdb/python/gdb/function/__init__.py __pycache__  as_string.py  caller_is.py  strfns.pyroot@qinyunti:~/# 

2.3执行Python脚本的方式

2.3.1直接命令行输入

直接GDB命令行中输入脚本

GDB中输入python回车进入python命令行交互环境

输入脚本,最后以end结束, 例如

定义函数add_function(a,b), 然后python add_function(1,2)调用执行

(gdb) python>def add_function(a,b):> c = a + b> print(f"{a}+{b}={c}")>end(gdb) python add_function(1,2)1+2=3(gdb) 

2.3.2脚本文件

新建add.py输入以下内容

def add_function(a,b):   c = a + b   print(f"{a}+{b}={c}")

 导入脚本source add.py

执行脚本python add_function(2,3)

data-directory/python/gdb/command 或 data-directory/python/gdb/function中的会自动导入无需source手动导入。

2.4 Python支持的模块

GDB自带多个模块来辅助编写Python代码。

• gdb.printing:构建和注册美观打印。

• gdb.types:用于处理类型的工具。

• gdb.prompt:用于快速值替代的实用工具。

• gdb.ptwrite:PTWRITE滤波器注册工具。

详见

https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python-modules.html#Python-modules

2.5 Python API

详见

https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python-API.html#Python-API

2.6参考

更多内容可以参考GDB的在线文档

https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python-API.html#Python-API

三. 实例在函数返回指定值后停止

    在调试时,有一种比较常见的需求,希望能在某个函数返回某个值时暂停,以查看当时状态,手动的方式是在函数返回处打断点,然后不断c, 并打印返回值,这样比较繁琐,尤其是在函数频繁调用且很小概率返回需要的值时。 此时就可以使用Python脚本来实现,返回特定值后自动暂停。

创建test.py

import gdbclass FunctionFinishBreakpoint (gdb.FinishBreakpoint):   def __init__ (self):       gdb.FinishBreakpoint.__init__(self, gdb.newest_frame(),                                      internal=True)       self.silent = True    def stop(self):       print("after: {}".format(self.return_value))       return self.return_value == 5class FunctionBreakpoint(gdb.Breakpoint):   def __init__ (self, spec):       gdb.Breakpoint.__init__(self, spec)       self.silent = True   def stop (self):       print("before")       FunctionFinishBreakpoint() # set breakpoint on function return       return False # do not stop at function entryFunctionBreakpoint("test")

source test.py时自动执行

FunctionBreakpoint("test")test为需要监控的函数名字

FunctionBreakpoint("test")的作用是每次在test执行时回调FunctionBreakpoint.stop且回调是silent的,此时调用FunctionFinishBreakpoint() 

而FunctionFinishBreakpoint.stop在其stop函数返回False时不暂停,返回True时暂停。

所以return not self.return_value表示返回0时暂停。

Breakpoint参考https://sourceware.org/gdb/current/onlinedocs/gdb.html/Breakpoints-In-Python.html#Breakpoints-In-PythonFinishBreakpoint参考https://sourceware.org/gdb/current/onlinedocs/gdb.html/Finish-Breakpoints-in-Python.html#Finish-Breakpoints-in-Python

测试代码

static  __attribute__((optimize("O0"))) int test(int i) {   return i;}   for(int i=0;i<10;i++){       int res = test(i);       char buf[16];       itoa(buf, res);       uart_put_string(buf);   }

看到source test.py后打印如下

(gdb) source test.pyBreakpoint 1 at 0x1000ba: file main.c, line 89.(gdb) cContinuing.beforeafter: 0beforeafter: 1beforeafter: 2beforeafter: 3beforeafter: 4beforeafter: 5(gdb) p i$1 = 5(gdb) 

可以看到返回5时就暂停了,此时查看i也是5

三. 总结

    使用Python 扩展 GDB可以方便自动化测试,提高调试效率,以上仅做简单介绍, 分享了一个简单的实例。平时可以多积累一些实例脚本,以便不时之需。 更详细的Python脚本语法等可参考GDB的文档。

最新文章

随机文章