静态链接

大多数编译系统提供编译器驱动程序( compiler driver ),它代表用户在需要时调用语言预处理器、编译器、汇编器和链接器。比如 GCC (GNU Compiler Collection) GUN编译器套件,其中 GUN 是一个开源组织,而 GCC 是他们开发的一款编译器套件,应用十分广泛。

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

链接前 —— 预处理、编译

C 的源代码。在编写出来后是不能直接被运行的 —— 其实在完成编写后只是一个文本文件而已。

complie.jpg

源代码需要经过:预处理、编译和汇编这一过程后产生目标文件

  • 预处理 :在这个阶段会对源代码进行插入修改等。主要进行:头文件的插入(#include)、宏的替换(#define)、根据条件编译指令(#ifdef#ifndef#else#elif#endif)过滤掉没必要的代码和识别特殊符号进行替换。
  • 编译:主要是由编译器完成。主要经过:词法分析、语意分析和中间代码生成。一般来说会输出汇编代码
  • 汇编:主要是汇编器完成。输入是有编译器输出的中间文件 —— 主要为汇编代码,输出机器语言文件。

目标文件格式

在介绍链接之前需要对链接的目标 —— 目标文件,的格式有所了解才可以清晰的理解链接的过程。

每个操作系统都有自己的目标文件的格式。这里便于理解主要采用 Linux 系统下的目标文件 ELF(Executeable Linkable Format) 做介绍。

程序的本质就是对数据的处理。所以一段程序可以分成两大部分:数据和指令。其中指令就是代表对数据的操作。所以在 ELF 中是分节储存的。如图:

elf_format.jpg

上图中除了* File Header (文件头)以外,还有 .text section.data section* 和 .bss section

当然上图只是简化版的其中还有许多的其他的节,为了便于理解就省略了其他的节 。

其中 File Header 它描述了整个文件的文件属性,包括文件的类型,以及目标操作系统的信息等。其中有一个重要的信息就是节表节表保存了各个 节的位置以及属性等节的信息。

.text 节 (.text section) 保存了执行语句的机器代码。.data 节 (.data section) 保存了已经初始化的全局变量和局部静态变量。.bss节(.bss section) 保存了未初始化的全局变量和局部静态变量。所以总体来说,程序源代码被编译以后主要分成两种段:程序指令和程序数据。.text 属于程序指令,而 .bss.data属于程序数据。

除了图中出现的节以外,目标文件还会包含一个符号表。符号表包含了该模块所定义和引用的所有符号。

符号:每个符号对应于一个函数、一个全局变量或一个静态变量(在C语言中用 static 申明的变量)。

链接

链接主要由链接器完成。链接器主要有两大任务:

  • 符号解析:将每个符号引用正好和一个符号定义关联起来
  • 重定位:编译器和汇编器生成的是地址从0开始的代码和数据。通过把符号定义与一个确切的内存地址相关联,从而修改这个符号引用的地方指向与其符号定义相关联的内存地址。

符号解析

符号表是由汇编器构造的,使用编译器输出到汇编语言.s 文件中的符号。每个系统上符号表的数据结构都是不同的。

链接器解析符号引用的方法是讲每个引用与它输入的目标文件的符号表中的一个确定的符号定义关联起来。

对于多重定义的全局符号,链接器有他们自己的规则来处理多重定义的符号名比如:

  • 不允许有多个同名的强符号
  • 如果有一个强符号和多个弱符号同名,那么选择强符号
  • 如果有多个弱符号同名,那么从这些若符号中任意选择一个

强符号:函数和已经初始化的全局变量
弱符号:未初始化的全局变量

当链接器解析和静态库相关的符号时,链接器会创建:文件集合E、未解析符号集合U和已定义符号集合D。

  1. 对于输入的文件f进行判断是目标文件还是存档文件(库文件):如果f是目标文件,那么链接器吧f添加到E,在根据f中的符号引用的关系来修改U和D。
  2. 如果f是一个存档文件(库文件),那么链接器就尝试匹配U中未解析的符号和有存档文件(库文件)成员定义的符号。如果存档文件(库文件)中某个成员m,定义了U集合中的符号,那么就将m添加到E中,根据m的符号来修改U和D集合。对于存档文件(库文件)中的所有成员进行以上的操作,知道U和D集合都不在改变,这个时候将没在E集合中的成员丢弃。
  3. 当链接器完成所有文件上的扫描以后,如果U集合是非空的话那么就输出错误链接终止。如果是空的那么就合并和重定位E集合中的文件,构建输出的可执行文件。

重定位

在完成了符号解析以后,此时,链接器就知道了整个模块的确切大小。那么就可以开始重定位步骤,这个步骤主要由两个部分组成:

  • 重定位节和符号定义:合并各个模块中相同的节合并为同一类型的聚合节 。以及吧运行时内存地址赋给新的聚合节和模块中的给个符号。
  • 重定位节中的符号引用:链接器修改代码节和数据节中对每个符号的引用,使得它们指向正确的运行时地址。

之前介绍过,在编译器生成目标文件时候,有许多不同的数据节和代码节用来存放不同的代码和变量等。比如: .data 节是用来存放已经初始化的全局和静态变量,.text 节是用来存放已编译的程序的机器代码,.bss 节是存放未初始化的全局变量和静态变量。而在重定位节和符号定义的步骤中,链接器会吧各个目标模块的这些数据节和代码节合并成一个数据节或者是代码节。如多个 .data 节会合并成一个 .data 节。同时在这个步骤中链接器也会赋给输入模块定义的每个符号给地址,这样到这一步骤完成时,程序中的每条指令和全局变量都有唯一的运行时内存了。

在所有的符号都有了唯一的运行时内存后,接下来就是要替换掉相关的符号引用的以地址来代替了。在汇编器生成目标模块的时候任何对外部符号的引用的地方都会生成一个叫重定位的条目,而链接器则会根据这个重定位的条目来替换想对应得地址。这就就合并成了一个可执行文件。

到此为止,静态链接的部分已经完成。剩下的就是把可执行文件装载进内存然后运行。同时动态链接和静态链接也是不同的。

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

推荐阅读更多精彩内容