使用gdb脚本修剪回溯输出

时间:2013-05-09 17:48:21

标签: gdb

我的程序有100个线程,其中大多数是空闲的,并且在空闲时共享一个非常明确的回溯。大多数时候我只对非空闲的线程感兴趣,因此没有“常见”的回溯。我认为使用gdb脚本是一种很好的方法。

define backtraces
    thread apply all bt
end

此脚本将只打印所有回溯。有没有办法将此输出存储到变量中,然后我可以处理,修剪并仅显示相关的回溯?

我天真地试过:

define backtraces
    set $bts = thread apply all bt
    // do whatever processing here
end

但是按照预期的那样失败了:

  

当前上下文中没有符号“thread”。

有更好的方法吗?或者关于如何在gdb中为脚本提供动力的好教程?

3 个答案:

答案 0 :(得分:2)

  

有更好的方法吗?

您需要使用Python scripting来获得所需的结果。

filtering backtrace可能是一个好的开始。

答案 1 :(得分:1)

使用Employed Russian的回答中的链接,我得到了一些工作。这是后人,因为它完全不明显。

import gdb

# This loops through all the Thread objects in the process
for thread in gdb.selected_inferior().threads():

    # This is equivalent to 'thread X'
    thread.switch()       

    print "Thread %s" % thread.num

    # Just execute a raw gdb command
    gdb.execute('bt')

    framesNames = []
    f = gdb.newest_frame()
    while f is not None:
        framesNames.append(gdb.Frame.name(f))
        f = gdb.Frame.older(f)

    # do something with the name of each frame

如果这是在一个名为traces.py的文件中,那么从gdb中你可以执行python:

source traces.py

还有其他方法可以调用此python脚本。

答案 2 :(得分:0)

这是我根据JaredC得出的结论:

import gdb

class FilteredThreadBacktraceCommand(gdb.Command):
    """
    Implements a command that allows printing the backtrace only for threads
    that do not have given frames.

    The class must be instantiated with a list of the frames to ignore. If the
    stack for a thread has any of those frames then the stack for that thread
    will not be printed (a visual dot will be printed to show a thread was just
    ignored and provide a notion of progress).
    """
    def __init__(self, ignored_frames):
        super (FilteredThreadBacktraceCommand, self).__init__ ("fbt", gdb.COMMAND_STACK)
        self.ignored_frames = ignored_frames

    def invoke(self, arg, from_tty):
        args = gdb.string_to_argv(arg)
        if len(args) != 0:
            gdb.write("ERROR: invalid number of arguments.\n")
            return

        # This loops through all the Thread objects in the process
        for thread in gdb.selected_inferior().threads():

            # This is equivalent to 'thread X'
            thread.switch()

            f = gdb.newest_frame()
            frames = []
            invalid_thread = False
            while f is not None:
                if any(ignored_frame in f.name() for ignored_frame in self.ignored_frames):
                        invalid_thread = True
                        break
                frames.append(f)
                f = gdb.Frame.older(f)

            if invalid_thread:
                # Visual effect as iterating frames might take a while
                sys.stdout.write('.')
                sys.stdout.flush()
                continue

            print "\nThread %s:" % thread.num
            for i in range(len(frames)):
                f = frames[i]
                funcInfo = f.function()
                printStr = "#{} in {}".format(i, f.name())
                if f.function():
                    printStr += " at {}:{}".format(funcInfo.symtab.filename, funcInfo.line)
                else:
                    printStr += " at (???)"
                print(printStr)

 FilteredThreadBacktraceCommand(["os::PlatformEvent::park"])

您可以在创建时向类提供要忽略的框架。也可以使用这种通用名称,以便为要注册的命令提供一个名称,以便您可以使用不同的过滤来使用不同的命令。

相关问题