【问题标题】:How do I use stack content in an LLDB breakpoint condition?如何在 LLDB 断点条件下使用堆栈内容?
【发布时间】:2013-05-31 03:29:49
【问题描述】:

问题:

我遇到过一种情况,我们在启动期间播放媒体,并且 objc_exception_throw() 在此期间点击了大约 5 次,但总是被捕获,并且它位于媒体播放器的南边方式对象。

我厌倦了 (a) 必须手动继续 n 次,或者 (b) 必须在播放完成之前禁用断点。

我的尝试:

  • 使断点忽略前五次命中(问题:并不总是准确五次)
  • 使用我的目标作为模块创建我自己的符号断点(问题:没有任何改变)

我想做的事:

想到的一个解决方案是在断点命中时评估堆栈,并在其中列出特定方法或函数时继续。但我不知道该怎么做。

也欢迎其他想法。

【问题讨论】:

    标签: xcode lldb


    【解决方案1】:

    您使用 Python 来完成。

    以下定义了一个忽略列表和一个可以作为命令附加到断点的函数。

    该函数在回溯中获取函数的名称,并将这些名称与忽略列表设置相交。如果有任何名称匹配,它会继续运行该进程。这有效地跳过了进入调试器以查找不需要的堆栈。

    (lldb) b objc_exception_throw
    Breakpoint 1: where = libobjc.A.dylib`objc_exception_throw, address = 0x00000000000113c5
    (lldb) script
    Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    >>> ignored_functions = ['recurse_then_throw_and_catch']
    def continue_ignored(frame, bp_loc, dict):
        global ignored_functions
        names = set([frame.GetFunctionName() for frame in frame.GetThread()])
        all_ignored = set(ignored_functions)
        ignored_here = all_ignored.intersection(names)
        if len(ignored_here) > 0:
            frame.GetThread().GetProcess().Continue()
    
    quit()
    
    (lldb) br comm add -F continue_ignored 1
    (lldb) r
    

    我对以下文件进行了尝试,它成功跳过了recurse_then_throw_and_catch 内的第一次抛出,并在 throw_for_real 内的抛出期间进入调试器。

    #import <Foundation/Foundation.h>
    
    void
    f(int n)
    {
        if (n <= 0) @throw [NSException exceptionWithName:@"plugh" reason:@"foo" userInfo:nil];
    
        f(n - 1);
    }
    
    void
    recurse_then_throw_and_catch(void)
    {
        @try {
            f(5);
        } @catch (NSException *e) {
            NSLog(@"Don't care: %@", e);
        }
    }
    
    void
    throw_for_real(void)
    {
        f(2);
    }
    
    int
    main(void)
    {
        recurse_then_throw_and_catch();
        throw_for_real();
    }
    

    我想您可以将此功能添加到您的.lldbinit,然后根据需要从控制台将其连接到断点。 (我认为你不能在 Xcode 中设置脚本命令。)

    【讨论】:

    • 该死的,伙计。我本来希望得到的最佳答案。
    • 不错的答案。唯一需要注意的是,如果任何ignored_functions 出现在堆栈上的任何位置,这将continue,而不仅仅是检查“上方”的框架objc_exception_throw
    • @JasonMolenda 完全正确。 “堆栈上的任何地方”是我认为基于“在断点命中时评估堆栈,如果其中列出了特定的方法或函数则继续”。改用if frame.GetThread().GetFrameAtIndex(1).GetFunctionName() in ignored_functions: 会很简单。关键见解是使用 Python 函数作为断点命令。
    • 还要注意,从 Xcode 5 的 lldb 开始,lldb 检查 Python 断点命令的返回值,如果它们返回布尔值 False,lldb 将从断点继续。也许这比手动调用“继续”要容易一些。这也意味着如果你同时命中两个断点(这确实发生在线程代码中),lldb 只有在两个断点命中都想继续时才会继续。
    【解决方案2】:
    break command add -s python -o "return any('xyz' in f.name for f in frame.thread)"
    

    如果 python 断点命令返回False,lldb 将继续运行。这就是说:如果堆栈中的any 帧的名称中有字符串'xyz',则返回True(停止)。否则,如果没有框架具有该名称,则此 any 表达式将返回 False(继续进行)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-03
      • 2019-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2014-03-18
      • 2011-12-12
      相关资源
      最近更新 更多