前言
链接这个操作分为两个部分 :
- 符号解析
- 重定位
简单点说就是找到符号(如何找呢??通过符号表找到) ,然后将正确的地址填上
文章先从符号到符号解
回顾链接过程
符号的类型及相关的段
链接符号的类型
包括三种类型
- 全局符号 ,里面还分强弱
- 外部定的全局符号
- 本模块的局部符号
可以看一下下面的例子
目标文件中的符号表 (.symtab)
符号表是一个 section (段),我们在前面介绍 ELF 段结构的时候是有看到这个段的 , 符号表的结构包含了符号的各种属性, 什么类型的, 在哪个地方,多大, 叫什么名字
全局符号分类
分强弱
符号解析
再介绍符号解析之前我们先介绍一下静态库 ,原因是我们现在写的程序都会用到这东西
什么是静态库
静态库的创建
常用的静态库
自定义静态库
符号解析-解析规则
最终的目标就是将代码中的地址替换成正确的地址或是数值 ,根据以下的规则进行解析
这个规则有时候在一些复杂的场景会解析出"意想不到的结果" ,看下面的例子
符号解析-解析过程
看目的这一行 , 这一步会将引用符号
和目标模块的符号
相关联
下面是解析的过程 , 用了三个集合, 目的就是给引用找到对应的地址 , 注意我们用的实例是上面 自定义静态库章节
里的例子
需要注意的是符号解析还需要注意顺序 ,例如 :
额 ,有点不智能吧
重定位
回顾
用到的例子代码
main.c
int buf[2] = {1, 2};
void swap();
int main()
{
swap();
return 0;
}
swap.c
extern int buf[];
int *bufp0 = &buf[0];
static int *bufp1;
void swap()
{
int temp;
bufp1 = &buf[1];
temp = *bufp0;
*bufp0 = *bufp1;
*bufp1 = temp;
}
重定位表
重定位就是将那些符号定义和符号引用替代掉 ,那么要去"去代替"这个动作需要知道 ,将要替代的符号在哪里 ,应该替换成那种类型 ,替代成什么这些信息 ,而
这些信息就记录在重定位表中
重定位过程
从上面这张图我们可以知道 main 长度占了12个字节.
根据前面的重定位表我们可以看到, 这个地方重定位的类型是相对定位
, 需要替代的符号是 swap
, 相对指的是相对于当前之前的偏移量 . 我们给出一个假设然后推理出一个相对定位的过程
而绝对位置定位就简单多了, 说白了就是那个符号的地址在哪里就是那里
总结
该篇介绍了符号表和符号解析 ,以及重定位相关的知识 ,主要是学习的课件 .
参考
- <<程序员的自我修改--链接,装载与库>> 书
- mooc上袁春风老师的课