【GDB】用 python 扩展 gdb

news2024/12/23 23:28:52

用 python 扩展 GDB

.gdbinit 文件中实现自定义命令 mv 代码如下

define mv
    if $argc == 2
        delete $arg0
        # 注意新创建的断点编号和被删除断点的编号不同
        break $arg1
    else
        print "输入参数数目不对,help mv 以获得用法"
    end
end

# (gdb) help mv 会输出以下帮助文档
document mv
Move breakpoint.
Usage: mv old_breakpoint_num new_breakpoint
Example:
    (gdb) mv 1 binary_search -- move breakpoint 1 to `b binary_search`

end

python 实现代码如下

# move.py
# 1. 导入 gdb 模块来访问 gdb 提供的 python 接口
import gdb


# 2. 用户自定义命令需要继承自 gdb.Command 类
class Move(gdb.Command):

    # 3. docstring 里面的文本是不是很眼熟?gdb 会提取该类的__doc__属性作为对应命令的文档
    """Move breakpoint
    Usage: mv old_breakpoint_num new_breakpoint
    Example:
        (gdb) mv 1 binary_search -- move breakpoint 1 to `b binary_search`
    """

    def __init__(self):
        # 4. 在构造函数中注册该命令的名字
        super(self.__class__, self).__init__("mv", gdb.COMMAND_USER)

    # 5. 在 invoke 方法中实现该自定义命令具体的功能
    # args 表示该命令后面所衔接的参数,这里通过 string_to_argv 转换成数组
    def invoke(self, args, from_tty):
        argv = gdb.string_to_argv(args)
        if len(argv) != 2:
            raise gdb.GdbError('输入参数数目不对,help mv 以获得用法')
        # 6. 使用 gdb.execute 来执行具体的命令
        gdb.execute('delete' + argv[0])
        gdb.execute('break' + argv[1])

# 7. 向 gdb 会话注册该自定义命令
Move()

.gdbinit 文件中导入 python 文件

layout src
# 导入 python 文件
source test.py
...
...

这样 gdb 每次启动时都会替我们 source 一下

gdb 的 python 接口

gdb 通过 gdb 模块提供了不少 python 接口。其中最为常用的是 gdb.executegdb.parse_and_eval

  • gdb.execute 可用于执行一个 gdb 命令。默认情况下,结果会输出到 gdb 界面上。如果想把输出结果转存到字符串中,设置 to_string 为 True:gdb.execute(cmd, to_string=True)。

  • gdb.parse_and_eval 接受一个字符串作为表达式,并以 gdb.Value 的形式返回表达式求值的结果。举例说,gdb 当前上下文中有一个变量 i,i 等于 3。那么 gdb.parse_and_eval(‘i + 1’) 的结果是一个 gdb.Value 的实例,其 value 属性的值为 4。这跟 (gdb) i + 1 是等价的。

何为 gdb.Value?在 gdb 会话里,我们可以访问 C/C++ 类型的值。当我们通过 python 接口跟这些值打交道时,gdb 会把它们包装成一个 gdb.Value 对象。

举个例子,struct Point 有 x 跟 y 两个成员。现在假设当前上下文中有一个 Point 类型的变量 point 和指向该变量的 Point 指针 p,就意味着:

point = gdb.parse_and_eval('point')
point['x'] # 等价于point.x
point['y'] # 等价于point.y
point.referenced_value() # 等价于&point

p = gdb.parse_and_eval('p')
point2 = p.dereference() # 等价于*p
point2['x'] # 等价于(*p).x,也即p->x

示例

C 代码

#include <stdio.h>

typedef struct
{
    int x;
    int y;
} point_t;

int binary_search(int *ary, unsigned int ceiling, int target)
{
    unsigned int floor = 0;
    while (ceiling > floor)
    {
        unsigned int pivot = (ceiling + floor) / 2;
        if (ary[pivot] < target)
            floor = pivot + 1;
        else if (ary[pivot] > target)
            ceiling = pivot;
        else
            return pivot;
    }
    return -1;
}

void set_point_data(point_t *point_in, point_t *p_point_in, int x, int y)
{
    point_in->x = x;
    point_in->y = y;

    return;
}

int main(int argc, char *argv)
{
    int a[] = {1, 2, 4, 5, 6};

    point_t point1;
    point_t *p_point;

    printf("%d\r\n", binary_search(a, 5, 7)); /* -1 */
    printf("%d\r\n", binary_search(a, 5, 6)); /* 4 */
    printf("%d\r\n", binary_search(a, 5, 5)); /* 3 */

    p_point = &point1;
    point1.x = 78;
    point1.y = 78;

    set_point_data(&point1, p_point, 1, 2);

    printf("%d %d\r\n", point1.x, point1.y);
    printf("%d %d\r\n", p_point->x, p_point->y);

    return 0;
}

.gdbinit 代码

layout src
# 导入 python 文件
source test.py

b main
b binary_search if target == 5

