首页 > 解决方案 > 在 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 可执行文件的重要信息,但我不知道它是什么。

标签: armclangelfqemugnu-assembler

解决方案


QEMU 对您的数据部分的程序头感到困惑:

    LOAD off    0x00000000000000c0 vaddr 0x00000000004100c0 paddr 0x00000000004100c0 align 2**16
         filesz 0x0000000000000000 memsz 0x0000000000000010 flags rw-

并且未能在该地址实际映射一些可写内存;当 QEMU 尝试将 BSS 的 memset() 归零时,段错误来自 QEMU 本身。

由于程序在真正的 AArch64 Linux 内核上运行良好,这是一个 QEMU 错误。我已将其报告给上游邮件列表,因此我们将看看是否有人提出解决方案。


推荐阅读