iOS 系统的延迟绑定机制
|
延迟绑定机制是指将符号的绑定工作推迟到符号第一次被程序调用的时候。为了大家更好地理解延迟绑定的概念以及我们为什么要延迟绑定,本文首先会介绍一些程序链接方面的知识。相关背景链接在编译过程中的位置一般来说... 延迟绑定机制是指将符号的绑定工作推迟到符号第一次被程序调用的时候。为了大家更好地理解延迟绑定的概念以及我们为什么要延迟绑定,本文首先会介绍一些程序链接方面的知识。 相关背景链接在编译过程中的位置一般来说,代码的编译过程分为以下几个阶段:
链接是程序编译过程中的最后一步,也是十分重要的一步,它主要有两方面的工作:(1)符号解析。将符号的引用和符号的定义联系起来;(2)重定位。将符号的定义和具体的地址对应起来,并修改所有对这些符号的引用,使它们指向相应的地址。 静态链接在很久很久以前,链接是指静态链接,也就是将所需的库文件全部都拷贝一份到程序中,最终形成一个可执行文件。静态链接在技术上是没有什么问题的,但是随着时间的推移,人们也发现了它身上的一些硬伤:
所以为了解决这些问题,勤劳、善良的程序员们又发明了新的技术:动态链接。 动态链接静态链接问题的根源在于它使程序和静态库的联系过于紧密,解决问题的关键是降低二者间的耦合度,动态链接技术为此应运而生。 与静态链接相比,动态链接将相关符号的绑定工作推迟到程序被加载到内存中执行的时候,这不仅减少了程序的编译时间,而且也使得库文件能够真正的被不同的程序所共享。此处的“共享”有两点含义:一是指库文件在操作系统中只存在一份,而不是像静态链接那样将库文件给每个程序都拷贝一份;二是指在程序运行的过程中,共享库的 text 段的内容可以被不同的进程所共享。 与动态链接技术相对应的库文件叫做动态库文件,在 Windows 上是 dll 文件,在 Linux 上是 so 文件,而在 Mac 上则是 dylib 文件。 我们知道,把对符号的引用修正为符号所对应的地址是链接过程中的关键部分,动态库也是一样,它也要做出相应的修改,但是最尴尬的地方在于动态库只有一份,但是它会被很多进程加载,而且它事先并不知道自己会被加载到哪里。 举个例子:假设动态库加载到进程 A 的地址为 0xAAAAAA,链接结束后动态库相关符号的地址也被修改,如果此后没有进程加载该动态库,那么一切都没有问题。可是直到某一天,进程 B 也要加载此动态库,还硬要把它加载到 0xBBBBBB 上,这样麻烦就来了。动态库中符号的相关地址是基于 0xAAAAAA 的,在进程 B 中是无法工作的,那么要基于 0xBBBBBB 修改吗?这样进程 A 就不能工作了。重新拷贝一份到进程 B 吗?那你还共享个啥啊!!! 还有一个潜在的问题,那就是动态库的 text 段必须是可写的,否则加载的时候就无法修改相关符号进行重定位,这就会使安全性大打折扣。 为了使动态链接成为可能,我们勤劳、善良的程序员又发明了新的技术,即 PIC(Position Independent Code)。 Position Independent CodePIC 又称为位置无关代码,即相关代码加载到任何位置都可以正常运行,动态库的编译都需要加上 -fPIC -shared 选项。
那么 PIC 是如何实现的?它又是如何在不修改 text 段的情况下,让同一动态库加载到不同进程的不同位置?使用动态库的程序又需要做哪些工作? 答案其实很简单,就是多一层引用关系。 既然 text 段不让写,那我就写 data 段呗 (编辑:无忧刷机网 - 51刷机网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