b set_point_data
# set_point_data 触发的命令
comm
# 向命令 print_point 传递的参数是 *point_in 和 p_point_in
print_point *point_in p_point_in
end

# 断点 1 触发执行的命令
command 1
i locals
i args
end

# 断点 2 触发执行的命令
comm 2
i locals
i args
end

python 代码

# 1. 导入gdb模块来访问gdb提供的python接口
import gdb

# 2. 用户自定义命令需要继承自gdb.Command类
class Move(gdb.Command):

    # 3. docstring里面的文本是不是很眼熟?gdb会提取该类的__doc__属性作为对应命令的文档
    """Move breakpoint
    Usage: mv old_breakpoint_num new_breapkpoint
    Example:
        (gdb) mv 1 binary_search -- move breakpoint 1 to `b binary_search`
    """

    def __init__(self):
        # 4. 在构造函数中注册该命令的名字
        super(self.__class__, self).__init__("mv", gdb.COMMAND_USER)

    # 5. 在invoke方法中实现该自定义命令具体的功能
    # args表示该命令后面所衔接的参数,这里通过string_to_argv转换成数组
    def invoke(self, args, from_tty):
        argv = gdb.string_to_argv(args)
        if len(argv) != 2:
            raise gdb.GdbError('输入参数数目不对,help mv以获得用法')
        # 6. 使用gdb.execute来执行具体的命令
        gdb.execute('delete ' + argv[0])
        gdb.execute('break ' + argv[1])


# 7. 向gdb会话注册该自定义命令
Move()

class print_point(gdb.Command):
    def __init__(self):
        super(self.__class__, self).__init__("print_point", gdb.COMMAND_USER)

    def invoke(self, args, from_tty):
        point = gdb.parse_and_eval('point_in')
        print(point['x']) # 等价于 point.x
        print(point['y']) # 等价于 point.y
        point.referenced_value() # 等价于 &point

        p = gdb.parse_and_eval('p_point_in')
        point2 = p.dereference() # 等价于 *p
        print(point2['x']) # 等价于 (*p).x,也即 p->x
        print(point2['y']) # 等价于 (*p).y,也即 p->y
print_point()

效果

在这里插入图片描述

参考

https://github.com/kfggww/algorithms-in-c/tree/main
https://segmentfault.com/a/1190000005718889

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1051267.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

搭建自己的搜索引擎之四

一、前言 搭建自己的搜索引擎之三 介绍了通过HTTP RESTful 对ES进行增删改查&#xff0c;这一般手工运维ES时使用&#xff0c;程序代码中最好还是使用Java API去操作ES会更容易维护&#xff0c;但ES API竟然贼多&#xff0c;本篇介绍一下 四种 API及其简单使用。 注&#xff…

深入理解二叉树:结构、遍历和实现

文章目录 &#x1f34b;引言&#x1f34b;什么是二叉树&#xff1f;&#x1f34b;二叉树的基本性质&#x1f34b;二叉树的遍历&#x1f34b;二叉树的实现&#x1f34b;结语 &#x1f34b;引言 在计算机科学中&#xff0c;二叉树是一种重要的数据结构&#xff0c;广泛应用于各种…

【密评】商用密码应用安全性评估从业人员考核题库(二)

商用密码应用安全性评估从业人员考核题库&#xff08;二&#xff09; 国密局给的参考题库5000道只是基础题&#xff0c;后续更新完5000还会继续更其他高质量题库&#xff0c;持续学习&#xff0c;共同进步。 251 多项选择题 根据《密码法》&#xff0c;核心密码、普通密码安全…

Linux常用命令(一)

目录 一、列出目录内容&#xff08;ls&#xff09; 二、切换目录&#xff08;cd&#xff09; 三、显示当前目录路径&#xff08;pwd&#xff09; 四、以树状结构显示目录内容&#xff08;tree&#xff09; 五、创建新目录&#xff08;mkdir&#xff09; 六、复制文件或目…

windows11 如何关闭 vbs

在Windows 11中&#xff0c;VBS是一种虚拟化安全功能&#xff0c;它可以防止恶意软件通过沙箱环境运行。 如果您想关闭VBS功能&#xff0c;方法如下&#xff1a; 点击底部开始菜单 在上方搜索 cmd &#xff0c;并点击以管理员身份运行 打开控制台后&#xff0c;在控制台输入…

文档图像处理:大模型的突破与新探索

前言 随着数字化时代的到来&#xff0c;文档图像处理技术在各行各业扮演着越来越重要的角色。在2023第十二届中国智能产业高峰论坛&#xff08;CIIS 2023&#xff09;的专题论坛上&#xff0c;合合信息智能技术平台事业部副总经理、高级工程师丁凯博士分享了当前文档图像处理面…

wallis匀色算法、直方图匹配、颜色转移方法比较

算法原理 这三种方法应该是比较基础的匀色处理算法 三个算法的原理比较简单&#xff0c;具体原理大家可以自己百度 &#xff08;1&#xff09;wallis匀色原理主要在于利用Wallis滤波器使原始图像的均值和标准差与参考影像相当&#xff0c;从而使原始影像和参考影像具有相近的色…

