日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Runtime底层原理总结--反汇编分析消息转发

發(fā)布時間:2024/9/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Runtime底层原理总结--反汇编分析消息转发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

消息轉(zhuǎn)發(fā):發(fā)送一個消息,也就是sel查找imp,當(dāng)沒有找到imp,接下來進入動態(tài)方法解析,如果開發(fā)者并沒有處理,會進入消息轉(zhuǎn)發(fā)。

消息轉(zhuǎn)發(fā)

前幾篇文章介紹了Runtime底層原理和動態(tài)方法解析總結(jié)

,我們知道如果前面的動態(tài)方法解析也沒有解決問題的話,那么就會進入消息轉(zhuǎn)發(fā)_objc_msgForward_impcache方法,會有快速消息轉(zhuǎn)發(fā)和慢速消息轉(zhuǎn)發(fā)。
_objc_msgForward_impcache方法會從C轉(zhuǎn)換到匯編部分__objc_msgForward_impcache進行快速消息轉(zhuǎn)發(fā),執(zhí)行閉源__objc_msgForward。

如果我們的方法沒有查找到會報錯_forwarding_prep_0

但是我們在源代碼中找不到該方法,除了前面文章–Runtime底層原理–動態(tài)方法解析、消息轉(zhuǎn)發(fā)源碼分析提到的方法外,我們可以用反匯編分析消息轉(zhuǎn)發(fā)。

首先進入/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework中,找到可執(zhí)行文件CoreFoundation,將該文件拖入hopper中,找到CFInitialze可以看到了___forwarding_prep_0___

進入___forwarding_prep_0___內(nèi)部,

從崩潰堆棧信息中看到有執(zhí)行forwarding,進入forwarding內(nèi)部,里面判斷了_objc_msgSend_stret、_objc_msgSend、taggedpointer之后有個forwardingTargetForSelector:,判斷forwardingTargetForSelector:沒有實現(xiàn),沒有實現(xiàn)跳轉(zhuǎn)到loc_126fc7,

進入loc_126fc7,判斷僵尸對象之后執(zhí)行方法簽名methodSignatureForSelector:,如果有值,獲取Name、是否有效的位移等,之后會響應(yīng)_forwardStackInvocation:,

如果沒有響應(yīng)_forwardStackInvocation:,則會響應(yīng)forwardInvocation:,給rdi發(fā)送rax消息,rdi就是NSInvocation,rax就是selforwardInvocation:,這就是消息轉(zhuǎn)發(fā)的流程

對_objc_msgForward部分進行反匯編成OC代碼:

int __forwarding__(void *frameStackPointer, int isStret) {id receiver = *(id *)frameStackPointer;SEL sel = *(SEL *)(frameStackPointer + 8);const char *selName = sel_getName(sel);Class receiverClass = object_getClass(receiver);// 調(diào)用 forwardingTargetForSelector:if (class_respondsToSelector(receiverClass, @selector(forwardingTargetForSelector:))) {id forwardingTarget = [receiver forwardingTargetForSelector:sel];if (forwardingTarget && forwarding != receiver) {if (isStret == 1) {int ret;objc_msgSend_stret(&ret,forwardingTarget, sel, ...);return ret;}return objc_msgSend(forwardingTarget, sel, ...);}}// 僵尸對象const char *className = class_getName(receiverClass);const char *zombiePrefix = "_NSZombie_";size_t prefixLen = strlen(zombiePrefix); // 0xaif (strncmp(className, zombiePrefix, prefixLen) == 0) {CFLog(kCFLogLevelError,@"*** -[%s %s]: message sent to deallocated instance %p",className + prefixLen,selName,receiver);<breakpoint-interrupt>}// 調(diào)用 methodSignatureForSelector 獲取方法簽名后再調(diào)用 forwardInvocationif (class_respondsToSelector(receiverClass, @selector(methodSignatureForSelector:))) {NSMethodSignature *methodSignature = [receiver methodSignatureForSelector:sel];if (methodSignature) {BOOL signatureIsStret = [methodSignature _frameDescriptor]->returnArgInfo.flags.isStruct;if (signatureIsStret != isStret) {CFLog(kCFLogLevelWarning ,@"*** NSForwarding: warning: method signature and compiler disagree on struct-return-edness of '%s'. Signature thinks it does%s return a struct, and compiler thinks it does%s.",selName,signatureIsStret ? "" : not,isStret ? "" : not);}if (class_respondsToSelector(receiverClass, @selector(forwardInvocation:))) {NSInvocation *invocation = [NSInvocation _invocationWithMethodSignature:methodSignature frame:frameStackPointer];[receiver forwardInvocation:invocation];void *returnValue = NULL;[invocation getReturnValue:&value];return returnValue;} else {CFLog(kCFLogLevelWarning ,@"*** NSForwarding: warning: object %p of class '%s' does not implement forwardInvocation: -- dropping message",receiver,className);return 0;}}}SEL *registeredSel = sel_getUid(selName);// selector 是否已經(jīng)在 Runtime 注冊過if (sel != registeredSel) {CFLog(kCFLogLevelWarning ,@"*** NSForwarding: warning: selector (%p) for message '%s' does not match selector known to Objective C runtime (%p)-- abort",sel,selName,registeredSel);} // doesNotRecognizeSelectorelse if (class_respondsToSelector(receiverClass,@selector(doesNotRecognizeSelector:))) {[receiver doesNotRecognizeSelector:sel];}else {CFLog(kCFLogLevelWarning ,@"*** NSForwarding: warning: object %p of class '%s' does not implement doesNotRecognizeSelector: -- abort",receiver,className);}// The point of no return.kill(getpid(), 9); }

該文章為記錄本人的學(xué)習(xí)路程,希望能夠幫助大家,也歡迎大家點贊留言交流!!!文章地址:https://www.jianshu.com/p/29d0272a97ff

總結(jié)

以上是生活随笔為你收集整理的Runtime底层原理总结--反汇编分析消息转发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。