gdb中使用python脚本

1、入门案例

首先有1个a.cpp,代码如下:

#include <map>
#include <set>
#include <iostream>
#include <string>using namespace std;struct MyStruct {std::string mName;std::map<int, std::string> mField1;std::set<std::string> mField2;int mI;int mJ;
};int main() {std::map<int,string> lm;std::set<std::string> ls;MyStruct s = {std::string("student"), lm, ls, 3, 4};return 0;
}

上面的C代码中有一个结构体MyStruct,如果想要打印结构体的内容。在GDB 9.X版本中打印出来是这样

$1 = {mName = "student", mField1 = std::map with 0 elements, mField2 = std::set with 0 elements, mI = 3, mJ = 4}

如果使用的是GDB 7.X,打印出来就是这样

$1 = {mName = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fffffffe380 "student"},_M_string_length = 7, {_M_local_buf = "student\000\000\000\000\000\000\000\000", _M_allocated_capacity = 32772479054607475}}, mField1 = {_M_t = {_M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<int const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {<No data fields>}, <No data fields>}, <std::_Rb_tree_key_compare<std::less<int> >> = {_M_key_compare = {<std::binary_function<int, int, bool>> = {<No data fields>}, <No data fields>}}, <std::_Rb_tree_header> = {_M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0x7fffffffe398,_M_right = 0x7fffffffe398}, _M_node_count = 0}, <No data fields>}}}, mField2 = {_M_t = {_M_impl = {<std::allocator<std::_Rb_tree_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>}, <std::_Rb_tree_key_compare<std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {_M_key_compare = {<std::binary_function<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool>> = {<No data fields>}, <No data fields>}}, <std::_Rb_tree_header> = {_M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0x7fffffffe3c8, _M_right = 0x7fffffffe3c8}, _M_node_count = 0}, <No data fields>}}},mI = 3, mJ = 4}

可以看到在GDB 9.X中打印出来的要美观很多,主要是由于GDB 9.x自带了一系列标准库的Python Pretty Printer(美观打印器)。如果想要查看原始的数据,可以使用 p /r s命令。

当然我们也可以实现字节的美观打印器。主要需要完成下面几个功能:

(1)自定义打印类,提供to_string()方法,该方法返回希望打印出来的字符串。

(2)创建判断函数,判断一个值是否需要使用自定义的打印类来打印。

(3)将判断函数注册到GDB美观打印函数中。

下面直接看完整的代码,t.py

class MyPrinter:def __init__(self, val):self.val = valdef to_string(self):return "name: {} integer: {}".format(self.val['mName'], self.val['mI'])def lookup_pretty_printer(val):if val.type.code == gdb.TYPE_CODE_PTR:return Noneif 'MyStruct' == val.type.tag:return MyPrinter(val)return None
gdb.printing.register_pretty_printer(gdb.current_objfile(),lookup_pretty_printer,replace=True)

简单解释下上面的python代码。

1、定义了一个名为 MyPrinter 的类,它有一个构造函数,接收一个 val 参数。参数就是p s中的s, to_string 方法定义了如何将 MyStruct 对象转换为字符串,例子中包含 mNamemI 字段的值。

2、lookup_pretty_printer 这个函数用来决定是否使用 MyPrinter 来打印某个值。如果传入的 val 是指针类型,则直接返回 None,表明不需要特别处理。如果 val 的类型标签是 MyStruct,则返回一个新的 MyPrinter 实例,否则也返回 None

3、最后一行,gdb.printing 是 GDB 的一个 Python 接口模块,它提供了一系列与 pretty printing 相关的功能。Pretty printing 是一种用于美化或格式化输出的技术,尤其是在处理复杂数据结构时,能够使输出更加清晰易读。gdb.printing 模块提供了以下功能:

  • 注册 pretty printers

  • 管理 pretty printer 集合

  • 提供查找 pretty printer 的方法

    gdb.printing.register_pretty_printergdb.printing 模块中的一个函数,用于注册一个 pretty printer。当 GDB 在打印某个变量或表达式时,它会调用已注册的 pretty printer 来美化输出。这个函数允许用户为特定类型的数据结构定制输出格式,使得输出更加直观和有用。

    三个参数分别表示:

    • objfile: gdb.ObjfileNone,表示要为其注册 pretty printer 的目标文件。如果是 None,则表示注册的 pretty printer 对所有目标文件有效。
    • pretty_printer: 函数,接受一个 gdb.Value 对象并返回一个 pretty printer 对象或 None。这个函数负责决定是否使用自定义的 pretty printer。
    • replace: 布尔值,默认为 False,表示是否替换现有的 pretty printer。如果为 True,则新注册的 pretty printer 会覆盖先前为相同类型注册的所有 pretty printer。

使用步骤:

  • 使用g++ -g a.cpp -o a将代码编译成可调试的可执行程序。

  • 将上面的t.py和上面编译出来的a放到同一目录。

  • 使用gdb a使用调试状态执行a

  • 在gdb命令行加载t.py,使用source t.py

  • 添加断点b 22,在a.cpp第22行添加断点。

  • 使用r命令运行程序,会在代码22行的位置停下来;使用p s打印变量s的值,就能看到打印格式就是我们t.pyMyPrinter.to_string指定的输出格式。

    在这里插入图片描述

2、在GDB窗口定义python脚本

除了可以上面的在外部定义python脚本,也可以直接在gdb调试窗口中定义函数。

步骤如下:

  • 在gdb 窗口输入python进入python脚本编辑模式

  • 输入python脚本内容,完成后输入end退回到gdb模式下

  • 使用python前缀调用python脚本中的内容

    (gdb) python
    >def my_function(arg):
    >    print(f"Argument received: {arg}")
    >end
    (gdb) python my_function(100)
    Argument received: 100

3、使用python控制gdb流程。

比如我们需要监控某个函数中某个变量的值,比如循环中执行多次,如果我们每次在gdb中手动输入命令,那就太繁琐了,我们可以使用python来做到这些。

比如有个c程序b.c

#include <stdio.h>int sum=0;
void print_message(const int i) {sum+=i;
}int main() {for(int i=0; i<100; i++){print_message(i);}printf("sum = %d\n", sum);return 0;
}

想要打印每次print_message函数执行时,变量i的值,也可以通过python脚本来实现。

下面是python脚本的内容c1.py

import gdbclass PrintVariable(gdb.Breakpoint):def __init__(self, function, variable):super(PrintVariable, self).__init__(function, gdb.BP_BREAKPOINT)self.variable = variabledef stop(self):frame = gdb.selected_frame()if frame:try:value = frame.read_var(self.variable)print(f"Variable '{self.variable}' has value: {value}")except gdb.error as e:print(f"Error reading variable '{self.variable}': {e}")# 禁用分页
gdb.execute("set pagination off")# 要执行的程序   file 是关键字,后文件路径
gdb.execute("file /root/c_debug/b")# 替换这里的'function_name'和'variable_name'为你的函数名(或者代码行号)和变量名
function_name = "5"
variable_name = "i"# 创建一个断点在函数f的开始处
bp = PrintVariable(function_name, variable_name)# 设置断点命令
bp.commands = "print " + variable_name# 运行程序
gdb.execute("run")

脚本的内容都有注释,也就不再说什么了 。

下面看看怎么执行:

  • 将上面的b.c编译成可调试的可执行程序。

gcc -g b.c -o b,我本地是放在/root/c_debug/b,也是上面脚本中的路径

  • 使用gdb命令进入gdb窗口,执行source c1.py,由于我们是在代码第5行设置断点,就可以看到就会自动执行上面我们编译的b,同时每次打印变量i的值。
root@wbo112:~/c_debug# gdb
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.2) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) source c1.py
Breakpoint 1 at 0x1154: file b.c, line 5.
Variable 'i' has value: 0
Variable 'i' has value: 1
Variable 'i' has value: 2
Variable 'i' has value: 3
Variable 'i' has value: 4
Variable 'i' has value: 5
Variable 'i' has value: 6
Variable 'i' has value: 7
Variable 'i' has value: 8
Variable 'i' has value: 9
Variable 'i' has value: 10
Variable 'i' has value: 11
Variable 'i' has value: 12
Variable 'i' has value: 13
Variable 'i' has value: 14
Variable 'i' has value: 15
Variable 'i' has value: 16
Variable 'i' has value: 17
Variable 'i' has value: 18
Variable 'i' has value: 19
Variable 'i' has value: 20
Variable 'i' has value: 21
Variable 'i' has value: 22
Variable 'i' has value: 23
Variable 'i' has value: 24
Variable 'i' has value: 25
Variable 'i' has value: 26
Variable 'i' has value: 27
Variable 'i' has value: 28
Variable 'i' has value: 29
Variable 'i' has value: 30
Variable 'i' has value: 31
Variable 'i' has value: 32
Variable 'i' has value: 33
Variable 'i' has value: 34
Variable 'i' has value: 35
Variable 'i' has value: 36
Variable 'i' has value: 37
Variable 'i' has value: 38
Variable 'i' has value: 39
Variable 'i' has value: 40
Variable 'i' has value: 41
Variable 'i' has value: 42
Variable 'i' has value: 43
Variable 'i' has value: 44
Variable 'i' has value: 45
Variable 'i' has value: 46
Variable 'i' has value: 47
Variable 'i' has value: 48
Variable 'i' has value: 49
Variable 'i' has value: 50
Variable 'i' has value: 51
Variable 'i' has value: 52
Variable 'i' has value: 53
Variable 'i' has value: 54
Variable 'i' has value: 55
Variable 'i' has value: 56
Variable 'i' has value: 57
Variable 'i' has value: 58
Variable 'i' has value: 59
Variable 'i' has value: 60
Variable 'i' has value: 61
Variable 'i' has value: 62
Variable 'i' has value: 63
Variable 'i' has value: 64
Variable 'i' has value: 65
Variable 'i' has value: 66
Variable 'i' has value: 67
Variable 'i' has value: 68
Variable 'i' has value: 69
Variable 'i' has value: 70
Variable 'i' has value: 71
Variable 'i' has value: 72
Variable 'i' has value: 73
Variable 'i' has value: 74
Variable 'i' has value: 75
Variable 'i' has value: 76
Variable 'i' has value: 77
Variable 'i' has value: 78
Variable 'i' has value: 79
Variable 'i' has value: 80
Variable 'i' has value: 81
Variable 'i' has value: 82
Variable 'i' has value: 83
Variable 'i' has value: 84
Variable 'i' has value: 85
Variable 'i' has value: 86
Variable 'i' has value: 87
Variable 'i' has value: 88
Variable 'i' has value: 89
Variable 'i' has value: 90
Variable 'i' has value: 91
Variable 'i' has value: 92
Variable 'i' has value: 93
Variable 'i' has value: 94
Variable 'i' has value: 95
Variable 'i' has value: 96
Variable 'i' has value: 97
Variable 'i' has value: 98
Variable 'i' has value: 99
sum = 4950
[Inferior 1 (process 78220) exited normally]
(gdb) q

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

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

