[OC底层]LLVM对alloc的优化

613 阅读2分钟

llvm对alloc的优化

我们再来动态静态分析一下alloc的流程,

1:首先使用汇编查看动态流程.

Debug -> Debug Workflow -> Always Show Disassembly 如下图一样打断点, 并运行

Screenshot 2021-08-06 at 14.24.13.png

可以看出下一个要跑到的方法是objc_alloc

2:command+鼠标静态分析代码

可以看到alloc 要跳到的下一个方法是_objc_rootAlloc 而不是objc_alloc 这又是什么原因呢?

Screenshot 2021-08-08 at 19.07.51.png

从上面的注释,我猜测是SEL和IMP进行了交换?

首先我们定位到类的加载映射里面找到_read_image方法, 这个方法里面有处理映射方法的代码块 Screenshot 2021-08-08 at 19.11.05.png 然后在这个长长的方法里面我跟踪到了另一个方法: fixupMessageRef(message_ref_t *msg) Screenshot 2021-08-08 at 19.13.57.png

可以看到这个方法里面将alloc绑定到了objc_alloc上面, 同样这个方法对retain, release, autorelease做了同样的操作. 从上段代码块可以看出, 当alloc出问题时, 会对他做出修复.如果没问题时,就直接执行objc_alloc方法. 苹果对一些方法进行hook处理, alloc是直接对内存进行直接操作的, 所以会对其进行相应的监控, 也就是hook拦截, 当调用alloc的时候, 不直接走alloc的底层流程, 而是先找objc_alloc, 找完objc_alloc之后, 才开始对下层进行标记, 标记完成之后, 才开始找alloc方法. Screenshot 2021-08-08 at 19.02.38.png

来到LLVM的源码 在LLVM源码里面搜索objc_alloc, 在CGObjC.cpp中找到了如下代码static Optional<llvm::Value *> tryGenerateSpecializedMessageSend:

Screenshot 2021-08-09 at 10.12.26.png

进入到llvm::Value *CodeGenFunction::EmitObjCAlloc 方法里

Screenshot 2021-08-09 at 10.14.10.png 可以看出allocobjc_alloc逻辑就这样实现了绑定.

那么谁调用的tryGenerateSpecializedMessageSend 这个方法呢, 在LLVM的源码里面搜索到了GeneratePossiblySpecializedMessageSend这个方法. 可以看出在这个方法里通过消息发送走到了tryGenerateSpecializedMessageSend.

Screenshot 2021-08-09 at 10.21.28.png 苹果对苹果对alloc等特殊函数做了hook,先走emitObjCValueOperation, 然后首次会走tryGenerateSpecializedMessageSend分支,第二次就走GenerateMessageSend分支了。

也就是第一次alloc调用了objc_alloc,第二次alloc后就没有调用objc_alloc走了正常的objc_msgSendalloc-> objc_alloc -> callAlloc -> alloc -> _objc_rootAlloc -> callAlloc。这也就是callAlloc走两次的原因。

Reference:

www.imgeek.org/article/825…