Oracle的递归公共表表达式

查询节点id为2的所有子节点的数据&#xff0c;包括向下级联 WITH T1 (id, parent_id, data) AS (SELECT id, parent_id, dataFROM nodesWHERE id 2UNION ALLSELECT t.id, t.parent_id, t.dataFROM nodes tJOIN T1 n ON t.parent_id n.id ) SELECT * FROM T1; --建表语句 C…

今天出门竟然忘了带套

今天是没有抢到票的打工人节前的最后一天&#xff0c;7点醒来&#xff0c;磨磨蹭蹭&#xff0c;解决完个人问题&#xff0c;7.35才出门&#xff0c;正常来说最晚7.30出门&#xff0c;骑上哈啰、挤上地铁才能保证打上卡。 说出来不怕各位同行笑话&#xff0c;谁能想到一个高速发…

打卡新“姿势”,多种打卡方式并行

打卡工具 路径 拓展 >> 工具 功能简介 在打卡工具 “班次管理”中&#xff0c;支持多种打卡方式。可同时选择「地点打卡」和「智能安全帽打卡」两种方式进行打卡。 注&#xff1a; 「地点打卡」可设置考勤地点&#xff1b; 「智能安全帽打卡」可设置电子围栏范围。…

排序篇(一)----插入排序

1.直接插入排序 插入排序的思想: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 。 你可以想像成打牌一样,比如说斗地主,一张一张的摸牌,然后把手上的这些牌变成手续的排列.…

【教学类-38】A4红纸-国旗灯笼(庆祝中华人民共和国成立74周年)

作品展示&#xff1a; 背景需求&#xff1a; 从教十余年&#xff0c;我在每年国庆都带领中大班孩子们制作与“国旗相关”国庆庆祝物品——国旗、礼盒 一、国旗&#xff08;吸管、A4红纸、黄纸打印五角星&#xff09; 二、铅画纸手提袋&#xff08;8K铅画纸、A4红纸、黄色打印…

Windows的批处理——获取系统时间、生成当天日期日志

Windows批处理基础https://coffeemilk.blog.csdn.net/article/details/132118351 一、Windows批处理的日期时间 在我们进行软件开发的过程中&#xff0c;有时候会使用到一些批处理命令&#xff0c;其中就涉及到获取系统日期、时间来进行一些逻辑的判断处理&#xff1b;那么我们…

Ubuntu 部署 Seata1.7.1

一、环境说明 IP操作系统程序备注10.0.61.22ubuntu20.04PostgreSQL-14.11已提前部署10.0.61.21ubuntu20.04Nacos-2.1.0已提前部署10.0.61.22ubuntu20.04seata-server-1.7.1本文将要部署 二、部署 1. 下载 wget https://github.com/seata/seata/releases/download/v1.7.1/se…

VUE2项目:尚品汇VUE-CLI脚手架初始化项目以及路由组件分析(一)

标题 环境VUE2目录publicassetscomponentsmain.jsbabel.config.jspackage.jsonvue.config.js 项目路由分析Header与Footer非路由组件完成Header示例 路由组件的搭建声明式导航编程式导航 Footer组件的显示与隐藏路由传递参数重写push和replace三级联动组件拆分附件 环境 前提要…

Scala第四章节

Scala第四章节 scala总目录 章节目标 掌握分支结构的格式和用法掌握for循环和while循环的格式和用法掌握控制跳转语句的用法掌握循环案例理解do.while循环的格式和用法 1. 流程控制结构 1.1 概述 在实际开发中, 我们要编写成千上万行代码, 代码的顺序不同, 执行结果肯定也…

GD32工程创建

1.创建空工程 在任意路径下创建空的test文件夹。打开keil5空工程创建空工程 选择对应的芯片型号&#xff1a; 然后把空工程保存到test文件夹下。会自动生成如下文件。 2. 添加组 下载GD32F10X的固件库&#xff1a;在百度里搜索GD32进入官网。 下载下来对应的文件如下&#xff…

问题记录 springboot 事务方法中使用this调用其它方法

原因: 因为代理对象中调用了原始对象的toString()方法,所以两个不同的对象打印出的引用是相同的

HTML详细基础(三)表单控件

本帖介绍web开发中非常核心的标签——表格标签。 在日常我们使用到的各种需要输入用户信息的场景——如下图&#xff0c;均是通过表格标签table创造出来的&#xff1a; 目录 一.表格标签 二.表格属性 三.合并单元格 四.无序列表 五.有序列表 六.自定义标签 七.表单域 …

Java微信分享接口开发

概述 微信JS-SDK实现自定义分享功能&#xff0c;分享给朋友&#xff0c;分享到朋友圈 详细 概述 概述 微信公众平台开始支持前端网页&#xff0c;大家可能看到很多网页上都有分享到朋友圈&#xff0c;关注微信等按钮&#xff0c;点击它们都会弹出一个窗口让你分享和关注&…