如何在LLDB断点条件下使用堆栈内容?

Mik*_*ard 8 xcode lldb

问题:

我有一个情况下,我们在发射过程中有一个媒体播放,和objc_exception_throw()在此期间命中的5倍左右,但总能吸引,而它的方式向南媒体播放器的对象.

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

我尝试过的:

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

我想做什么:

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

其他想法也欢迎.

Jer*_*man 14

你用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
Run Code Online (Sandbox Code Playgroud)

我尝试对照下面的文件,它成功地跳过内部的第一次抛出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();
}
Run Code Online (Sandbox Code Playgroud)

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