在 x86 平台中使用 -mcmodel=kernel 标志

Xte*_*ter 2 c gcc makefile x86-64 red-zone

我正在尝试将为 x86 架构构建的设备驱动程序交叉编译到 ARM 平台。它的编译没有任何错误,但我认为所有功能都不可用。所以我检查了 makefile 并找到了这个特定的部分。

ifeq ($(ARCH),x86_64)
    EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone
Run Code Online (Sandbox Code Playgroud)

这似乎是唯一依赖于架构的部分。在google上一段时间后,我发现 -mcmodel=kernel 用于内核代码模型,而 -mno-red-zone 是为了避免在内存中使用红色区域,并且它们都适用于 x86_64。但我不清楚,将 cmodel 设置为内核会产生什么影响?

(任何对arm问题的深入了解也将不胜感激。)

Pet*_*des 5

GCC 手册的x86 选项部分说:

-mcmodel=kernel

为内核代码模型生成代码。内核在负 2 GB 的地址空间中运行。

(即上面的2GiB,地址类似0xfffffffff0001234

在内核代码模型中,静态符号地址不适合 32 位零扩展常量(与默认的小代码模型不同,其中mov eax, imm32(5 字节)是将符号地址放入寄存器的最有效方式)。

但它们确实适合符号扩展的 32 位常量,与large代码模型不同。所以mov rax, sign_extended_imm32(7 字节) 可以工作,并且大小相同,但可能比lea rax, [rel symbol].

但更重要的mov eax, [table + rdi*4]是,它可以工作,因为 disp32 位移已符号扩展为 64 位。 -mcmodel=kernel告诉 gcc 它可以做到这一点,但不能mov eax, table


RIP 相对寻址还可以从任何代码地址(具有 rel32 +-2GiB 偏移量)到达任何符号,因此-fPIC-fPIE也将使您的代码正常工作,但在以下情况下不利用 32 位绝对寻址是一个很小的代价:有用。(例如索引静态数组)。

如果你没有得到链接错误-mcmodel=kernel像这些),你可能有一个默认情况下生成 PIE 可执行文件的 gcc(在最近的发行版上很常见),因此它避免了绝对寻址。