arm - 在 GAS 组装的 QEMU 中运行的 ARM64 ELF 可执行文件的对齐要求
问题描述
我有这个 ARM64 程序,当我运行它时它会立即组装但会出现段错误:
// GNU Assembler, ARM64 Linux
.bss
.lcomm ARRAY, 16
.text
.global _start
_start:
mov x8, 93 // exit sys num
mov x0, 0 // success
svc 0
通过蛮力试验和错误,我设法通过添加以下行来修复它:
// GNU Assembler, ARM64 Linux
.bss
.lcomm ARRAY, 16
.p2align 12 // why?
.text
.global _start
_start:
mov x8, 93 // exit sys num
mov x0, 0 // success
svc 0
它仅适用于.p2align 12
(相当于.balign 4096
)或更高,否则它仍然会在值为.p2align 11
或更低的情况下出现段错误。我知道填充可能会解决一些错位问题,但我不明白为什么它必须是这么大的值,因为我见过的几乎所有其他 ARM64 示例,无论是手写的还是由编译器生成的,通常只插入一个.p2align 2
在本.text
节之前,为什么我需要.p2align 12
我的小程序?
此外,我注意到所需的填充大小与部分的长度成反比.text
。对于像上面这样的小程序,.p2align 12
需要让它们在没有段错误的情况下运行,但是.text
部分越长,我可以制作的填充越小,而对于有数千条指令的程序,我根本不需要添加任何填充!
我在 x86_64 macOS 机器上,但我正在从这个 Dockerfile 构建的 Docker 容器内编译和运行这些程序:
FROM ubuntu:20.04
RUN apt-get update && apt-get -y install clang qemu gcc-aarch64-linux-gnu
我正在编译和运行 ARM64 程序:
clang -nostdlib -fno-integrated-as -target aarch64-linux-gnu -s program.s -o program.out && ./program.out
我觉得我错过了一些关于 GAS、QEMU、ARM64 或 ELF 可执行文件的重要信息,但我不知道它是什么。
解决方案
QEMU 对您的数据部分的程序头感到困惑:
LOAD off 0x00000000000000c0 vaddr 0x00000000004100c0 paddr 0x00000000004100c0 align 2**16
filesz 0x0000000000000000 memsz 0x0000000000000010 flags rw-
并且未能在该地址实际映射一些可写内存;当 QEMU 尝试将 BSS 的 memset() 归零时,段错误来自 QEMU 本身。
由于程序在真正的 AArch64 Linux 内核上运行良好,这是一个 QEMU 错误。我已将其报告给上游邮件列表,因此我们将看看是否有人提出解决方案。
推荐阅读
- android-studio - 未安装 Flutter 和 dart 插件
- azure - 为什么 azure-api 不显示构建相关的工作项?
- python - 更改按钮状态
- javascript - 反应原生,从文本转换到旋转我
- python - 诗歌已添加模块,但未安装
- c# - 在 Visual Studio 中打开 C# 脚本后,它会像普通记事本一样显示
- quicksort - 所有重复项的数组如何进行快速排序 O(N^2)?
- ruby-on-rails - 未定义的方法“relation_delegate_class”
- android - Android:NDK:超级打开失败:ENOENT(没有这样的文件或目录)错误
- javascript - 正则表达式:查找“m:ss、mm:ss 或 hh:mm:ss”,没有“lookbehind”并拒绝子字符串和无效值