1、
- 什么是符号
- 什么是符号的定义,什么是符号的引用
- 链接符号的类型有哪些,各自有什么特点
- 符号表是什么
- 链接器对符号的解析规则
一、
1、 什么是符号?
符号:就是其实程序中的变量名、函数名。
2、什么是符号的定义,什么是符号的引用?
符号的定义:就是程序中变量名、函数名的定义(位于定义位置的 变量名、函数名);
符号的引用:就是程序中变量名、函数名的引用(不在定义位置的 变量名、函数名);
3、 链接符号的类型有哪些,各自有什么特点?
每个可重定位目标模块m 都有一个符号表,它包含了在m中定义和引用的符号,有3种链接器符号:
类型 | 特征 | 举例 |
Global symbols (模块内部定义的全局符号) |
由模块m定义并能被其他模块引用的符号。 例如,非static C函数和非 static的C全局变量(指不带static的函数\全局变量) |
如,main.c 中的全局变量名buf |
External symbols (外部定义的全局符号) |
由其他模块定义并被模块m引用的全局符号 | 如,main.c 中的函数名swap |
Local symbols (本模块的局部符号) |
仅由模块m定义和引用的本地符号。 例如,在模块m中定义的带static的(C函数和全局变量) |
如,swap.c 中的static变量名bufp1 |
注意:1.局部变量temp分配在栈
中,不会在过程外被引用,因此不在符号的类型中;
2. 链接器的局部符号 不是指程序中的局部变量(分配在栈中的临时性变量),链接器不关心这种局部变量;
4、符号表是什么?
目标文件的.symtab节记录着符号表信息,符号表 是一个结构体数组,每个表项(16字节)的结构如下:
使用readelf -s 可查看目标文件的符号表信息,以上面的main.o和swap.o为例:
二、链接器对符号的解析规则
1、首先要知道2个名词(全局符号的强、弱)
强符号 | 函数名 和已初始化 的全局变量名 |
---|---|
弱符号 | 未初始化 的全局变量名 |
2、符号的解析:就是将符号引用和符号定义建立关联后,将引用符号的地址重定位为相关联的符号定义的地址。
三、链接器对符号的解析过程
篇一:
3、若干集合
E 将被合并到一起以组成可执行文件的所有目标文件集合(可执行文件\静态库文件)
U 未解析符号(未不对应定义符号关联的的引用符号)的集合 (符号)
比如说:在一个.o文件用了max(a,b),但是.o文件中却没有找到这个max符号的定义,这个max现在就称作未解析符号。
D 当前已被加入到E的所有目标文件中定义符号的集合(定义符号)
开始E、U、D为空,符号解析过程如下:(扫描文件的顺序:按gcc指令的顺序扫描)
①命令行中文件按照顺序出现,假如现在是f文件,链接器看它是什么文件:
是可重定位目标文件,就将f放到E中,并将f中未解析符号放到U,定义符号放到D。
是静态库文件:链接器尝试把U中所有未解析符号与f中各个目标模块中的定义的符号匹配。如果f中的某个m模块定义了U中的未解析符号x,就将:m放入E,x从U移到D,直到U和D不再变化。又假设f中的模块n,里面的定义符号都没在链接中用到,那么n就被扔了!(随扫随丢)库文件里也有可能存在那种未解析符号,那么就把静态库里的未解析符号也放到U里去。
如图例,处理main.o的时候,先把这个模块放到E中。发现d是定义符号,那么d就加入D,而main.c第8行的d已经被定义了,所以d不会被放到U里面。
②若往D中加入了一个已经存在的符号(双重定义),或扫描完所有文件时U非空,则连接器报错并停止。否则,链接器将生成.o文件,最终U中一定为空,D中符号唯一。
③最终还会自动检索默认库,也是匹配符号的过程。它不需要在 gcc -static 后明显指出。
原文链接:https://blog.csdn.net/qq_39286580/article/details/106516434
二、
静态库的符号解析的过程(重要)
链接器在工作的时候:
首先创建三个集合 E、U、D
- E:合并在一起的所有目标文件(还未重定位)
- U:没有解析的符号(定义符号和引用符号还没有被建立联系)
- D:定义符号的集合
现在来叙述全部过程
- 对每一个输入文件来说,首先判断是不是库文件。
如果不是库文件,就是目标文件 f。就能把目标文件放入 E 中,根据 f 中未解析符号和定义符号判断后分别放入 U、D 中
比如说,f 中有一个未解析符号 k,如果 D 中存在对它的定义,那么就可以建立联系。如果没有就放入 U 中。
- 如果是库文件,会试图把所有 U 中的符号与库文件中的符号匹配,匹配上了就从 U 放入 D 中。并把匹配上的模块放入 E 中。一直重复直到 U D 不再变化。库文件剩下的内容直接就不管了。
- 如果往 D 中放入了一个已经存在的符号或者扫描完所有文件后 U 还是非空,则链接器会停止并报错。否则执行重定位
作者:madao756
链接:https://www.jianshu.com/p/2786533a34c9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。