Debugging 如何转到GDB中的上一行?
在gdb中是否可以转到当前执行行之前的行。 e、 g: 我目前在b行,可以检查那里的Debugging 如何转到GDB中的上一行?,debugging,gdb,Debugging,Gdb,在gdb中是否可以转到当前执行行之前的行。 e、 g: 我目前在b行,可以检查那里的arr值,但我想回到a行,检查arr的内容 我认为这可能是不可能的,因为调试器可以慢动作运行代码,但不能使其向后执行。 还有更多的见解。根据,以及“如果目标环境支持它”,是的。如果您的程序很短,通常的技巧是 在前一行放置一个新断点 激发r以重新启动调试 GDB就是为了这样做的 每个人都希望有这样一个无所不知的调试器:,但它们(取决于语言/机器)很难制作,而且有很多簿记工作要做 目前,在真正的硬件上,而不是在虚
arr
值,但我想回到a行,检查arr
的内容
我认为这可能是不可能的,因为调试器可以慢动作运行代码,但不能使其向后执行。还有更多的见解。根据,以及“如果目标环境支持它”,是的。如果您的程序很短,通常的技巧是
- 激发
以重新启动调试r
GDB就是为了这样做的 每个人都希望有这样一个无所不知的调试器:,但它们(取决于语言/机器)很难制作,而且有很多簿记工作要做
目前,在真正的硬件上,而不是在虚拟机上,这几乎是不可能做到的。简短回答:不 有关解决方法,请阅读下面的内容 虽然在b行不可能确定a行的值,但可以通过只命中一个断点来记录a和b以及其他位置的arr值
- 使用“display”命令(display variable_name,其中variable_name将替换为arr、*arr、**arr,具体取决于您要查找的内容),以便在命中任何断点时,变量_name的内容将转储到屏幕上。请注意,当variabe_名称在范围内时,可以将其添加到显示列表中,这样可能需要等待第一个断点李>
- 在您感兴趣的代码的不同位置创建断点,以便记录变量\u name的值。其中一个断点位于a行
- 对于每个断点,使用命令(命令断点编号)并指示断点不要停止程序的执行。您需要使用的命令是continue,后跟end。见下面的例子
- 在b行上放置一个断点
根据具体情况,您还可以转储(并显示)大量有用的信息。例如,如果在循环中调用上述函数10000次,您可能还希望转储循环计数器(例如i)。这真的取决于你想要实现什么。是的!使用新版本7.0 gdb,您可以做到这一点 该命令将是“
reverse step
”或“reverse next
”
您可以从ftp.gnu.org:/pub/gnu/gdb获得gdb-7.0
如果遇到错误:目标子级不支持此命令。
然后尝试在执行开始时,在启动run
后添加目标记录
编辑:由于GDB 7.6目标记录
已被弃用,请改用目标记录完整
。是的,现在使用真正的硬件(即不仅仅是虚拟机)是可能的,而且简单明了。
GDB-7.0支持在本机linux x86机器上使用反向步骤和反向继续等命令进行反向调试
这里有一个教程:如果您的arr设置代码刚好在“行a”(一个非常常见的场景)上方,您可以这样做:
tbreak myfilename.c:123
(第123行是arr设置代码的开始),然后
“tbreak”阻止gdb在跳转后继续(恢复)程序
然后,您可以单步执行设置代码,或者只在“行a”处设置一个断点,然后继续执行而不是gdb,但您可以使用名为qira的调试器轻松地返回历史。您可以使用向上和向下箭头来回移动,它还会突出显示已更改的寄存器
mozilla rr
GDB的内置记录和重播具有严重的限制,例如不支持AVX指令:
rr的正面:
- 现在要可靠得多。我已经对几个复杂的软件进行了较长时间的测试
- 还提供了带有gdbserver协议的GDB接口,使其成为一个很好的替代品
- 对于大多数程序来说,性能下降很小,如果不进行测量,我自己也没有注意到
- 生成的记录道在磁盘上很小,因为只记录了很少的非确定性事件,到目前为止,我从来不用担心它们的大小
下面的示例展示了它的一些功能,特别是reverse next
、reverse step
和reverse continue
命令
在Ubuntu 18.04上安装:
sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
sudo cpupower frequency-set -g performance
# Overcome "rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3."
echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
现在您被留在GDB会话中,您可以正确地反向调试:
(rr) break main
Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
(rr) continue
Continuing.
Breakpoint 1, main () at a.c: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 a.c:7
7 i = 0;
(rr) reverse-step
main () at a.c: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 a.c:16
16 i = 0;
rr通过首先以记录每个非确定性事件(如线程切换)发生的情况的方式运行程序来实现这一点
然后在第二次重播运行期间,它使用该跟踪文件(其小得惊人)准确地重构在原始非确定性运行上发生的情况,但以确定性的方式,向前或向后
rr最初是由Mozilla开发的,用于帮助他们重现第二天夜间测试中出现的计时错误。但是,对于只有在执行数小时内发生的错误,反向调试方面也很重要,因为您经常希望后退一步,检查前一种状态导致了后一种故障
我认为rr最严重的限制是:
- 您必须从中进行第二次重播
sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
sudo cpupower frequency-set -g performance
# Overcome "rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3."
echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
#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
(rr) break main
Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
(rr) continue
Continuing.
Breakpoint 1, main () at a.c: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 a.c:7
7 i = 0;
(rr) reverse-step
main () at a.c: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 a.c:16
16 i = 0;