如何在GDB中使用特定操作码中断指令?

时间:2012-12-25 15:31:55

标签: debugging gdb breakpoints

我有一些代码的汇编代码将在程序中的某个点执行。 我不知道内存中代码的地址。

当当前指令与输入的指令匹配时,是否可以使gdb中断?

例如,每当gdb到达此指令时,我都希望gdb中断:

leaq        0x000008eb(%rip),%rax

3 个答案:

答案 0 :(得分:7)

正如其他人所说,由于没有硬件支持,很可能无法有效地完成它。

但如果你真的想这样做,这个Python命令可以作为一个起点:

class ContinueI(gdb.Command):
    """
Continue until instruction with given opcode.

    ci OPCODE

Example:

    ci callq
    ci mov
"""
    def __init__(self):
        super().__init__(
            'ci',
            gdb.COMMAND_BREAKPOINTS,
            gdb.COMPLETE_NONE,
            False
        )
    def invoke(self, arg, from_tty):
        if arg == '':
            gdb.write('Argument missing.\n')
        else:
            thread = gdb.inferiors()[0].threads()[0]
            while thread.is_valid():
                gdb.execute('si', to_string=True)
                frame = gdb.selected_frame()
                arch = frame.architecture()
                pc = gdb.selected_frame().pc()
                instruction = arch.disassemble(pc)[0]['asm']
                if instruction.startswith(arg + ' '):
                    gdb.write(instruction + '\n')
                    break
ContinueI()

只需通过以下方式获取:

source gdb.py

并使用命令:

breaki mov
breaki callq

并且您将继续执行使用给定操作码执行的第一条指令。

TODO:这会忽略你的其他断点。

对于syscall的特定常见情况,您可以使用catch syscallhttps://reverseengineering.stackexchange.com/questions/6835/setting-a-breakpoint-at-system-call

答案 1 :(得分:2)

不,这是不可能的,实施效率也很低。

调试器通常支持两种断点:

  • 硬件断点:调试器要求CPU在发生某些事件时引发特殊异常中断,例如内存中的某些位置已更改。
  • 软件断点:调试器使用特殊的“陷阱”指令(x86架构上的int 3 / 0xcc)替换断点地址处的操作码。

匹配当前指令的操作码要么需要CPU支持来插入硬件断点,要么调试器需要知道使用软件断点的地址。

理论上,调试器只能在整个存储器中搜索指令的字节序列,但由于字节序列也可能出现在指令或数据的中间,因此可能会出现误报。

由于汇编指令是可变长度的,控制可以跳转到任意地址或代码可以修改自身,因此反汇编整个内存区域以找到某些特定指令也是不容易的。

基本上,在任意汇编代码中可靠地查找指令的唯一方法是单步执行指令级。这将是非常昂贵的,如果你单步执行每条指令,即使像printf()这样的简单库调用也可能需要几分钟才能完成今天的硬件。

答案 2 :(得分:2)

  

我不知道内存中代码的地址。

什么阻止您找到该地址?运行objdump -d,找到感兴趣的指令,记下它的地址。问题解决了? (这也简单地扩展到共享库。)