链接器和加载器做什么?
任何一个链接器和加载器的基本工作都非常简单:将更抽象的名字与更低层的名字绑定起来,好让程序员使用更抽象的名字编写代码。
地址绑定:从历史的角度
编译时绑定
链接时绑定
加载时绑定
运行时绑定
都是为了节省代码。
虚拟内存的出现,使分段出现?动态链接库的出现。
链接器与加载器完成几个相关但概念上不同的动作。
程序加载:将程序从辅助存储设备拷贝到主内存中准备运行。分配存储空间,设置保护位,或通过虚拟内存将虚拟地址映射到磁盘内存页上。
重定位:汇编器为每个文件创建程序地址从0开始的目标代码,但是实际情况是会被加载到不同的地址,调整程序中的数据和代码以反映所分配地址的过程。
典型的过程是:多个子程序构建一个程序,并生成一个链接好的起始地址为0的输出程序,各个子程序通过重定位在大程序中确定位置。当这个程序被加载时,系统会选择加载一个地址,而链接好的程序作为整体被重定位到加载地址。
(是的,这就是我寻找的流程。)
符号解析:就是call的问题,这个符号表必须保留,(call,可以call一个间接地址是实现动态链接库的方法,问题是为什么程序不在加载的时候binding动态库,不可以吗?明明可以的。)
一个仅完成程序加载和重定位的程序为加载器。
一个仅完成符号解析和重定位的程序为链接器。
意思是说:一切皆引用,重定位也是地址引用基地址。
两趟链接:
链接器接受输入文件,产生输出文件,有时候还有其他的文件。
两趟链接,第一趟对输入文件进行扫描,得到各个段的大小,并且收集对所有符号的定义和引用。他会创建一个列出输入文件中定义所有段的段表,和导入导出符号的符号表,链接器可以为符号分配数字地址,决定各个段在输出地址空间中的大小和位置,并且确定布局。
第二遍扫描利用第一遍扫描中收集的信息来控制实际的链接过程。目标代码库,重定位和代码修改。