2013-06-04 90 views
7

問題:如何在LLDB斷點條件中使用堆棧內容?

我有一種情況,我們在發射過程中有一個媒體播放,和objc_exception_throw()在此期間命中的5倍左右,但總是抓,這是方式南媒體播放器對象。

我厭倦了(a)必須手動繼續n次,或者(b)在播放完成之前不得不離開斷點。

我已經試過什麼:

  • 使得斷點忽略第一個五支安打(問題:它並不總是準確的五倍)
  • 使用我的目標作爲模塊創建我自己的符號斷點(問題:什麼都沒有改變)

我想做什麼:

想到的一個解決方案是在斷點碰撞時評估堆棧,並在其中列出特定方法或函數時繼續。但我不知道如何做到這一點。

其他想法也歡迎。

回答

12

你用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中設置的腳本命令。)

+0

該死的,夥計。我可能希望的最佳答案。 – MikeyWard

+0

很好的答案。唯一需要注意的是,如果任何'ignored_functions'出現在堆棧的任何位置,而不是僅僅檢查objc_exception_throw之上的幀,這將會「繼續」。 –

+0

@JasonMolenda完全正確。「堆棧中的任何地方」就是我所期望的,基於「斷點到達時評估堆棧,並在其中列出特定方法或函數時繼續」。這將很容易適應做'if frame.GetThread().getFrameAtIndex(1).GetFunctionName()in ignored_functions:'而不是。關鍵的見解是使用Python函數作爲斷點命令。 –

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

如果蟒蛇斷點命令返回False,LLDB將繼續下去。所以這就是說:如果堆棧中的any幀的名稱中有字符串'xyz',則返回True(停止)。否則,如果沒有幀具有該名稱,則此any表達式將返回False(繼續前進)。