首页 文章

如何才能在断点处使GDB在SIGTRAP处停止?

提问于
浏览
4

我不能手动"continue"所有这些无关的SIGTRAP . 但是如果我使用命令 handle SIGTRAP nostop noprint ,则GDB不会在我的断点处停止 .

似乎必须有一种方法来教育GDB,以便它了解哪个SIGTRAP有利于停止,哪个不利于停止 . 很明显,GDB知道它是否处于断点,因为输出非常可靠地不同:在断点处,它提到“断点”并显示断点号 - 但在任何其他SIGTRAP中,它只是说“SIGTRAP” . 所以不是打印关于SIGTRAP的消息,我真的很喜欢GDB对自己说,“哇,这是一个SIGTRAP,这里没有断点 - 看着我,我要停下来打印一个完全破坏调试会话的无用的SIGTRAP消息!我只是静静地继续?“如果有人有办法,请告诉我 .

1 回答

  • 2

    您可以设置catchpoints以捕获SIGTRAP信号并添加命令以决定是继续还是停止 . 在此处理程序中,您可以检查convenience variables,例如$_siginfo,以了解信号的原因 .

    特别感兴趣的是 $_siginfo.si_code ,其值取决于所传递的信号 . sigaction(2) Linux手册页描述了确切的关系 . 您可以通过编译程序或查找 Headers 来找到这些 SI_USERSI_KERNEL 等代码的数值(在我的系统上它使用 Headers /usr/include/bits/siginfo.h ) . 我遇到的一些值是:

    • 0x00(0): SI_USER

    • 0x80(128): SI_KERNEL

    • 0x02(2): TRAP_TRACE

    有了这些信息,这里有一个捕获SIGTRAP并打印原因的例子,然后继续:

    catch signal SIGTRAP
    commands
     p $_siginfo.si_code
     c
    end
    # Set another breakpoint for testing
    break sleep
    

    现在考虑这个睡眠时间为5秒的测试程序,然后在x86(-64)上触发调试陷阱:

    #include <unistd.h>
    int main(void) {
        for (;;) {
            sleep(5);
            asm("int3");
        }
        return 0;
    }
    

    该程序在 int3 行停止 gdb ,因为信号被捕获( si_code 恰好是0x80, SI_KERNEL ),但随后指令再次重复 . 因此,要跳过此指令,必须递增程序计数器( $pc ) . 完成后,我学习了有关 SIGTRAPsi_code 的信息:

    • 断点使用代码128( SI_KERNEL )触发SIGTRAP .

    • 继续破坏之后,接收到代码为2( TRAP_TRACE )的SIGTRAP(因为 SIGTRAP 的捕获点) .

    • int3 指令使用代码128触发SIGTRAP . 因此,您需要一些东西来区分指令 .

    以下是跳过 int3 陷阱并仍保持断点功能的最终GDB命令:

    catch signal SIGTRAP
    commands
     silent # do not print catchpoint hits
     # ignore the int3 instruction (this address was looked up at
     # the tracepoint using print $pc)
     if $pc == 0x400568
      set $pc++ # skip int3
      c
     end
     # Ignore TRAP_TRACE that is used for breakpoints
     if $_siginfo.si_code == 2
      c
     end
    end
    

    最后一点:SIGTRAP由调试器在内部使用,上述内容可能过多 . 这是在Arch Linux上使用GDB 7.10测试的 .

相关问题