简单说,链接器就是把符号表绑定到地址。
本文是对戴铭专栏中“链接器:符号是怎么绑定到地址上的”的小结。
1 编译型语言、解释型语言
编译型,执行效率高,调试周期长
解释型,调试方便,执行效率地
2 LLVM,苹果使用的编辑器工具集合
2-1 lld项目,是内置的链接器
2-2 编译器编译每个文件,生成Mach-O
Mach-O可执行文件,包括
代码
(函数定义)和数据
(全局变量的定义、初始值)
2-3 链接器将多个Mach-O合并成一个
- 完成变量、函数符号 -> 地址的
绑定
2. 多文件链接时,会检测命名冲突
- 生成最终Mach-O时,自动
去掉没有被调用的函数、变量
3 动态库和静态库的链接
3.1 静态库的链接:编译时链接进项目的Mach-O
静态库修改后,整个项目需要重新编译一次
3.2 动态库dylib的链接:运行时通过dyld链接
3.2.1 dyld工作流程
- 系统上的动态链接器,使用了共享缓存
- 加载Mach-O时,首先检查缓存。
- 每个进程,会在自己的地址空间映射这些共享缓存
3.2.2 一个dylib的实际链接和加载流程
3.2.2.1 链接
链接最后,iOS会用ASLR做地址偏移,避免攻击
3.2.2.1.1 dyld方式加载
编译时参与Mach-O的链接
3.2.2.1.1 通过dlopen/dlsym的方式加载
- 编译时不进行Mach-O链接
2. 项目的Mach-O中只有动态库的名字、路径、符号名
3. 项目的Mach-O中不包含动态库的符号表
苹果会限制这种App上线
3.2.2.2 加载
- 加载动态库
- 填充(绑定)项目Mach-O的符号表中undefined的部分
- 处理动态库中的load函数等
- 如有依赖的库,递归加载依赖
3.3 命令行工具 xcrun
- 可以查看.o文件的链接情况
- 可以链接.o文件