如何转到GDB的上一行?

时间:2009-07-30 14:15:24

标签: debugging gdb

是否可以在gdb中转到当前执行行之前的一行。 e.g:


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的内容。

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

9 个答案:

答案 0 :(得分:96)

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

命令为“reverse-step”或“reverse-next”。

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

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

修改:由于弃用了GDB 7.6 target record,请改用target record-full

答案 1 :(得分:12)

是的,现在,使用真实硬件(即不仅仅是VM),这是可能的,而且很简单。 GDB-7.0支持在本机linux x86机器上使用反向步骤和反向继续等命令进行反向调试。

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

答案 2 :(得分:5)

简短回答:不。

对于解决方法,请阅读以下内容。

虽然在第b行无法确定a行的值,但只能通过一个断点记录a和b以及其他位置的arr值。

  • 使用“display”命令( display variable_name ,其中variable_name将替换为arr,* arr,** arr,具体取决于您要查找的内容),以便在遇到任何断点时, variable_name的内容将被转储到屏幕上。请注意,当variabe_name在范围内时,您可以添加到显示列表,这可能需要您等待第一个断点。
  • 在您有兴趣记录variable_name值的代码的各个位置创建断点。一个这样的断点就在第a行。
  • 对于每个断点,使用命令(命令breakpoint_number )并指示断点不要暂停程序的执行。您需要使用的命令是 continue ,然后是 end 。见下面的例子。
  
    

(gdb)命令1

         

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

         

继续

         

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

现在,当所有其他日志记录断点都被命中时,arr的值将被转储到屏幕上,但断点不会等待用户交互并自动继续。当您在第b行点击断点时,您可以看到arr的过去值,这些值将记录在gdb本身中。

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

答案 3 :(得分:5)

mozilla rr

https://github.com/mozilla/rr

GDB的内置记录和重播有严重的限制,例如:不支持AVX指令:gdb reverse debugging fails with "Process record does not support instruction 0xf0d at address"

rr的好处:

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

以下示例展示了它的一些功能,特别是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

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

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;

    /* 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会话中,你可以正确地反向调试:

(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;

答案 4 :(得分:2)

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

答案 5 :(得分:2)

如果你的节目很短,通常的伎俩就是,

  1. 在上一行放置一个新断点
    • 触发 r 重启调试
  2. GDB 是为了做到这一点!

答案 6 :(得分:1)

不是gdb,但你可以使用名为qira的调试器轻松回到历史记录中。您可以使用向上和向下箭头来回移动,它还会突出显示哪些寄存器已更改。

enter image description here

答案 7 :(得分:0)

每个人都希望像这样的Omniscient Debugger:http://www.lambdacs.com/debugger/,但它们(取决于语言/机器)很难制作并且需要做大量的簿记。

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

答案 8 :(得分:0)

如果arr的设置代码位于“line a”(非常常见的情况)之上,您可以这样做:

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

jump 123

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

然后您可以单步执行设置代码或只在“a行”处设置断点并继续