GAS 组装的 QEMU 中 ARM64 ELF 可执行文件 运行 的对齐要求
alignment requirements for ARM64 ELF executables run in QEMU assembled by GAS
我有这个 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 机器上,但我正在 运行 将这些程序编译到一个 Docker 容器中,该容器是从这个 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() 设置为零时。
由于程序在真正的 AArch64 Linux 内核上运行良好,这是一个 QEMU 错误。我已经报告了它 to the upstream mailing list 所以我们会看看是否有人提出了解决方案。
我有这个 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 机器上,但我正在 运行 将这些程序编译到一个 Docker 容器中,该容器是从这个 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() 设置为零时。
由于程序在真正的 AArch64 Linux 内核上运行良好,这是一个 QEMU 错误。我已经报告了它 to the upstream mailing list 所以我们会看看是否有人提出了解决方案。