相关文章

51单片机的无线病床呼叫系统【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温湿度传感器模块矩阵按键时钟模块等模块构成。适用于病床呼叫系统、16床位呼叫等相似项目。 可实现基本功能: 1、LCD1602实时显示北京时间、温湿度信息、呼叫床位等信息&#xff1b; 2、DHT11采集病房温湿度信息&…

深度学习的发展历程

深度学习的起源 在机器学习中&#xff0c;我们经常使用两种方式来表示特征&#xff1a;局部表示&#xff08;Local Representation&#xff09;和分布式表示&#xff08;Distributed Representation&#xff09;。以颜色表示为例&#xff0c;见下图&#xff1a; 要学习到一种好…

iPhone手机清理软件:照片清理功能全解析

在数字化生活中&#xff0c;智能手机成为我们记录生活点滴的主要工具&#xff0c;尤其是iPhone&#xff0c;以其卓越的相机功能备受用户青睐。然而&#xff0c;成千上万的照片迅速堆积&#xff0c;不仅占用了大量存储空间&#xff0c;还使得设备运行缓慢。在众多解决方案中&…

【数据分享】《中国城市统计年鉴》(1985-2023)全PDF版本 第一次补档

数据介绍 中国城市&#xff0c;如同一本生动的历史书&#xff0c;承载着经济、社会的快速变迁。《中国城市统计年鉴》记录了城市的发展轨迹&#xff0c;是我们理解城市化进程、洞察城市挑战的重要指南。 这份年鉴的数据庞大而详实&#xff0c;囊括了中国城市发展的多个方面。…

船舶机械设备5G智能工厂物联数字孪生平台,推进制造业数字化转型

船舶机械设备5G智能工厂物联数字孪生平台&#xff0c;推进制造业数字化转型。在当今数字化浪潮推动下&#xff0c;船舶制造业正经历着前所未有的变革。为了应对市场的快速变化&#xff0c;提升生产效率&#xff0c;降低成本&#xff0c;并增强国际竞争力&#xff0c;船舶机械设…

海底生物检测-目标检测数据集(包括VOC格式、YOLO格式)

海底生物检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Kp4Reqt4tq1IafVF33IrnA?pwddxbv 提取码&#xff1a;dxbv 数据集信息介绍&#xff1a; 共有 7383 张图像和一一对应的标注文件 标…

仕考网:事业编考试考什么?

事业编考试科目为&#xff1a; 《职测》《综应》《公基》三选二 事业编有哪些招考形式? ①联考 多省份统一考试&#xff0c;考试时间、考试内容相同&#xff0c;每年两次&#xff0c;上半年5月和下半年10月各一次; ②单招 用人单位单独招聘&#xff0c;考试时间和内容自…

js原型与原型链详解(万文总结,一文搞懂原型链!)

目录 一&#xff0c;原型 1&#xff0c; 对象 2&#xff0c;原型&#xff08;原型对象&#xff09; 二&#xff0c;隐式原型__proto__ 1&#xff0c;__proto__ 2&#xff0c;考你一下 三&#xff0c;原型链 1&#xff0c;Object.prototype 2&#xff0c;链 四&#xff0c;练…

