首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在gdb中跨过长gdb

如何在gdb中跨过长gdb
EN

Stack Overflow用户
提问于 2016-11-03 18:14:45
回答 3查看 1.1K关注 0票数 2

我正在尝试修复其他人编写的代码中的一个bug,并试图在gdb中执行一步,以了解到底发生了什么。但是我点击的其中一行是对longjmp()的调用,在命中该行上的" next“之后,gdb继续正常执行,而不是中断正在执行的下一个源行。如果我在longjmp()行上尝试"step“,也会发生类似的继续。在longjmp()之后,我可以使用任何gdb命令来中断下一个源行吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-03 18:32:12

您需要在setjmp的非零返回代码后面的行设置一个断点。

例如:

代码语言:javascript
复制
#include <stdio.h>
#include <setjmp.h>

jmp_buf jb;

void f1()
{
    printf("jumping\n");
    longjmp(jb, 1);
    printf("what???\n");
}

int main()
{
    if (!setjmp(jb)) {
        printf("calling f1\n");
        f1();
    } else {
        printf("jumped!!\n");    // line 19
    }
    return 0;
}

调用longjmp之后,下一个要执行的行是第19行(参见注释)。因此,在本例中,在gdb提示符下运行break 19,然后在调用longjmp之后在该行处停止。

gdb产出:

代码语言:javascript
复制
(gdb) break 19
Breakpoint 2 at 0x40056d: file /tmp/x1.c, line 19.
(gdb) start
Temporary breakpoint 3 at 0x400549: file /tmp/x1.c, line 15.
Starting program: /tmp/x1
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000

Temporary breakpoint 3, main () at /tmp/x1.c:15
15          if (!setjmp(jb)) {
(gdb) step
16              printf("calling f1\n");
(gdb)
calling f1
17              f1();
(gdb)
f1 () at /tmp/x1.c:8
8           printf("jumping\n");
(gdb)
jumping
9           longjmp(jb, 1);
(gdb)

Breakpoint 2, main () at /tmp/x1.c:19
19              printf("jumped!!\n");
(gdb)
jumped!!
21          return 0;
(gdb)
22      }
(gdb)
0x0000003fa441d9f4 in __libc_start_main () from /lib64/libc.so.6
(gdb)
票数 1
EN

Stack Overflow用户

发布于 2016-11-03 19:07:38

值得注意的是,gdb的行为是系统依赖的。

在Linux上,nextlongjmpthrow上的工作方式与您预期的大致相同:如果非本地跳转的目标位于或高于当前帧,则执行将停止。

这是使用longjmpthrow实现中的调试钩子来实现的。对于throw,这是通过一个助手函数(较早的方法)和所谓的SystemTap探测(也称为"sdt探测“)完成的。对于longjmp,这只能用glibc中的sdt探测来完成。

为此,必须将探测支持编译到有关库中。您可以向readelf -n查询。至少Fedora做得很好。

理论上可以为gdb中的其他平台实现对longjmp的支持。然而,这可能是不平凡的。

您可以尝试解码jmp_buf,就像其他注释中提到的那样。但是,请注意,在某些系统(如Linux )中,出于安全考虑,jmp_buf中的目标PC是编码的。所以你得想办法破解它。

另一种方法是简单地通过longjmp本身进行一步操作。在那里设置一个断点,如break longjmp;使用disassemble查看程序集;然后使用si,直到您逐步完成将执行转移到目标的指令为止。

票数 6
EN

Stack Overflow用户

发布于 2016-11-03 18:33:49

在longjmp()之后,我可以使用任何gdb命令来中断下一个源行吗?

据我所知没有。您需要在调用堆栈中跟踪jmp_buf的起源,以找到填充它的setjmp()。如果源中的setjmp()调用很少,则可以考虑在每次调用之后设置一个断点。否则,您可能只需遍历程序,在传递的每个setjmp()之后设置一个断点。

还请注意,当到达相应的setjmp()时,您确实应该在调用堆栈中的一个函数中找到相关的longjmp(),否则jmp_buf无效。

您可以使用bt命令获取调用堆栈,使用frame命令切换到堆栈上的任何帧并对其进行检查。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40408553

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档