zoukankan      html  css  js  c++  java
  • GDB 反向调试(Reverse Debugging)

    这个挺有意思

    http://blog.csdn.net/CherylNatsu/article/details/6436570

    使用调试器时最常用的功能就是step, next, continue,这几个调试命令都是往下执行的, 但是很多时候会有这种需求:你在调试的过程中多跳过了几步而错过中间过程,这时候不得不重头调试一遍,非常麻烦。而GDB7.0版本开始支持反向调试功能,也就是允许你倒退着运行程序,或者说撤销程序执行的步骤从而会到以前的状态。

     

    直观地来看,加入你正在使用GDB7.0以上版本的调试器并且运行在支持反向调试的平台,你就可以用以下几条命令来调试程序:

    reverse-continue

    反向运行程序知道遇到一个能使程序中断的事件(比如断点,观察点,异常)。

     

    reverse-step

    反向运行程序到上一次被执行的源代码行。

     

    reverse-stepi

    反向运行程序到上一条机器指令

     

    reverse-next

    反向运行到上一次被执行的源代码行,但是不进入函数。

     

    reverse-nexti

    反向运行到上一条机器指令,除非这条指令用来返回一个函数调用、整个函数将会被反向执行。

     

    reverse-finish

    反向运行程序回到调用当前函数的地方。

     

    set exec-direction [forward | reverse]

    设置程序运行方向,可以用平常的命令stepcontinue等来执行反向的调试命令。

     

    上面的反向运行也可以理解为撤销后面运行的语句所产生的效果,回到以前的状态。

     

    好的,接下来我们来试试看如何反向调试。

    首先确认自己的平台支持进程记录回放(Process Record and Replay),当在调试器启用进程记录回放功能时,调试器会记录下子进程,也就是被调试进程的每一步的运行状态与上一步运行状态的差异,需要撤销的时候就可以很方便回到上一步。

    假设我们有以下C程序:

    [cpp] view plaincopyprint?

    1.  int main(int argc, const char *argv[]) 

    2. 

    3.    int a = 0; 

    4.    a = 1; 

    5.    a = 2; 

    6.    return 0; 

    7. 

     

     

    将它编译并加上调试符号:

    [python] view plaincopyprint?

    1.  $ gcc -Wall -g a.c 

     

    开始调试:

    [python] view plaincopyprint?

    1.  $ gdb a.out 

     

    查看一下源代码:

    [python] view plaincopyprint?

    1.  (gdb) l 

    2.  1   int main(int argc, const char *argv[]) 

    3.  2   { 

    4.  3     int a = 0

    5.  4     a = 1

    6.  5     a = 2

    7.  6     return 0

    8.  7   } 

     

    接下来设置一个断点在第三行:

    [python] view plaincopyprint?

    1.  (gdb) b 3 

    2.  Breakpoint 1 at 0x804839a: file a.c, line 3. 

     

    运行,程序会在第三行的地方停下来:

    [python] view plaincopyprint?

    1.  (gdb) r 

    2.  Starting program: /home/cheryl/a.out  

    3.  Breakpoint 1, main (argc=1, argv=0xbffff3e4) at a.c:3 

    4.  3     int a = 0

    给变量a设置监视点方便我们观察:

    [python] view plaincopyprint?

    1.  (gdb) watch a 

    2.  Hardware watchpoint 2: a 

     

    启动进程记录回放:

    [python] view plaincopyprint?

    1.  (gdb) record 

     

    现在每运行一步调试器都会记录下变化,以便回溯。我们连续执行3条语句。

    [python] view plaincopyprint?

    1.  (gdb) n 

    2.  4     a = 1

    3.  (gdb)  

    4.  Hardware watchpoint 2: a 

    5.  Old value = 0 

    6.  New value = 1 

    7.  main (argc=1, argv=0xbffff3e4) at a.c:5 

    8.  5     a = 2

    9.  (gdb)  

    10. Hardware watchpoint 2: a 

    11. Old value = 1 

    12. New value = 2 

    13. main (argc=1, argv=0xbffff3e4) at a.c:6 

    14. 6     return 0

     

    可以看到,a的值先是从0变为了1,然后变为2,如果想让程序倒退回到以前的状态怎么办?可以用reverse-next命令:

    [python] view plaincopyprint?

    1.  (gdb) reverse-next 

    2.  Hardware watchpoint 2: a 

    3.  Old value = 2 

    4.  New value = 1 

    5.  main (argc=1, argv=0xbffff3e4) at a.c:5 

    6.  5     a = 2

    7.  (gdb)  

    8.  Hardware watchpoint 2: a 

    9.  Old value = 1 

    10. New value = 0 

    11. main (argc=1, argv=0xbffff3e4) at a.c:4 

    12. 4     a = 1

    13. (gdb)  

    14. No more reverse-execution history. 

    15. main (argc=1, argv=0xbffff3e4) at a.c:3 

    16. 3     int a = 0

    17. (gdb)  

    这样程序就倒退到了我们启动进程记录回放的地方,a的值经过两步回到了最初的状态。

    若需要关闭进程记录回放,可以使用record stop

     

     

    [python] view plaincopyprint?

    1.  (gdb) record stop 

    2.  Process record is stoped and all execution log is deleted. 

     

     

    参考:《Reverse Debugging with GDB --- http://sourceware.org/gdb/wiki/ReverseDebug

     

  • 相关阅读:
    C# 互操作性入门系列(三):平台调用中的数据封送处理
    C# 互操作性入门系列(二):使用平台调用调用Win32 函数
    C# 互操作性入门系列(一):C#中互操作性介绍
    远程桌面打开 提示无法打开连接文件 default.rdp
    C# for循环 创建model 在循环里和循环外引发的问题
    C# 使用ListView.CheckedItems慢的问题
    获取数据库信息
    获取文件路径
    String数据转Matrix矩阵
    文件IO(存取.txt文件)
  • 原文地址:https://www.cnblogs.com/xuxm2007/p/3244709.html
Copyright © 2011-2022 走看看