mozilla rr
https://github.com/mozilla/rr
GDB内置的记录与重放功能有严重的限制,例如不支持AVX指令:gdb reverse debugging fails with "Process record does not support instruction 0xf0d at address"
rr的优点:
- 当前更加可靠。我测试过多次运行较长复杂软件。
- 还提供了GDB接口和gdbserver协议,是一个很好的替代品。
- 对大多数程序的性能影响很小,没有进行测量也没有注意到明显的下降。
- 生成的跟踪文件因为只记录了极少数的非确定性事件,所以在磁盘上很小,迄今为止我从未担心它们的大小。
以下示例展示了一些其特性,尤其是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
echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
测试程序:
reverse.c
#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;
f();
printf("i = %d\n", i);
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 会话中,可以正确地进行反向调试:
(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 通过首先以记录每个非确定性事件(如线程切换)上发生情况的方式运行程序来实现此目标。
然后,在第二次重放运行期间,它使用那个跟踪文件(出乎意料地小),以确定性的方式前进或后退重建原始非确定性运行中发生的一切。
最初,Mozilla 开发了 rr 来帮助他们重现在夜间测试之后出现的定时错误。但是,反向调试方面对于您在执行中仅发生数小时的错误非常重要,因为您通常希望后退以检查导致后来失败的先前状态。
我认为 rr 最严重的限制是:
UndoDB 是 rr 的商业替代品:https://undo.io 两者都是基于跟踪/重放的,但我不确定它们在功能和性能方面如何比较。
start
... 然后 输入target record-full
。快捷方式是rn
。 - user2023370record
和target record-full
是一样的吗?在 https://sourceware.org/gdb/current/onlinedocs/gdb/Reverse-Execution.html#Reverse-Execution 中,它是提到的第一个命令,对我来说似乎可以工作。 - user2023370start
和target record-full
后,rn
会产生以下错误:进程记录和重放目标不支持系统调用编号292 进程记录:无法记录执行日志。
我猜反向调试也需要一些编译器标志吧? - SamuelMyself