如何去GDB的上一行?

是否有可能在gdb去当前正在执行的行之前的行。 例如:

void my_fun( somePtrType** arr,int start,int end) { // arr is an array of pointers to somePtrType //line a ... some assignments swap(&arr[ind1] , &arr[ind2] ) ; //line b (current line ) } 

我目前在线b,可以检查那里的arr值,但是我想回到a线,并且在那个时候检查arr的内容。

我认为这可能是不可能的,因为debugging器可以慢动作运行代码,但不能使其向后执行。
更多的见解..

是! 使用新版本的7.0 gdb,你可以做到这一点!

该命令将是“ reverse-step ”或“ reverse-next ”。

你可以从ftp.gnu.org:/pub/gnu/gdb获得gdb-7.0

如果遇到错误: Target child does not support this command. 然后尝试在开始run之后在执行开始时添加target record

编辑:由于GDB 7.6 target record已过时,请使用target record-full

是的,现在使用真正的硬件(即不仅仅是一个虚拟机)是可能的,也是直截了当的。 GDB-7.0支持在本机Linux x86机器上使用反向步骤和反向继续等命令进行反向debugging。

这里有一个教程: http : //www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial

简短的回答 :不。

解决方法请参阅下文。

虽然在b行不可能确定a行的值,但是可能只logging一个断点,loggingar和a,b和其他位置的值。

  • 使用“display”命令( 显示variable_name ,其中variable_name将被replace为arr,* arr,** arr,这取决于您正在查找的内容),以便当遇到任何断点时,variables名称的内容将被转储屏幕。 请注意,当variables名在范围内时,您可以添加到显示列表,以便可能需要等待第一个断点。
  • 在有兴趣loggingvariable_name值的代码的各个位置创build断点。 一个这样的断点将在第一行。
  • 对于每个断点,使用命令( 命令breakpoint_number )并指示您的断点不停止程序的执行。 您需要使用的命令继续后面的结尾 。 看下面的例子。

(gdb)命令1

input断点1时的命令,每行一个。 最后用一句话说“结束”。

继续

结束

  • 在b行上放置一个断点。

现在,当所有其他logging断点被击中时,arr的值将被转储到屏幕上,但是断点不会等待用户交互,并且将自动继续。 当你在b行打断点时,你可以看到在gdb本身中logging的arr的过去值。

根据情况,您也可以转储(并显示)大量有用的信息。 例如,如果上述函数在循环中被调用10000次,您也可能需要转储循环计数器(比如i)。 这真的取决于你想要达到的目标。

根据http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC51 ,和“如果目标环境支持它”,是的。

如果你的程序很短,通常的技巧是,

  1. 在前一行放置一个新的断点
    • 消防r重新启动debugging

GDB是这样做的!

不是gdb,但是你可以使用一个叫做qira的debugging器轻松地回到历史logging。 您可以使用向上和向下箭头前后移动,还可以突出显示哪些寄存器已更改。

在这里输入图像说明

每个人都希望有这样一个全能的debugging器: http : //www.lambdacs.com/debugger/ ,但是它们(取决于语言/机器)难以制作,并且需要大量的簿记工作。

目前在真正的硬件上,而不是在虚拟机上,这几乎是不可能的。

如果您的arr设置代码刚好位于“line a”(一个非常常见的场景)之上,您可以这样做:

tbreak myfilename.c:123 (第123行是arr的设置代码的开始)

 jump 123 

“tbreak”阻止gdb在跳转后继续(恢复)程序。

那么你可以通过设置代码或者只是在“line a”处设置一个断点并继续

mozilla rr

https://github.com/mozilla/rr

GDB的内置logging和重播有严格的限制,例如不支持AVX指令: gdb反向debugging失败,“进程logging不支持地址0xf0d”

rr的上游:

  • 目前更可靠
  • 还提供了GDB接口与gdbserver协议,使其成为一个很好的替代品
  • 许多程序的性能下降

下面的例子展示了它的一些特性,特别是reverse-nextreverse-stepreverse-continue命令。

安装Ubuntu 16.04:

 sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic sudo cpupower frequency-set -g performance 

但是也要考虑从源代码编译来获取最新的更新,这并不难。

testing程序:

 #include <stdio.h> #include <stdlib.h> #include <time.h> int f() { int i; i = 0; i = 1; i = 2; return i; } int main(void) { int i; i = 0; i = 1; i = 2; /* Local call. */ f(); printf("i = %d\n", i); /* Is randomness completely removed? * Recently fixed: https://github.com/mozilla/rr/issues/2088 */ i = time(NULL); printf("time(NULL) = %d\n", i); return EXIT_SUCCESS; } 

编译并运行:

 gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c rr record ./reverse.out rr replay 

现在你被留在GDB会话中了,你可以正确地反向debugging:

 (rr) break main Breakpoint 1 at 0x55da250e96b0: file ac, line 16. (rr) continue Continuing. Breakpoint 1, main () at ac:16 16 i = 0; (rr) next 17 i = 1; (rr) print i $1 = 0 (rr) next 18 i = 2; (rr) print i $2 = 1 (rr) reverse-next 17 i = 1; (rr) print i $3 = 0 (rr) next 18 i = 2; (rr) print i $4 = 1 (rr) next 21 f(); (rr) step f () at ac:7 7 i = 0; (rr) reverse-step main () at ac:21 21 f(); (rr) next 23 printf("i = %d\n", i); (rr) next i = 2 27 i = time(NULL); (rr) reverse-next 23 printf("i = %d\n", i); (rr) next i = 2 27 i = time(NULL); (rr) next 28 printf("time(NULL) = %d\n", i); (rr) print i $5 = 1509245372 (rr) reverse-next 27 i = time(NULL); (rr) next 28 printf("time(NULL) = %d\n", i); (rr) print i $6 = 1509245372 (rr) reverse-continue Continuing. Breakpoint 1, main () at ac:16 16 i = 0;