2

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

ifeq ($(ARCH),x86_64)
    EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone

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

(也非常感谢您对 arm 问题的任何见解。)

4

1 回答 1

4

GCC 手册的x86 选项部分说:

-mcmodel=kernel

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

(即上层 2GiB,地址如0xfffffffff0001234

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

但它们确实适合符号扩展的 32 位常量,这与large代码模型不同。所以mov rax, sign_extended_imm32(7 bytes) 有效,并且大小相同,但可能比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像这些)没有链接错误,那么您可能有一个 gcc,默认情况下会生成 PIE 可执行文件(在最近的发行版中很常见),因此它避免了绝对寻址。

于 2018-03-20T11:50:34.567 回答