链接时的静态绑定

本文详细解释了C++中的延迟绑定(latebinding)和静态绑定(staticlinking),以及它们如何在编译器生成的目标文件中通过存根和跳转指令实现函数调用。讨论了符号导入表和导出表在链接过程中的作用,以及链接器如何通过这些表来确保正确解析和定位函数地址。
摘要由CSDN通过智能技术生成

“延迟绑定”(late binding)或“静态绑定”(static linking)。这种技术在编译器生成的目标文件(.obj)中使用“存根”(stub)或“跳转指令”(jump instruction)来代替直接的函数调用。

当编译器编译一个源文件时,它会生成目标文件(obj文件),其中包含了函数的实现和对其他函数的调用。对于调用的函数,编译器可能不知道被调用函数的最终地址,因为这些函数可能定义在其他源文件中,或者可能是外部库的一部分。在这种情况下,编译器会在调用点插入一个存根,通常是一条跳转指令(如 `jmp`),指向一个临时的、未知的目标地址。

符号导入表和符号导出表

在C++中,符号导入表(Import Table)和符号导出表(Export Table)是在编译和链接过程中用于管理全局符号(如函数和全局变量)的机制。这些符号表确保了在多个编译单元和库之间的正确链接和引用。下面详细介绍这两个概念:

符号导出表(Export Table)

  1. 目的:符号导出表是动态链接库(DLLs或shared libraries)的一部分,它列出了库中所有  可供外部引用的符号。这些符号可以是函数、变量或其他数据结构

  2. 作用:当其他程序或库需要使用这些符号时,链接器会查找导出表以确定符号的位置和内存地址。

符号导入表(Import Table)

  1. 目的:符号导入表是可执行文件或静态库的一部分,它列出了程序需要从其他库或外部定义中引用的所有符号。

  2. 作用:链接器使用导入表来解析程序中的外部符号引用。在程序运行时,动态链接器(如Windows的DLL加载器或类Unix系统的ld-linux.so)会加载相应的动态链接库,并根据导入表中的信息将符号地址填充到程序的地址空间中。

链接过程

在链接过程中,链接器(linker)负责处理符号导入表和导出表,以确保所有符号引用都能正确解析。链接器会查找导出表中与导入表中的符号相匹配的条目,并更新导入表中的符号地址。

如果一个符号在多个地方定义,或者在导入表中找不到对应的符号,链接器会产生错误。多重定义会导致链接错误,因为链接器无法决定使用哪个定义。未定义的引用则意味着链接器找不到任何匹配的符号定义,可能是因为缺少相应的库或拼写错误。

因为.obj与.exe的格式是一样的,在这样的文件中有一个符号导入表和符号导出表(import  table和export  table)其中将所有符号和它们的地址关联起来。这样连接器只要在test.obj的符号导出表中寻找符号f(当然C++对f作了mangling)的地址就行了,然后作一些偏移量处理后(因为是将两个.obj文件合并,当然地址会有一定的偏移,这个连接器清楚)写入main.obj中的符号导入表中f所占有的那一项即可。

链接

在链接阶段,链接器的作用是将多个目标文件合并成一个可执行文件(.exe)。链接器有一个符号表(symbol table),其中包含了每个目标文件中定义和引用的符号(如函数名和变量名)及其地址。链接器会查找每个引用的符号的地址,并更新跳转指令的目标地址。

如果在test.cpp中写f()函数的实现,在main.cpp中调用f()函数,连接器会在 `test.obj` 的符号导出表中查找函数 `f` 的地址。由于C++会对函数名进行名称修饰(name mangling),链接器会根据名称修饰规则找到正确的函数符号。一旦找到,链接器会计算出正确的地址,并将其写入 `main.obj` 的符号导入表中对应 `f` 的条目里。

这个过程确保了所有的函数调用都指向正确的地址,即使在多个目标文件合并时地址发生了变化。这种技术的使用简化了链接过程,并允许在不同的目标文件之间共享代码,而不需要担心地址的偏移问题。

编译main.cpp时,编译器不知道f的实现,所以当碰到对它的调用时只是给出一个指示,指示连接器应该为它寻找f的实现体。这也就是说main.obj中没有关于f的任何二进制代码。

编译test.cpp时,编译器找到了f的实现。于是f的实现(二进制代码)出现在test.obj里。

连接时,连接器在test.obj中找到f的实现代码(二进制)的地址(通过符号导出表)。然后将main.obj中悬而未决的call  XXX地址改成f实际的地址。

参考文章:http://t.csdnimg.cn/e3yQm

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值