如何去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 ,和“如果目标环境支持它”,是的。
如果你的程序很短,通常的技巧是,
- 在前一行放置一个新的断点
- 消防
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
GDB的内置logging和重播有严格的限制,例如不支持AVX指令: gdb反向debugging失败,“进程logging不支持地址0xf0d”
rr的上游:
- 目前更可靠
- 还提供了GDB接口与gdbserver协议,使其成为一个很好的替代品
- 许多程序的性能下降
下面的例子展示了它的一些特性,特别是reverse-next
, reverse-step
和reverse-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;