定义了_start且无库依赖的目标文件,为何仍需链接才能执行?
单个自包含汇编程序的链接器作用说明
链接器即使处理单个完全自包含的目标文件,也会完成以下核心工作:
- 转换ELF文件格式类型
汇编生成的hello.o属于可重定位目标文件(ELF头中类型标识为ET_REL),这类文件的设计定位是作为链接过程的输入,操作系统内核的程序加载器并不支持直接执行该类型的文件,这就是直接运行.o文件会报格式错误的根本原因。链接器会将其转换为符合执行要求的可执行ELF文件(默认静态链接下类型为ET_EXEC,开启位置无关编译时为ET_DYN)。 - 完成虚拟地址分配与重定位
汇编阶段汇编器无法确定代码、数据最终被加载到内存的虚拟地址,比如示例代码里mov $message, %rsi这条指令,汇编时message的运行时地址是未知的,汇编器会在目标文件中留下对应的重定位条目等待后续处理。链接器会为.text(代码段)、.rodata(只读数据段)等所有段分配运行时的虚拟地址空间,同时遍历所有重定位条目,把指令、数据中所有未确定的地址引用替换为最终的虚拟地址,还会统一规整各个段的权限、对齐属性,比如代码段设置为可读可执行、只读数据段设置为可读不可写不可执行,符合操作系统内存映射的安全要求。 - 设置程序入口点
可执行ELF的文件头中存在e_entry字段,存储程序启动后执行的第一条指令的虚拟地址。链接器会识别代码中通过.global _start声明的全局入口符号,将_start的最终虚拟地址填入e_entry字段,操作系统加载程序完成后就会从这个地址开始执行指令,而可重定位目标文件的该字段是未初始化的。
内容的提问来源于stack exchange,提问作者Him
相关产品推荐
相关产品推荐

