How do I use stack content in an LLDB breakpoint condition?

折月煮酒 提交于 2019-11-29 19:14:38

问题


The problem:

I've got a situation where we have a media playback during launch, and objc_exception_throw() hits about 5 times during that period, but is always caught, and it's way south of the media player object.

I'm tired of either (a) having to manually continue n times, or (b) having to leave breakpoints disabled until after the playback is complete.

What I've tried:

  • making the breakpoint ignore the first five hits (problem: it's not always exactly five times)
  • creating my own symbolic breakpoint using my target as the module (problem: nothing changed)

What I'd like to do:

One solution that comes to mind is to evaluate the stack when the breakpoint hits, and continue if a particular method or function is listed therein. But I have no idea how to do this.

Other ideas welcome as well.


回答1:


You do it using Python.

The following defines an ignore list and a function you can attach as a command to a breakpoint.

The function grabs the names of functions in the backtrace and set-intersects those names with the ignore list. If any names match, it continues running the process. This effectively skips dropping into the debugger for unwanted stacks.

(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

I tried it against the following file, and it successfully skips the first throw inside recurse_then_throw_and_catch and drops into the debugger during the 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();
}

I imagine you could add this function to your .lldbinit and then connect it to breakpoints as needed from the console. (I don't think you can set a script command from within Xcode.)




回答2:


break command add -s python -o "return any('xyz' in f.name for f in frame.thread)"

If a python breakpoint command returns False, lldb will keep going. So this is saying: if any frame in the stack has the string 'xyz' in its name, then return True (to stop). Otherwise if no frame has that name, this any expression will return False (to keep going).



来源:https://stackoverflow.com/questions/16922859/how-do-i-use-stack-content-in-an-lldb-breakpoint-condition

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!