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, b
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).
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.)