GDB 行动迟缓

GDB 行动迟缓

我正在很好地演示 ARM 汇编代码的执行,我需要 GDB 每 1 秒无限长地步进代码(直到我按CTRL+ C)。有人有解决办法吗?

当访客来参观我的摊位时,我不想继续站在键盘旁边并执行程序。

答案1

Gdb 的 CLI 支持while循环。没有内置sleep命令,但您可以调用 shell 来运行程序sleep,或者使用 gdb 的内置 python 解释器(如果有)。它可以用 Control-C 中断。

方法一:

(gdb)而 (1)
 >
 >外壳睡眠 1
 >结尾

方法二:

(gdb)python 导入时间
(gdb)而 (1)
 >
 >python time.sleep(1)
 >结尾

方法三(定义宏):

(gdb)定义运行缓慢
键入命令来定义“runslowly”。
以一行“结束”结束。
>python 导入时间
>而 (1)
 >
 >python time.sleep(1)
 >结尾
>结尾
(gdb)文件运行缓慢
键入“runslowly”的文档。
以一行“结束”结束。
>一次走一行,每 1 秒一次
>结尾

(gdb)运行缓慢

答案2

expect可以自动化这个

#!/usr/bin/env expect
spawn -noecho gdb -q ls
expect -ex {(gdb)}
send -- "break main\r"
expect -ex {(gdb)}
send -- "run\r"
while {1} {
    expect -ex {(gdb)}
    send -- "s\r"
    sleep 1
}

或者,如果存在程序耗尽的风险,s您可以重复执行gdb,但稍微复杂一点

#!/usr/bin/env expect

while {1} {
    spawn -noecho gdb -q ls
    expect -ex {(gdb)}
    send -- "break main\r"
    expect -ex {(gdb)}
    send -- "run\r"
    expect {
        -ex {The program is not being run} {}
        eof {}
        -ex {(gdb)} {
            send -- "s\r"
            sleep 1
            exp_continue
        }
    }
}

答案3

你可以在命令中使用 shell 管道;想法是这样的:

while :; do echo step; sleep 1; done | gdb arm-program

gdb 从管道读取命令;它每隔一秒就会看到一个“step”命令,无限循环。

您可能想设置一些断点并运行程序;调整口味:

(echo br 1; echo run; while :; do echo step; sleep 1; done ) | gdb arm-program

答案4

目前接受的答案确实总是 step,一旦启动,因此也会“跳过”断点、信号甚至程序结束(在最后一种情况下,在 gdb 内部中止发生的地方之前,会引发一个错误“程序未运行” while)。
作为另一个罪魁祸首,如果 GDB 输出“已满”,则如果打开分页(这是默认设置),它就会停止。

使用 python api 可以很好地处理这个问题:

  • 定义用户命令(带有附加参数来说明自动步进的速度)
  • 可选:定义默认参数(为简单起见,此处替换为固定值)
  • 在python中执行while循环,处理CTRL-C的“预期”键盘中断
  • 注册一个stop事件处理程序来检查停止原因并将步骤类型存储在那里
  • 调整 while 循环以停止“不简单”的停止(断点/观察点/信号/...)

以下代码可以放置在 gdb-auto-step.py 中,source gdb-auto-step.py只要您需要,就可以将其激活(或包含在 .gdbinit 文件中以使其始终可用):

import gdb
import time

class CmdAutoStep (gdb.Command):
    """Auto-Step through the code until something happens or manually interrupted.
An argument says how fast auto stepping is done (1-19, default 5)."""
    def __init__(self):
        print('Registering command auto-step')
        super(CmdAutoStep, self).__init__("auto-step", gdb.COMMAND_RUNNING)
        gdb.events.stop.connect(stop_handler_auto_step)

    def invoke(self, argument, from_tty):

        try:
            frame = gdb.newest_frame()
        except gdb.error:
            raise gdb.GdbError("The program is not being run.")

        number = 5 # optional: use a parameter for the default
        if argument:
            if not argument.isdigit():
                raise gdb.GdbError("argument must be a digit, not " + argument)
            number = int(argument)
            if number == 0 or number > 19:
                raise gdb.GdbError("argument must be a digit between 1 and 19")

        sleep_time = 3.0 / (number * 1.4)

        global last_stop_was_simple
        last_stop_was_simple = True

        pagination = gdb.execute("show pagination", False, True).find("on")
        if pagination:
            gdb.execute("set pagination off", False, False)
        
        try:
            while (last_stop_was_simple):
                gdb.execute ("step")
                time.sleep(sleep_time)
        except KeyboardInterrupt as ki:
            if pagination:
                gdb.execute("set pagination on", False, False)
        except gdb.GdbError as user_error:
            if pagination:
                gdb.execute("set pagination on", False, False)
            # pass user errors unchanged
            raise user_error
        except:
            if pagination:
                gdb.execute("set pagination on", False, False)
            traceback.print_exc()

def stop_handler_auto_step(event):
    # check the type of stop, the following is the common one after step/next,
    # a more complex one would be a subclass (for example breakpoint or signal)
    global last_stop_was_simple
    last_stop_was_simple = type(event) is gdb.StopEvent

CmdAutoStep()

https://stackoverflow.com/a/67470615/5027456以获得更完整(和更新)的代码,包括速度参数、auto-next以及auto-step更好的错误处理。

相关内容