在gdb中使用python脚本继续执行SIGNAL后

6 投票
2 回答
2190 浏览
提问于 2025-04-18 17:56

我正在尝试用一个Python脚本在gdb中生成一些关于段错误(还有其他信号)的输出。这个脚本是这样的:

import gdb

def event_handler(event):
    gdb.execute("set scheduler-locking on") # this is needed to avoid parallel exec of the handler

    gdb.write("\n[ME] SIG " + event.stop_signal)
    frame = gdb.selected_frame()
    while frame:
        gdb.write("\n[ME] FN " + str(frame.name()))
        frame = frame.older()

# make sure output goes to a file
gdb.execute("set logging on") 
gdb.execute("set logging file gdbout")
gdb.events.stop.connect(event_handler)

问题是每当出现段错误时,我都需要按一下c键然后回车,脚本才会继续运行。

如果我在处理程序中这样做:

gdb.execute("continue")

我就会遇到栈溢出的问题。我觉得这是因为execute()这个函数一直没有返回。如果我这样做:

handle SIGSEGV nostop

我的处理程序就不再被调用了。我该如何在处理程序之后继续呢?

2 个回答

1

很遗憾,目前在gdb中还没有一个好的Python接口来处理信号。所以你只能用一些变通的方法。不过,你的做法看起来还不错。

为了处理“继续”的问题,我建议你使用 gdb.post_event 来把一个事件放入gdb的事件队列中。这个事件可以触发 continue 命令。这样至少可以避免栈溢出的问题。

7

好的,我找到了怎么做:

首先,我需要一个可以调用的继续命令。正如Tom所建议的,这个命令会和post_event一起使用:

class Executor:
    def __init__(self, cmd):
        self.__cmd = cmd

    def __call__(self):
        gdb.execute(self.__cmd)

接下来是事件处理器:

def event_handler(event):
    gdb.execute("set scheduler-locking on") # to avoid parallel signals in other threads

    gdb.write("\n[ME] SIG " + event.stop_signal)
    frame = gdb.selected_frame()
    while frame:
        gdb.write("\n[ME] FN " + str(frame.name()))
        frame = frame.older()
    gdb.execute("set scheduler-locking off") # otherwise just this thread is continued, leading to a deadlock   
    gdb.post_event(Executor("continue")) # and post the continue command to gdb

然后,调用它的方法是:

gdb.execute("set logging on")
gdb.execute("set logging file gdbout")
gdb.execute("set pagination off")
gdb.events.stop.connect(event_handler)

这里的关键是稍后要禁用调度器锁定,这样做是为了避免并发问题,但如果没有处理器在运行,就会导致死锁。

撰写回答