gdb查看空指针 linux_5 个鲜为人知 GNU 调试器(GDB)技巧

695b1fe287ab2d716487bacef20d29e0.png

了解如何使用 gdb 的一些鲜为人知的功能来检查和修复代码。-- Tim Waugh(作者)

GNU 调试器 (gdb)是一种宝贵的工具,可用于在开发程序时检查正在运行的进程并解决问题。

你可以在特定位置(按函数名称、行号等)设置断点、启用和禁用这些断点、显示和更改变量值,并执行所有调试器希望执行的所有标准操作。但是它还有许多其它你可能没有尝试过的功能。这里有五个你可以尝试一下。

条件断点

设置断点是学习使用 GNU 调试器的第一步。程序在达到断点时停止,你可以运行 gdb 的命令对其进行检查或更改变量,然后再允许该程序继续运行。

例如,你可能知道一个经常调用的函数有时会崩溃,但仅当它获得某个参数值时才会崩溃。你可以在该函数的开始处设置一个断点并运行程序。每次碰到该断点时都会显示函数参数,并且如果未提供触发崩溃的参数值,则可以继续操作,直到再次调用该函数为止。当这个惹了麻烦的参数触发崩溃时,你可以单步执行代码以查看问题所在。

(gdb) break sometimes_crashesBreakpoint 1 at 0x40110e: file prog.c, line 5.(gdb) run[...]Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:55 fprintf(stderr,(gdb) continueBreakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:55 fprintf(stderr,(gdb) continue

为了使此方法更具可重复性,你可以在你感兴趣的特定调用之前计算该函数被调用的次数,并在该断点处设置一个计数器(例如,continue 30 以使其在接下来的 29 次到达该断点时忽略它)。

但是断点真正强大的地方在于它们在运行时评估表达式的能力,这使你可以自动化这种测试。

break [LOCATION] if CONDITION(gdb) break sometimes_crashes if !fBreakpoint 1 at 0x401132: file prog.c, line 5.(gdb) run[...]Breakpoint 1, sometimes_crashes (f=0x0) at prog.c:55 fprintf(stderr,(gdb)

条件断点使你不必让 gdb 每次调用该函数时都去问你要做什么,而是让条件断点仅在特定表达式的值为 true 时才使 gdb 停止在该位置。如果执行到达条件断点的位置,但表达式的计算结果为 false,调试器会自动使程序继续运行,而无需询问用户该怎么做。

断点命令

GNU 调试器中断点的一个甚至更复杂的功能是能够编写对到达断点的响应的脚本。断点命令使你可以编写一系列 GNU 调试器命令,以在到达该断点时运行。

我们可以使用它来规避在 sometimes_crashes 函数中我们已知的错误,并在它提供空指针时使其无害地从该函数返回。

我们可以使用 silent 作为第一行,以更好地控制输出。否则,每次命中断点时,即使在运行断点命令之前,也会显示堆栈帧。

(gdb) break sometimes_crashesBreakpoint 1 at 0x401132: file prog.c, line 5.(gdb) commands 1Type commands for breakpoint(s) 1, one per line.End with a line saying just "end".>silent>if !f >frame >printf "Skipping call" >return 0 >continue >end>printf "Continuing">continue>end(gdb) runStarting program: /home/twaugh/Documents/GDB/progwarning: Loadable section ".note.gnu.property" outside of ELF segmentsContinuingContinuingContinuing#0 sometimes_crashes (f=0x0) at prog.c:55 fprintf(stderr,Skipping call[Inferior 1 (process 9373) exited normally](gdb)

转储二进制内存

GNU 调试器内置支持使用 x 命令以各种格式检查内存,包括八进制、十六进制等。但是我喜欢并排看到两种格式:左侧为十六进制字节,右侧为相同字节表示的 ASCII 字符。

当我想逐字节查看文件的内容时,经常使用 hexdump -C(hexdump 来自 util-linux 软件包)。这是 gdb 的 x 命令显示的十六进制字节:

(gdb) x/33xb mydata0x404040  : 0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x010x404048  : 0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x720x404050 : 0x69 0x62 0x75 0x74 0x65 0x73 0x2d 0x630x404058 : 0x68 0x61 0x72 0x73 0x65 0x75 0x00 0x050x404060 : 0x00

如果你想让 gdb 像 hexdump 一样显示内存怎么办?这是可以的,实际上,你可以将这种方法用于你喜欢的任何格式。

通过使用 dump 命令以将字节存储在文件中,结合 shell 命令以在文件上运行 hexdump 以及define 命令,我们可以创建自己的新的 hexdump 命令来使用 hexdump 显示内存内容。

(gdb) define hexdumpType commands for definition of "hexdump".End with a line saying just "end".>dump binary memory /tmp/dump.bin $arg0 $arg0+$arg1>shell hexdump -C /tmp/dump.bin>end

这些命令甚至可以放在 ~/.gdbinit 文件中,以永久定义 hexdump 命令。以下是它运行的例子:

(gdb) hexdump mydata sizeof(mydata)00000000 02 01 00 02 00 00 00 01 01 47 00 12 61 74 74 72 |.........G..attr|00000010 69 62 75 74 65 73 2d 63 68 61 72 73 65 75 00 05 |ibutes-charseu..|00000020 00 |.|00000021

行内反汇编

有时你想更多地了解导致崩溃的原因,而源代码还不够。你想查看在 CPU 指令级别发生了什么。

disassemble 命令可让你查看实现函数的 CPU 指令。但是有时输出可能很难跟踪。通常,我想查看与该函数源代码的特定部分相对应的指令。为此,请使用 /s 修饰符在反汇编中包括源代码行。

(gdb) disassemble/s mainDump of assembler code for function main:prog.c:11 { 0x0000000000401158 : push %rbp 0x0000000000401159 : mov %rsp,%rbp 0x000000000040115c : sub $0x10,%rsp12 int n = 0; 0x0000000000401160 : movl $0x0,-0x4(%rbp)13 sometimes_crashes(&n); 0x0000000000401167 : lea -0x4(%rbp),%rax 0x000000000040116b : mov %rax,%rdi 0x000000000040116e : callq 0x401126 [...snipped...]

这里,用 info 寄存器查看所有 CPU 寄存器的当前值,以及用如 stepi 这样命令一次执行一条指令,可以使你对程序有了更详细的了解。

反向调试

有时,你希望自己可以逆转时间。想象一下,你已经达到了变量的监视点。监视点像是一个断点,但不是在程序中的某个位置设置,而是在表达式上设置(使用 watch 命令)。每当表达式的值更改时,执行就会停止,并且调试器将获得控制权。

想象一下你已经达到了这个监视点,并且由该变量使用的内存已更改了值。事实证明,这可能是由更早发生的事情引起的。例如,内存已释放,现在正在重新使用。但是它是何时何地被释放的呢?

GNU 调试器甚至可以解决此问题,因为你可以反向运行程序!

它通过在每个步骤中仔细记录程序的状态来实现此目的,以便可以恢复以前记录的状态,从而产生时间倒流的错觉。

要启用此状态记录,请使用 target record-full 命令。然后,你可以使用一些听起来不太可行的命令,例如:

  • reverse-step,倒退到上一个源代码行
  • *reverse-next,它倒退到上一个源代码行,向后跳过函数调用
  • reverse-finish,倒退到当前函数即将被调用的时刻
  • reverse-continue,它返回到程序中的先前状态,该状态将(现在)触发断点(或其他导致断点停止的状态)

这是运行中的反向调试的示例:

(gdb) b mainBreakpoint 1 at 0x401160: file prog.c, line 12.(gdb) rStarting program: /home/twaugh/Documents/GDB/prog[...]Breakpoint 1, main () at prog.c:1212 int n = 0;(gdb) target record-full(gdb) cContinuing.Program received signal SIGSEGV, Segmentation fault.0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:77 return *f;(gdb) reverse-finishRun back to call of #0 0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:70x0000000000401190 in main () at prog.c:1616 sometimes_crashes(0);

这些只是 GNU 调试器可以做的一些有用的事情。还有更多有待发现。你最喜欢 gdb 的哪个隐藏的、鲜为人知或令人吃惊的功能?请在评论中分享。


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

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

相关文章

盘点三个JavaScript案例——实现限时秒杀、定时跳转、改变盒子大小

前言 今天来给大家盘点三个JavaScript案例,分别是实现限时秒杀、定时跳转、改变盒子大小案例,一起来看看吧! 一、实现限时秒杀案例 1.在淘宝网中,商家为了促销经常搞一些活动,例如限时秒杀是常见的一种活动&#xff0c…

华为的鸿蒙系统是海思_死心了!华为鸿蒙系统首款终端确认,不是手机

欢迎点击上面ZAKER关注5 月底谷歌宣布断供华为。随后,华为 " 秘密 " 研发 7 年的自主产权操作系统鸿蒙被公之于众。随着关于鸿蒙系统的消息越来越多,如鸿蒙系统 2012 年便开始规划、鸿蒙系统在多个国家注册商标等。人们除了佩服华为的未雨绸缪…

网络知识:宽带下载网速是30MB/s,经过路由器后仅10MB/s,看完你就懂了

问题:宽带下载网速本是30MB/s,经过路由器后速度仅10MB/s,这是为什么? 宽带下载测速可以到30MB/s,说明外线和光猫还有电脑是没有问题的。目前家庭的组网基本都是光纤入户了,你的测速瓶颈既然不在光猫&#…

手机投屏到电脑的5种方式,你学到了吗

今天小编给大家分享5种手机投屏到电脑的方式,希望对大家能有帮助! 方法一: 1、我们可以通过Win10自带的投影功能,将我们的手机和电脑连接同一个无线网络。 2、接下来我们就在电脑开始菜单栏里找到设置选项打开。 3、我们进入之后找…

poj 3728 Catch That Cow ([kuangbin带你飞]专题一 简单搜索)

题目大意:题目链接 就是给你N,K,每次有三种惭怍1,-1,*2,,问多少次操作能到K 解题思路,搜索直接算,。,,,哎,啥时候这种垃圾…

不拦截指定路径_控制层访问拦截

在控制层进行访问拦截也是我们在项目中常会遇到的需求,例如:项目中要求系统登录操作有时间限制--12306购票时间的限制等.对于这类需求我们一般有几种选择:过滤器FilterAOPSpringMVC拦截器...本文我们主要说一下SpringMVC拦截器的实现原理Spring MVC的拦截器是基于回调机制,可以…

电脑知识:Win10系统把系统盘的软件移到D盘的简单方法

❤️作者主页:IT技术分享社区 ❤️作者简介:大家好,我是IT技术分享社区的博主,从事C#、Java开发九年,对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉: 数据库领域优质创作者🏆&#x…

RuntimeException和Exception区别

Exception :受检查的异常,这种异常是强制我们catch或throw的异常。你遇到这种异常必须进行catch或throw,如果不处理,编译器会报错。比如:IOException。 RuntimeException:运行时异常,这种异常我…

语言高精度算法阶乘_JavaScript中的算法(附10道面试常见算法题解决方法和思路)...

https://juejin.im/post/6844903811505455118Introduction面试过程通常从最初的电话面试开始,然后是现场面试,检查编程技能和文化契合度。几乎毫无例外,最终的决定因素是还是编码能力。通常上,不仅仅要求能得到正确的答案&#xf…

硬件:LCD和LED相关知识介绍

目录 一、LCD简介 二、LED简介 三、LED和 LCD的区别 四、LED和 LCD显示器的区别 一、LCD简介 LCD是液晶显示屏(Liquid Crystal)Display的全称,主要有TFT、UFB、TFD、STN等几种类型的液晶显示屏无法定位程序输入点于动态链接库上。 笔记本液晶屏最常用的是TFT。 TFT…

Swagger+AutoRest 生成web api客户端(.Net)

简介 对于.net来说,用web api来构建服务是一个不错的选择,都是http请求,调用简单,但是如果真的要在程序中调用,则还有些工作要做,比如我们需要手写httpClient调用,并映射Model, 如果…

电脑技巧:六款Mac电脑上值得推荐的看图软件

❤️作者主页:IT技术分享社区 ❤️作者简介:大家好,我是IT技术分享社区的博主,从事C#、Java开发九年,对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉: 数据库领域优质创作者🏆&#x…

Git的smart Checkout\force checkout\Don‘t Checkout的区别

我们在develop分支修改了代码,但是没有commit,所以在切换到其他分支的时候回弹出这个窗口. smart checkout就会把冲突的这部分内容带到目的分支(如果你没有点进窗口的那些文件处理冲突的话) force checkout就不会把冲突的这部分内容带到目的分支 dont ch…

软件:推荐5款职场人必备的效率神器APP

目录 1.番茄TO DO(支持Android、ios端下载) 2.块时间 (支持Android、ios端下载) 3.滴答清单(支持Android、ios端、PC端下载) 4.Eventai(仅ios端下载) 5.Ihour(支持Androi…

Windows常用必备软件整理,太全了,值得收藏

目录 1、Office系列 2、杀毒软件 3、视频播放和视频处理 4、音乐播放 5、压缩解压 6、输入法 7、PDF阅读软件 8、文件加密 9、网盘 10、社交聊天 11、日常办公软件 ‍12、图片/照片处理‍ 13、系统自带的工具 Windows常用必备软件整理,太全了,值得收藏&…

数据库:SQLServer数据库备份方式介绍

今天小编给大家梳理一下数据库备份的相关知识,希望对大家能有所帮助!1、完整备份完整备份相当于针对整个数据库备份,包含数据库的全部内容。数据库完整备份可以将数据库的所有内容备份为一个.Bak文件。后续可以通过该备份文件在本机或者拷贝到…

注入双括号报错注入_SQL手动注入:sqlilabs(less110)

种一棵树最好的时间是10年前,其次是现在。忘了是谁前言说实话,由于前段时间学 python ,对于 OWASP TOP10 漏洞的学习都有所落下,虽然现在也在慢慢复习当中,但是今晚谈及的 SQL 注入漏洞手动注入和自动化(sqlmap)注入的…

markdown学习/mou

markdown编辑器mou markdown编辑器的使用很简单,mac平台选择课 MOU 这款比较轻的客户端。 使用也很方便,打开软件,->helo->mou help 就有各种示例,照葫芦画瓢。 有些关键字需要转义,使用的时候要注意,比如插入一…