Chromium Chronicle #13:使用 RR 进行时间旅行调试

第 13 集:作者:Christian Biesinger,位于威斯康星州麦迪逊(2020 年 3 月)
上一集

您是否发现自己在调试程序中反复运行同一测试,并试图弄清楚代码是如何处于错误状态的?我们为您准备了一款工具! 它易于安装和设置,会记录执行轨迹,并为 gdb 提供神奇的新功能。退步、反向运行,查看变量在什么位置更改了其值,或上次对对象调用函数的时间(使用条件断点)。

在 Linux 上,您可以使用 rr。使用 sudo apt-get install rr 或访问 https://rr-project.org/ 进行安装。

此操作并非官方支持,但非常有用。rr 的工作原理是,您先录制轨迹,然后重放轨迹

rr record .../content_shell --no-sandbox  --disable-hang-monitor --single-process
# record the trace. --single-process is optional, see below. The other flags are required.
rr replay # This will replay the last trace
(gdb)       # rr uses GDB to let you replay traces

方便的是,每次重放同一轨迹时,时间和指针地址都会保持不变。您可以使用 rr pack 将跟踪记录设为可移植,以便您可以将它们复制到另一台机器并在另一台机器上重放,或者在重新编译后重放。使用 continue 运行程序。您可以使用所有常规 GDB 命令 -bnextwatch 等。但是,您也可以使用 reverse-next (rn)、reverse-cont (rc)、reverse-step (rs) 和 reverse-fin 等。

这些断点仍会遵循您设置的任何断点。例如:

(gdb) c  # Execute to the end
(gdb) break blink::LayoutFlexibleBox::UpdateLayout
(gdb) rc # Run back to the last layout call
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
    this=0x121672224010)
(gdb) # Inspect anything you want here. To find the previous Layout call on this object:
(gdb) cond 1 this == 0x121672224010
(gdb) rc
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
    this=0x121672224010)
(gdb) watch -l style_.ptr_ # Or find the last time the style_ was changed
(gdb) rc
Thread 5 hit Hardware watchpoint 2: -location style_.ptr_

Old value = (const blink::ComputedStyle *) 0x1631ad3dbb0
New value = (const blink::ComputedStyle *) 0x0
0x00007f68cabcf78e in std::__Cr::swap<blink::ComputedStyle const*> (

在此示例中,为简单起见,我使用了 --single-process,但这并非必要操作。RR 可以跟踪多个进程;记录后,您可以使用 rr ps 查看列表,然后使用 rr replay -f PID 选择一个进程进行重放。

RR 可以通过多种方式发挥作用。还有其他命令可供使用,例如用于了解您何时所处事件编号的 rr replay -M,或者使用 rr replay -Mstdout 添加每行的进程 ID 和事件编号的注解。如需了解详情,请参阅 RR 网站和文档