链接器和架构
为什么我们有不同架构的链接器?链接器的服务是解析地址。那么它与目标架构的指令有什么关系呢?
Why do we have linkers for different architectures? Service of the linker is to resolve addresses. So how it is related to the instructions of target architecture?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
原因有很多很多,我无法一一列举。
当架构不支持位置无关代码时,链接器需要做更多的工作。在这些情况下,甚至函数内的跳转也需要解决。
链接器需要创建特定于体系结构的标头,例如 ELF 或 PE 标头。
链接器需要在支持它们的平台上包含资源、数据分叉或类似的东西
链接器需要实例化导出的C++模板< /p>
链接器还需要处理尚无法解析的地址。这可以包括系统调用或动态加载的库。
链接动态库时,链接器需要导出多个入口函数。不同的体系结构使用不同的方法来指示要导出哪些函数
如果在编译时无法确定,链接器可能需要插入实际的调用序列。例如,对于支持两个指令集的体系结构,只要调用者和被调用者所使用的指令集不同,就需要插入“指令集开关”。
链接器优化可以基于架构相关的细节。例如,如果 4KB 区域内的函数调用速度更快,则将调用者和被调用者放在一起是有意义的。
可以完成跨对象文件的内联,但需要删除调用设置、被调用者序言、被调用者结尾和返回值处理。这些是特定于体系结构的,因此仅识别它们就需要特定于体系结构的链接器。
There are many, many reasons, and I cannot exhaustively list all of them.
Linkers need to do a whole lot more work when an architecture does not support position-independent code. In those cases, even jumps within functions need to be resolved.
Linkers need to create architecture-specific headers, such as ELF or PE headers.
Linkers need to include resources, data forks or similar things on platforms that support them
Linkers need to instantiate exported C++ templates
Linkers also need to deal with addresses that cannot be resolved yet. This can include system calls, or dynamically loaded libraries.
When linking a dynamic library, a linker needs to export more than a single entry function. Different architectures uuse different methods to indicate which functions are to be exported
Linkers may need to insert the actual call sequences if they cannot be determined at compile time. E.g. for architectures that support two instruction sets, an "instruction set switch" needs to be inserted whenever the caller and callee differ in instruction set used.
Linker optimizations can be based on architecture-dependent details. E.g. if function calls within a 4KB region are faster, it makes sense to put caller and callee close together.
Inlining across object files can be done, but requires removal of the call setup, callee prolog, callee epilog and return value handling. Those are architecture-specific, so just recognizing them already takes an architecure-specific linker.
不同的体系结构在其指令中具有不同的地址格式,链接器必须知道这些地址格式才能操作它们。
根据相对地址的大小,相对寻址可能会导致不同的指令。
还存在更复杂的方案,例如针对 ARM 的方案。
通常它在链接器格式规范的补充中进行描述,例如查看从 这篇关于 ELF 格式的维基百科文章。
Different architectures have different address formats in their instructions which the linker has to know in order to manipulate them.
Relative addressing may lead to different instructions depending on the size of the relative address.
More complicated schemes also exist, for example for ARM.
Usually it is described in a supplement to the specification of the linker format, for example take a look at the documents linked from this Wikipedia article on the ELF format.
要解析地址,链接器至少需要知道地址的字节序和大小。某些体系结构(例如 x86 实模式)具有相当复杂的寻址方案,某些体系结构在指令中嵌入地址,因此链接器可能需要知道地址或偏移字段。
To resolve addresses the linker needs at least to know the endian-ness and size of addresses. Some architectures such as x86 real-mode have rather more complex addressing schemes, some embed addresses in the instruction, so the linker may need to know the address or offset field.
可以构建一些链接器来理解多种体系结构。例如,我在交叉编译器项目中使用 gnu ld、gdb、binutils 和汇编器,http://ellcc.org。我有一个针对每个目标的汇编器,但链接器、调试器和 binutils 都可以理解所有处理器。支持的处理器多种多样:ARM、CellSPU、Mips、MSP430、Nios2、PIC16、PowerPC、PowerPC64、Sparc、X86、X86_64。
Some linkers can be built to understand multiple architectures. For example, I use gnu ld, gdb, binutils, and assemblers for my cross compiler project, http://ellcc.org. I have an assembler specific for each target, but the linker, debugger, and binutils all understand all the processors. The supported processors are pretty varied: ARM, CellSPU, Mips, MSP430, Nios2, PIC16, PowerPC, PowerPC64, Sparc, X86, X86_64.
一些工具链的构建使得大部分优化被推迟到链接时,当整个程序信息可用时。内联、常量传播和许多其他传统优化的好处在应用于整个二进制文件而不仅仅是每个对象时最适用。
Some toolchains are built such that a huge portion of optimizations are deferred to link-time, when whole-program information is available. The benefits of inlining, constant propagation, and many other traditional optimizations, are all most applicable when applied to the entire binary, and not just each object.