为何使用-pie选项链接的汇编程序存在却无法运行?
问题原因与解决方案
这个问题的核心是位置无关可执行文件(PIE)的寻址要求和你汇编代码里的绝对地址引用不兼容,导致动态链接器无法正确加载程序,系统给出了误导性的"No such file or directory"提示(实际是加载失败,不是文件真的不存在)。
为什么会出现这个问题?
当你给ld加上-pie选项时,会生成一个位置无关的可执行文件——这类程序在运行时会被加载到内存的随机基地址,而不是固定地址。但你的原代码里:
mov rsi, message ; address of string to output
这里直接使用了message的绝对地址,在PIE模式下,这个绝对地址是无效的(因为程序加载地址随机,原绝对地址不再对应实际数据位置),动态链接器无法解析这个地址,导致加载失败,系统就抛出了看似无关的文件不存在错误。
如何修复?
你需要改用相对RIP的寻址方式来访问message,也就是用lea指令配合rel前缀,修改代码中的这一行:
lea rsi, [rel message] ; 用相对RIP寻址获取message的地址
修改后的完整代码如下:
global _start section .text _start: mov rax, 1 ; system call for write mov rdi, 1 ; file handle 1 is stdout lea rsi, [rel message] ; 改用相对RIP寻址 mov rdx, 13 ; number of bytes syscall ; invoke operating system to do the write mov rax, 60 ; system call for exit xor rdi, rdi ; exit code 0 syscall ; invoke operating system to exit section .data message: db "Hello, World", 10 ; note the newline at the end
现在再执行你的编译链接命令:
nasm -f elf64 hello.asm && ld -pie hello.o && ./a.out
就能正常输出Hello, World了。
额外说明
为什么错误提示是"No such file or directory"?这是Linux系统的一个常见误导性提示:当动态链接器无法正确加载一个可执行文件(比如PIE程序存在寻址错误)时,系统会把这种加载失败的情况上报为文件不存在,而不是更准确的加载错误。你可以用ldd ./a.out命令查看原错误版本的a.out,会发现动态链接器无法解析依赖,这也能佐证问题所在。
内容的提问来源于stack exchange,提问作者L. Ouyang
相关产品推荐
相关产品推荐

