程序链接中:符号 和 符号表

发布于:2024-04-27 ⋅ 阅读:(185) ⋅ 点赞:(0)

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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


网站公告

今日签到

点亮在社区的每一天
去签到