前面有篇文章分析了ELF格式,也只是让我们对目标文件有了一个大概的了解,并没有说明一个十分重要的问题:重定位,今天重新看了下重定位的资料,终于弄懂了重定位的过程,下面来做一个分析。
我们将使用下面两个源代码中的文件a.c和b.c展开分析:
//a.c
extern int shared;
int main()
{
int a=100;
swap(&a,&shared);
}
//b.c
int shared=1;
void swap(int *a,int *b)
{
*a^=*b^=*a^=*b;
}
使用命令:gcc -c a.c b.c生成两个可重定位目标文件a.o和b.o,下面就要使用链接器将a.o和b.o链接起来生成执行文件ab,我们分析的就是这个过程。
1.链接的过程
现在的链接器一般都是两步链接,也就是说整个链接过程分两步。
1)符号解析,主要使用ELF里面的符号表节来完成,不做描述。
2)重定位:一旦链接器完成符号解析这一步,它就把代码中的每个符号引用和定义联系起来。在此时,链接器就知道它的输入目标文件中的代码节和数据节的确切大小。现在就可以重定位了,在这个步骤中将合并输入模块,并为每个符号分配运行时地址。重定位由两步组成:
- 重定位节和符号定义:在这一步中,链接器将所有相同类型的节合并为同一类型的新的聚合节。例如输入文件a.o的.text节和b.o中的.text节合并为可执行文件ab中的.text节。然后链接器将运行时存储器地址赋值给新的聚合节。当这一步完成时,程序中的每个指令和全局变量都有唯一的运行时存储器地址。
- 重定位节中的符号引用:在这一步中,链接器修改代码节和数据节中对每个符号的引用,试的他们指向正确的运行时地址。为了执行这一步,链接器依赖于重定位条目。稍后我们来重点分析这一步骤的具体实现过程。


OFFSET TYPE VALUE
0000001c R_386_32 shared
00000027 R_386_PC32 swap
1f: 00

3389



被折叠的 条评论
为什么被折叠?



