欢迎访问我的个人博客: luomuxiaoxiao.com
在 可执行文件详解详细的介绍了可执行文件的各个section的内容和功能,但是唯独
.text
section没有被提到。其实
.text
section的内容,我们在上一篇文章
Linux X86 程序启动 – main函数是如何被执行的?中已经分析的很详细了。这篇文章将从链接的角度来探讨
.text
的指令的生成过程,尤其是引用到外部动态链接库代码的指令生成过程。
一、 静态链接和动态链接
链接过程实际上是把多个可重定位文件合并成一个可执行文件的过程。这个过程中最重要的两个步骤是符号解析和重定位。所谓的符号解析,就是将符号的定义和引用关联起来,而重定位就是给所有符号和指令添加运行时的地址的过程。这个两个过程具体来讲就是:
- 符号解析,就是根据编译器生成的可重定位文件中的符号表,来使符号定义和符号引用一一对应并关联。
- 重定位,就是将每个符号和内存中的一个位置关联起来,然后修改代码中所有对这些符号的引用,使它们指向这个内存位置。
很多时候我们可能会复用多次某个函数或者某个模块,如果每次都需要把它对应的代码找出来,然后重新编译的话,这样效率是很低的。静态链接库的出现正好解决了这个问题。其基本原理是,将常用的函数或者模块单独编译成其对应的可重定位文件,然后再将其封装成一个单独的.a文件(静态链接库)。在链接的时候,根据解析的规则把使用到的模块打包到最终生成的可执行文件内。这个过程称为静态链接。但是,这样同时带来了两个问题:
- 如果更新了某个静态库,那么必须重新链接该可执行文件。
- 如果每个可执行程序都把库函数的代码复制到内存中其对应进程的文本段,那么这将是极大的浪费。
于是,动态链接库应运而生。动态库在编译时使用了位置无关码,在运行和加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来。动态链接的过程有别于静态链接,在创建可执行文件时,动态链接库的代码并未被复制到可执行文件中,而只是复制了一些符号表和重定位信息,而在运行时,要先执行动态链接,加载动态链接库的文本段和代码段到内存,修改符号表和重定位信息,然后再继续执行真正的可执行文件的代码段。
二、可执行文件代码段
本篇文章仍然使用上篇文章中的add.c
和main.c
作为研究对象,分别研究静态链接和动态链接生成可执行文件的代码段的区别。由于在代码中使用到了libc库的库函数printf,这里的静态链接和动态链接指的就是静态链接或者动态链接libc库。
2.1 编译方法
想第一时间查看我的文章吗?请关注我的微信公众号号,搜索“落木萧萧技术论坛”或登陆我的个人博客:www.luomuxiaoxiao.com,更多精彩文章等你。