你用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中設置的腳本命令。)
該死的,夥計。我可能希望的最佳答案。 – MikeyWard
很好的答案。唯一需要注意的是,如果任何'ignored_functions'出現在堆棧的任何位置,而不是僅僅檢查objc_exception_throw之上的幀,這將會「繼續」。 –
@JasonMolenda完全正確。「堆棧中的任何地方」就是我所期望的,基於「斷點到達時評估堆棧,並在其中列出特定方法或函數時繼續」。這將很容易適應做'if frame.GetThread().getFrameAtIndex(1).GetFunctionName()in ignored_functions:'而不是。關鍵的見解是使用Python函數作爲斷點命令。 –