第七章-链接(1)

链接(linking)

链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载到内存并执行。
链接执行时期:

  • 编译时
  • 加载时
  • 运行时

编译过程:
gcc -Og -o prog main.c sum.c

  • C预处理器(cpp),将C源程序mina.c翻译成一个ACSII码的中间文件。
    cpp main.c /tmp/main.i
  • C编译器(ccl),将main.i翻译成一个ASCII汇编语言文件main.s
    ccl /tmp/main.i -o /tmp/main.s
  • 汇编器,将main.s翻译成一个可重定位目标文件 main.o
    as -o /tmp/main.o /tmp/main.s
  • 链接器,将main.o和sum.o以及一些必要的系统目标文件组合起来,创建一个可执行文件prog:
    ld -o prog /tmp/main.o /tmp/sum.o

调用程序:
./prog
shell调用操作系统中一个叫加载器(loader)的函数,它将可执行文件aprog中的代码和数据复制到内存,然后将控制转移到程序的开头。

静态链接

上面的ld命令就是一个静态链接器,将一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的、可以加载和运行的可执行目标文件作为输出。

目标文件

  1. 可重定位目标文件。包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。
  2. 可执行目标文件。包含二进制代码和数据,其形式可以被直接复制到内存并执行。
  3. 共享目标文件。一种特殊类型的可重定位目标文件,可以在加载或运行时被动态加载进内存并链接。
    1和3都由编译器和汇编器生成,2则由链接器生成。

可重定位目标文件

ELF: 一种目标文件格式,用于现代x86-64 Linux和Unix系统使用的可执行可链接格式(Executable and Linkable Format,ELF)


image.png
  • .text:已编译程序的机器代码。
  • .rodata:只读数据
  • .data:已初始化的全局和静态C变量。
  • .bss:未初始化的全局和静态C变量,以及所有初始化为0的全局或静态变量。这是一个占位符,不分配实际空间,运行时才在内存中分配这些变量,初始值为0。
  • .symtab:符号表,存放在程序中定义和引用的函数和全局变量信息。


    image.png

符号和符号表

符号表 .symtab
符号:

  1. 由模块m定义并能被其他模块引用的全局符号。(不带static属性的C函数和全局变量)
  2. 由其他模块定义并被模块m引用的全局符号,这些符号称为外部符号。
  3. 只被模块m定义和引用的局部符号(带有static属性的C函数和全局变量),这些符号在模块m中任何位置都可见,但是不能被其他模块引用。
    本地链接符号和本地程序变量是不同的。局部变量是不会出现在符号表中的,因为这些都是在运行时在栈中被管理,链接器对此类符号不感兴趣。

符号解析

链接器解析符号引用的方法是将每个引用与它输入的可重定向目标文件的符号表中的一个确定的符号定义关联起来。对那些引用定义在系统模块中的局部符号的引用,符号解析非常简单,因为编译器只允许每个模块中每个局部符号有一个定义。
全局符号则不同,编译器遇到不在当前模块中定义的符号时,会生成一个链接器符号表条目,并交由链接器处理。如果链接器在输入的模块中找不到这个被引用的符号定义,就会输出错误信息并终止。全局符号还可能有相同的名字,所以解析起来也会增加困难。

解析多重定义的全局符号

image.png

与静态库链接

编译系统提供了一种机制,将所有相关目标模块打包成为一个单独得文件,称为静态库(static library),它可以用作链接器的输入。当链接器构造一个输出的可执行文件时,它只复制静态库里被应用程序引用的目标模块。即将许多.o文件打包成一个.a文件,然后将.a文件作为链接器的输入,并从.a文件里面复制被引用的.o模块。
以标准C函数为例(printf, atoi,scanf),如果编译器内置这些函数,那么如果要更新函数,必须要更新编译器。如果将所有函数的.o文件打包成一个.o文件,这样会使得可执行文件占用磁盘与内存空间较大。如果将函数的.o文件单独分开,这样在编译时要输入的.o文件又会太多。
为了解决上面那些问题,就提出了静态库的概念。将所有的.o打包成一个.a文件,链接器只复制用到的目标模块。这样既方便了程序员,也节省了磁盘与内存空间。


image.png

链接器如何使用静态库来解析引用

维护三个集合,可重定位目标文件集合E,未解析的符号U,已定义的符号集合D。

  • 对命令行上每个输入文件f,链接器判断f是目标文件还是存档文件(.a),如果是目标文件,那么把f添加到E中,修改U和D来反映f中的符号定义和引用,并继续下一个文件。
  • 如果f是存档文件,那么尝试匹配U中未解析的符号,如果存档文件某个成员m定义了一个符号来解析U中的一个引用,那么将m当做目标文件对待。一直重复这个过程,当U,D不再发生变化时,丢弃次存档文件的其他成员。继续处理下一个文件。
  • 如果命令行上输入文件扫描完成后,U是非空的,那么就报错(因为有未解析的符号)。否则,合并E中的目标文件,构建出可执行文件。
    所以,目标文件一般放在参数开头,库文件放在参数结尾。如果库文件在开头,那么可能由于U一开始是空的,很多目标文件要用的引用都会被丢弃。导致链接失败。

重定位

完成了链接之后,链接器就知道它的输入目标模块中的代码节和数据节的确切大小。就可以开始重定位的步骤了,在这个步骤中,合并输入模块,并为每个符号分配运行时地址。重定位分为两步:

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

推荐阅读更多精彩内容