了解苹果的LD
其实文章关于传统
Section Based Linker
那块我还没怎么读懂,有兴趣的欢迎互相探讨。
之前研究Xcode 10
兼容libstdc++
的时候,稍微把玩了下苹果的LD
,借这个机会正好通读了下苹果的LD
设计,本文做一下总结。
Atom & FixUp
苹果的LD
,核心理念就是基于Atom
和FixUp
,拿着两个术语是啥意思呢?
Atom
就是一块代码(函数)或者数据(全局变量)之类的,每个Atom
都有一些属性,比如名称、作用域、内容类型、字节对齐之类的。Fixup
可以理解为一个包含种类、便宜、辅助加数以及目标Atom
的数据结构。
有点抽象对吧?概要来说,苹果LD
通过Atom
和FixUP
构建一张图,图中的节点都是Atom
,连接Atom
的则是FixUP
。
通过构建这样一张图,苹果就可以在链接期间进行一系列的优化,比如死代码剔除,怎么做呢?比如一段代码也会被抽象成Atom
,如果没有FixUP
连接的Atom
就可以进行剔除
举一个简单的小例子main.c
:
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
会被抽象出如下行为:
单独编译这个.c
文件生成的.o
会包含两个atom
,一个是main
函数,另外一个是C
字符串"hello world"
printf 本质上也会一个
atom
,但是在这个编译单元内他还没加入图中。
而fixup
也存在两个,一个是去调用不知道在哪的函数printf
的调用fixup
,一个是去加载字符串的fixup
。
链接过程
链接过程的第一步就是要处理输入文件,构建一张初始图。
- 如果输入文件是
.o
,那么所有的atom
都会被加入到初始图当中。 - 如果输入文件是静态库(静态库基本上就是一组
.o
文件包含一个目录),初始状态下这里面的atom
都默认不会加入到里面,当LD
不断初始图中有没被决议的fixup
,如果fixup对应的目标atom
在这个静态库里面的话,就会把找到的atom
的加入到图内。 - 动态库其实在链接期间不会添加任何的
atom
,同静态库一样,如果有没被决议的fixup
对应的atom
在动态库内找到(比如tbd
声明的那些),就就提供一个代理,这个代理标记了这个符号来自哪个动态库
- 如果输入文件是
本质上来说,链接期间动态库的作用就是参与标记一下。
考虑完符号决议,还要考虑符号合并之类的,比如根据字符串表的设计,来自不同文件的相同字符串,比如
"haha"
,不可能保留两份,需要合并。此外还有诸如C
中的tentative definitions
,C++ Weak Symbol
等处理
fixup
的时候,也需要分几种类型,见下图:
其他
虽然苹果的LD
已经抽象成了Atom-FixUP
的架构,但是它的可执行文件Mach-O
还是传统的基于section
的结构,这限制了Atom-FixUP
的能力。