1、引言
在《GDB高级技巧:边Debug边修复BUG,无需修改代码,无需重新编译》一文中,介绍了使用GDB breakpoint command lists的功能,可以在不修改源码、不重新编译的前提下,修复掉被调试程序中的BUG,从而避免反复修改代码和编译构建的过程,大大提高程序调试的效率。
文中提到了解决一个问题的几种不同的思路,但限于篇幅,只重点讲解了其中的一种。有童鞋希望能够把其它几种也讲解一下,于是便有了此文。
本文会介绍5种不同的方法,解决同一个Bug!
2、本文要解决的问题
如下示例程序中,存在两个BUG:
正常执行时,该程序将出现异常,如下图所示:
本文将介绍5种方法,在不修改源码、不重新编译的前提下,借助GDB解决掉示例程序中的两个BUG,使其能够正确执行,并得到预期结果。
其最终执行结果如下图所示:
先介绍一些必需的背景知识。
3、背景知识介绍
3.1、x64 CPU函数参数传递
对于C语言,不同的CPU/编译器,其参数传递方式也不尽相同。
我的测试环境是x64CPU,所以仅介绍x64 CPU的函数参数传递规则。
用GCC编译出来的程序,在x64 CPU上,如果程序中没有特殊指定,会优先使用寄存器传递参数,当寄存器不够用的时候,用栈传递。
默认情况下,前6个参数,从左到右,依次用寄存器RDI(EDI)、RSI(ESI)、RDX(EDX)、RCX(ECX)、R8、R9传递,从第七个函数开始,使用栈传递。
注:RDI、RSI、RDX、RCX是64位寄存器,EDI、ESI、EDX、ECX分别是它们低32位寄存器的表示。
如下图简单示例:
test()共有8个参数,我们在GDB中把main()函数反汇编一下,看下是如何传递参数的:
通过反汇编,可以看到,前面6个参数是使用寄存器传递的,而第7、8两个参数是通过栈传递的。
3.2、GDB断点预置命令
注:已阅读过之前那篇文章的童鞋,可以直接跳过3.1小节。当然, 也可以再回顾一下,加深印象