10

问题:

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

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

我试过的:

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

我想做的事:

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

也欢迎其他想法。

4

2 回答 2

17

你用 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

我对以下文件进行了尝试,它成功地跳过了第一个 throw insiderecurse_then_throw_and_catch并在 throw inside 期间掉入调试器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 中设置脚本命令。)

于 2013-06-04T18:09:12.233 回答
4
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(继续进行)。

于 2017-06-22T18:48:22.010 回答