无编译器构建AArch64 ELF:sys_write无输出问题求助
问题原因与解决办法
1. 数据未被映射到进程地址空间
你提到"hello world"从文件偏移98开始,但如果这个区域没有被包含在ELF的**程序头(Program Header)**的加载段中,ELF加载时这部分数据不会被映射到进程的虚拟内存空间。此时你给r1传入的地址(无论是文件偏移还是自行计算的虚拟地址)都是无效的,内核执行sys_write时读不到数据,自然没有输出。
x86_64中你可能把数据和代码放在同一个加载段里实现正常映射,但AArch64的加载逻辑严格遵循程序头定义,必须明确标记哪些文件区域需要被加载到内存。
2. 代码段权限限制(若数据嵌入代码段)
即便你把数据和代码放在同一个加载段,AArch64用户态内存页权限通常会把代码段设为可读可执行(PF_R | PF_X),部分环境下甚至会设为仅执行。如果是后者,从代码段读取数据会触发内存访问错误,若你未处理错误直接调用sys_exit,程序看似正常退出,但sys_write实际已失败。
3. 地址加载方式错误
AArch64的MOV指令无法直接加载64位完整地址,若你用MOV把文件偏移98直接写入r1,这个值是文件偏移而非进程虚拟地址,必然无效。正确做法是:
- 计算数据的虚拟地址:根据程序头的加载基址(
p_vaddr)和数据在加载段内的偏移得出。比如代码段加载到0x400000,数据在代码段文件偏移0x62(98的十六进制),则虚拟地址为0x400000 + 0x62。 - 使用
ADRP + ADD组合加载地址:这是AArch64加载全局地址的标准方式,ADRP加载地址的页基址,ADD加上页内偏移得到完整地址;也可使用PC相对寻址的LDR指令(注意偏移范围为±1MB)。
具体修正步骤
- 调整ELF程序头:确保包含数据区域的加载段,标记权限为
PF_R | PF_W(可写数据)或PF_R(只读数据),并正确设置p_offset、p_vaddr、p_filesz、p_memsz字段。 - 拆分代码与数据:把"hello world"放到单独的
.data段,或和代码段放在同一加载段但确保权限允许读取。 - 正确加载数据地址:用ADRP+ADD生成数据虚拟地址到X1寄存器,示例汇编(对应机器码需自行转换):
ADRP X1, hello ; 加载hello所在页的基址到X1 ADD X1, X1, #:lo12:hello ; 加上页内偏移,得到完整地址 - 验证sys_write参数:确保X0=1(标准输出)、X1=数据虚拟地址、X2=字符串长度(比如"hello world\n"为12字节),再触发系统调用(AArch64用
SVC #0)。
内容的提问来源于stack exchange,提问作者ton
相关产品推荐
相关产品推荐