C++第四十七弹---深入理解异常机制:try, catch, throw全面解析

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1.C语言传统的处理错误的方式 2.C异常概念 3. 异常的使用 3.1 异常的抛出和捕获 3.2 异常的重新抛出 3.3 异常安全 3.4 异常规范 4.自定义…

OpenCV结构分析与形状描述符(8)点集凸包计算函数convexHull()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 查找一个点集的凸包。 函数 cv::convexHull 使用斯克拉斯基算法&#xff08;Sklansky’s algorithm&#xff09;来查找一个二维点集的凸包&#…

java基础-IO(1)

1、从计算机的存储说起 电脑电脑&#xff0c;有电才能发挥出“脑”的作用&#xff0c;没电就是破铜烂铁一堆&#xff0c;根据电的特性&#xff08;高低电平&#xff09;巧妙的使用0、1组合&#xff0c;记住了万事万物&#xff0c;才得以让"破铜烂铁"发挥出神奇的功效…

为什么我选择这款PR剪辑软件?打工人亲测好用!

现在大家都爱看短视频和Vlog&#xff0c;要是你会剪辑视频&#xff0c;那可就牛了。不管是出去玩拍的视频&#xff0c;还是工作需要&#xff0c;都能派上用场。我就是个爱旅行、爱剪辑的发烧友&#xff0c;今天给你们推荐三款特别好用的视频剪辑软件&#xff0c;尤其是PR剪辑&a…

C语言 | Leetcode C语言题解之第386题字典序排数

题目&#xff1a; 题解&#xff1a; int* lexicalOrder(int n, int* returnSize){int *ret (int *)malloc(sizeof(int) * n);int number 1;for (int i 0; i < n; i) {ret[i] number;if (number * 10 < n) {number * 10;} else {while (number % 10 9 || number 1 …

解读三国历史中的配角们:探索未被书写的故事 - 《三国配角演义》读后感

在传统的三国叙事中&#xff0c;英雄主角们的事迹往往被无限放大&#xff0c;而那些默默无闻的小人物则被忽视。然而&#xff0c;《三国配角演义》通过挖掘历史细节&#xff0c;赋予这些小角色新的生命。书中用微小的史料合理推断&#xff0c;构建了他们不为人知的精彩故事。 …

C语言进阶版第8课—指针(2)

文章目录 1. 数组名的理解2. 指针访问数组3. 一维数组传参本质4. 冒泡排序5. 二级指针6. 指针数组7. 指针数组模拟二维数组 1. 数组名的理解 sizeof&#xff08;数组名&#xff09;— 这里的数组名代表整个数组&#xff0c;计算的也是整个数组的大小&数组名 — 这里的数组名…

使用 ELK Stack 进行云原生日志记录和监控:AWS 中的开发运营方法

使用 ELK Stack 进行云原生日志记录和监控 欢迎来到雲闪世界。在当今的云原生世界中&#xff0c;日志记录和监控是强大的 DevOps 策略的重要组成部分。监控应用程序性能、跟踪错误和分析日志对于确保无缝操作和主动识别潜在问题至关重要。在本文中&#xff0c;我们将指导您使用…

Vue——Diff算法

目录 什么是Diff算法&#xff1f; 比较方式 1. 同层比较 2. 双端比较 双端比较的步骤&#xff1a; 3. 通过 key 来优化比较 原理分析 1. 虚拟 DOM 和真实 DOM 2. Diff 算法的基本原理 3. 双端比较优化 4. 通过 key 进行优化 5. 具体操作 6. 原理总结 声明&#xf…

AWS SES服务 Golang接入教程(排坑版)

因为刚来看的时候 也迷迷糊糊的 所以 先讲概念 再上代码 一 基础设置 这里需要完成两个最基础的设置任务 1 是验证至少一个收件电子邮箱 2 【很关键】是验证发送域。即身份里的域类型的身份。&#xff08;可以理解为配置你的域名邮箱服务器&#xff08;SMPT&#xff09;为亚马…

Flink问题记录

尚硅谷Flink1.17问题记录 上手pom依赖循环递归WordCountStreamDemo中readTextFile是deprecated&#xff08;强烈反对的&#xff09;Flink本地模式开启WebUI 上手 pom依赖循环递归 pom依赖中&#xff1a; <dependency><groupId>org.apache.flink</groupId>&…

前端开发中遇到的小问题以及解决方案记录2

1、H5中适配屏幕的工具-postcss-px-to-viewport postcss-px-to-viewport。因为设计稿一般给的都是375px宽度的&#xff0c;所以假如一个字体是16px&#xff0c;那么在开发中不能直接写死为16px&#xff0c;因为各个厂商的手机屏幕大小是不同的&#xff0c;所以要根据屏幕大小去…