(WWDC) Xcode 构建过程的幕后 —— Linker

 

接下来,我们将揭晓以下问题的答案:

  • 链接器(linker)实际上做了什么?
  • 什么是符号(symbols)?
  • 什么是目标文件(object files)?
  • 什么是库(libraries)?

 
 

链接器 (linker)

  • 执行构建可执行 Mach-O 文件的最后任务;

  • 把所有编译器调用的输出整合到单个文件中:

    • 移动和修补编译器生成的代码
  • 输入两种类型的文件:

    • 目标文件 (.o)
    • 库文件 (.dylib, .tbd, .a)

 
 

符号 (symbols)

  • 一个符号是一段代码或者数据的名字;

  • 代码段可能会引用其他的符号;

  • 符号可以具有改变链接器行为的属性:

    • 比如:弱符号(weak symbol)
  • 编程语言通常会编码一些数据到符号,使其成为有"乱码(mangling)"的符号;

 
 

目标文件 (object files)

  • 单个编译器调用的产出物;

  • 一个包含代码和数据片段的不可执行的 Mach-O 文件:

    • 每个代码片段被一个符号代表
    • 代码片段可以引用未定义(undefined)的符号

 
 

库(libraries)

库定义了你的 target 中不包含的符号:

  • Dylibs(Dynamic libraries): 动态库(暴露了可执行程序可以使用的代码和数据的 Mach-O 文件)

  • TBDs(Text Based Dylib Stubs): 基于文本的 Dylib 桩(只包含符号)

  • 静态归档文件(Static archives)

    • 用 "ar" 工具构建的由多个 .o 文件归档而成的文件
    • 只有包含了你已引用的符号的 .o 文件会被包含到你的应用中

 
 

下面,让我们通过一个简单的例子来理解这些内容。

 
 

首先,你已经将 playSound 函数定义在了项目中的某一处,所以这里的定义是没有错误的。

让我们来看一下对应的汇编代码:

 

由于静态常量 purrFile 对于外部不可见,所以忽略这个常量。
最后,purr.aac 这个字符串直接被拷贝到 Cat.o 中:

使用 -[Cat purr] 作为符号表示 Cat 类中的实例方法 purr

有两条指令引用了这个文件名字符串。
arm64 架构下,我们知道完成这个操作只需要两条指令。
这里并没有这个字符串的实际内存地址,因为我们不知道这个字符串最终在可执行程序内存中的位置:

使用 @PAGE@PAGEOFF 来占位,让链接器来更新这个内存地址。

然后,调用 playSound 函数。不过,Cat.o中的汇编代码做了一些编码处理,编码部分包含了函数的参数信息,所以这个函数在汇编代码中不再命名为 playSound

至此,我们已经生成了一个 Cat.o 文件。
事实上,在构建项目时,会有很多 .o 文件生成。

 

那我们如何处理这些 .o 文件呢?
构建系统会把所有的 .o 文件作为链接器的输入,然后链接器会创建一个文件来整合这些输入。

 

现在,让我们来构建 PetWall 应用中的内嵌代码库 PetKit

首先创建一个用于容纳所有应用代码的文本段(text segment)。

然后,把 Cat.o 中的内容复制进去。不过,我们需要把内容分为两部分。
一部分是常量字符串,另一部分是可执行代码。

到这里j,我们已经知道这些数据的内存地址,所以链接器可以通过重写 Cat.o 来从特定的内存地址偏移位置读取内容。
你会发现汇编指令变了。第二条指令变为了 nop,意思是空操作。
因为移除或者创建指令会导致重新计算大小,所以这里使用了空操作来进行替换。

接下来,我们的处理会遇到一个未定义的符号。
而到目前为止,所有的 .o 文件已经被包含进来,所以我们可以去查找这个未定义的符号。
我们首先查找静态归档库(static archives),在 PetSupport.a 中的 PetSounds.o 文件中找到了 playSound 函数。

然后我们把 PetSounds.o 中的内容复制进来。
不过,我们不需要 PetCare.o 中的内容,因为其中不存在项目需要引用的符号。
注意 open$stub 是未定义的。所以在后续的步骤中需要对它进行替换。

继续查找,我们在 libSystem.tbd 系统库中找到了 open 函数的一个副本。

然后,我们需要做一些处理才能使调用成功。
所以,我们添加了一个假的方法,里面包含了模板代码。
我们可以用系统库中的 open 函数替换这个模板方法。

这个方法可以加载一个指针(像C语言里面的指针一样),然后跳到这个指针。
所以,这里我们只需要一个 open 函数的指针即可。

接下来,我们需要在数据段(data segment)中创建这个函数指针,数据段是存储全局变量的地方。
不过,这里被设置为了0。如果我们直接对这个地址取值并跳到这里,程序就会崩溃。

所以,我们需要添加链接编辑段(link edit segment)。
链接编辑是链接工具用来告知操作系统和动态链接器在运行时修复问题的元数据。

想了解动态链接的相关内容,请看这里《Optimizing App Startup Time》

 
 

总结

  • 构建系统:分析依赖,然后利用多核硬件完成构建过程
  • Clang:查找头文件、通过模块来优化编译过程
  • Swift 编译器:查找声明和生成接口
  • Linker:整合所有编译器的输出到可执行程序文件中,在这个过程中 Xcode 会对代码签名打包

 

开源资源:

 
 



参考内容:
Behind the Scenes of the Xcode Build Process

 
 
转载请注明出处,谢谢~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343