【发布时间】:2009-11-05 09:05:32
【问题描述】:
为什么我们有不同架构的链接器?链接器的服务是解析地址。那么它与目标架构的指令有什么关系呢?
【问题讨论】:
为什么我们有不同架构的链接器?链接器的服务是解析地址。那么它与目标架构的指令有什么关系呢?
【问题讨论】:
原因有很多很多,我不能一一列举。
当架构不支持与位置无关的代码时,链接器需要做更多的工作。在这些情况下,即使是 在 函数内的跳转也需要解决。
链接器需要创建特定于体系结构的标头,例如 ELF 或 PE 标头。
链接器需要在支持它们的平台上包含资源、数据分叉或类似的东西
链接器需要实例化导出的 C++ 模板
链接器还需要处理还不能解析的地址。这可以包括系统调用或动态加载的库。
链接动态库时,链接器需要导出多个入口函数。不同的架构使用不同的方法来指示要导出哪些函数
如果在编译时无法确定,链接器可能需要插入实际的调用序列。例如。对于支持两个指令集的架构,只要调用者和被调用者使用的指令集不同,就需要插入一个“指令集开关”。
链接器优化可以基于架构相关的细节。例如。如果 4KB 区域内的函数调用更快,则将调用者和被调用者放在一起是有意义的。
可以跨对象文件进行内联,但需要删除调用设置、被调用者序言、被调用者结语和返回值处理。这些是特定于架构的,因此只需识别它们就需要一个特定于架构的链接器。
【讨论】:
不同的架构在其指令中具有不同的地址格式,链接器必须知道这些地址格式才能操作它们。
根据相对地址的大小,相对寻址可能会导致不同的指令。
还存在更复杂的方案,例如 ARM。
通常在对链接器格式规范的补充中进行了描述,例如查看从this Wikipedia article on the ELF format 链接的文档。
【讨论】:
要解析地址,链接器至少需要知道地址的字节序和大小。某些架构(例如 x86 实模式)具有更复杂的寻址方案,有些会在指令中嵌入地址,因此链接器可能需要知道地址或偏移字段。
【讨论】:
可以构建一些链接器来理解多种架构。例如,我将 gnu ld、gdb、binutils 和汇编程序用于我的交叉编译器项目http://ellcc.org。我对每个目标都有一个特定的汇编器,但链接器、调试器和 binutils 都了解所有处理器。支持的处理器种类繁多:ARM、CellSPU、Mips、MSP430、Nios2、PIC16、PowerPC、PowerPC64、Sparc、X86、X86_64。
【讨论】:
某些工具链的构建使得大部分优化都推迟到链接时间,当整个程序信息可用时。内联、常量传播和许多其他传统优化的好处在应用于整个二进制文件时最适用,而不仅仅是每个对象。
【讨论】: