在Objective-C函數的入口處(第一行)加斷點,可用esp指針來探查參數。
以esp為基址,往後的偏移分别是:
0:函數執行完畢後的傳回位址(不是傳回值的位址哦)
4:對象執行個體的指針,即self指針
8:selector,實際是一個char數組型的字元串,即char*
12:(如果有)第一個參數
…(前一個參數的基址+前一個參數所占的位元組數):(如果有)第n個參數
由此,要調試這樣一個函數
時,斷點後可在gdb這樣調試:
po *(id*)($esp+4) // 得到對象執行個體的描述。執行越過函數頭部後,應為 po *(id*)($ebp+8),以下類同。
p (char*)*(SEL*)($esp+8) // 得到selector的名字
po *(id*)($esp+12) // 得到p1的description
p *(CGRect*)($esp+16) // 得到p2的各個成員值,輸出結果為:“(CGRect) $1 = origin=(x=10, y=20) size=(width=30, height=40)”
p *(CGPoint*)($esp+32) // 因為一個CGRect結構體占16位元組(4個float),是以是“+32”,即“+16+16”, 得到p3的各個成員值,輸出結果為:“(CGPoint) $4 = (x=50, y=60)”
po *(id*)($esp+40) // 因為一個CGPoint結構體占8位元組(2個float),是以是“+40”,即“+32+8”、得到p4的description
注意:由于在第一行,push了ebp,會導緻esp被修改,而第二行又立刻把esp的值賦給ebp,是以在執行經過函數的這些頭部後,可以用ebp類似地通路,不過參數的偏移都需要+4。
下面是如何檢視浮點型參數。
浮點型參數會通過SSE寄存器來傳遞,可以在gdb中這樣檢視:
(lldb不能用上面的指令,暫沒去研究用什麼替代)
例如調試上例中的
編譯器會把參數反序送入xmm寄存器組,即40傳入xmm0,30傳入xmm1……
在CGRectMake加斷點,執行到下圖中的位置時輸入指令
指令結果如下:
因為SSE寄存器是128位的,gdb并不知道哪些bit是有意義的,是以列出了一些猜測的結果。
我們傳入的是CGFloat,即float,故v4_float = {0, 0, 0, 40} 是有意義的。
當傳入的是double型,則v2_double有意義。
xcode反彙編調試iOS模拟器程式
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8697654">(一)檢視反彙編</a>
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8700964">(二)看懂反彙編</a>
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8721870">(三)檢視Objective-C函數與參數</a>
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8752235">(四)自動斷點應用之NSNotificationCenter</a>
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8755491">(五)調試objc_msgSend函數</a>
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8766487">(六)函數出入口處的處理與局部變量</a>
<a target="_blank" href="http://blog.csdn.net/hursing/article/details/8766719">(七)Debug與Release的差別</a>