返回

细说库文件到类的内存加载

IOS

前言

在前面的学习中,我们已经基本了解了dyld对于底层镜像文件的处理,即把这些镜像文件映射到程序中,但这些镜像文件并没有变成内存中的数据,只是库或者名字而已,内存中的数据并没有加载到内存,没有加载到内存便无法读取里面的内容,那我们又应该如何将这些数据加载到内存中呢?

内存映射

内存映射是将文件的内容直接映射到内存中的技术,这样就可以直接访问文件的内容,而无需将其加载到内存中。内存映射对于大文件非常有用,因为可以避免将整个文件加载到内存中,从而节省内存空间。

dyld使用内存映射来将库文件映射到进程的地址空间中。当一个进程请求加载一个库时,dyld会先检查库是否已经加载。如果库已经加载,则会直接返回库的地址。如果库尚未加载,则dyld会将库映射到进程的地址空间中。

动态链接库

动态链接库(Dynamic Link Library,DLL)是一种共享库,它可以被多个进程同时加载和使用。动态链接库的好处在于,它可以节省内存空间,因为多个进程可以共享同一个动态链接库。此外,动态链接库还可以方便地更新,因为不需要重新编译和链接整个程序。

dyld使用动态链接库来加载库。当一个进程请求加载一个库时,dyld会先检查库是否已经加载。如果库已经加载,则会直接返回库的地址。如果库尚未加载,则dyld会先将库映射到进程的地址空间中,然后将库中的符号解析到进程的符号表中。

符号解析

符号解析是将符号名称解析为符号地址的过程。符号可以是函数、变量或数据结构。当一个进程调用一个函数或访问一个变量时,需要先解析该符号的地址,然后才能调用该函数或访问该变量。

dyld使用符号解析表来解析符号。符号解析表是一个包含所有符号名称和地址的表格。当一个进程请求解析一个符号时,dyld会先在符号解析表中查找该符号的地址。如果找到,则直接返回该地址。如果没有找到,则dyld会尝试在库中搜索该符号。如果在库中找到该符号,则会将其添加到符号解析表中,然后返回该地址。

重定位

重定位是将符号地址更新为正确的地址的过程。当一个进程加载一个库时,库中的符号地址可能与进程的地址空间中的地址不同。这是因为库可以在不同的地址空间中加载。为了解决这个问题,需要将库中的符号地址更新为进程的地址空间中的地址。

dyld使用重定位表来重定位符号地址。重定位表是一个包含所有需要重定位的符号地址和新的地址的表格。当一个进程加载一个库时,dyld会先将库中的符号地址添加到重定位表中。然后,dyld会遍历重定位表,并将符号地址更新为进程的地址空间中的地址。

GOT表

全局偏移量表(Global Offset Table,GOT)是一个包含所有外部符号地址的表格。外部符号是指在当前模块中定义的但不在当前模块中实现的符号。当一个进程调用一个外部函数或访问一个外部变量时,需要先从GOT表中获取该符号的地址,然后才能调用该函数或访问该变量。

dyld在加载库时会创建GOT表。GOT表是一个只读的表格,它包含所有外部符号的地址。当一个进程调用一个外部函数或访问一个外部变量时,需要先从GOT表中获取该符号的地址,然后才能调用该函数或访问该变量。