在 x86 平台中使用 -mcmodel=kernel 标志
Posted
技术标签:
【中文标题】在 x86 平台中使用 -mcmodel=kernel 标志【英文标题】:use of -mcmodel=kernel flag in x86 platform 【发布时间】:2018-08-29 02:04:18 【问题描述】:我正在尝试将针对 x86 架构构建的设备驱动程序交叉编译到 arm 平台。它编译时没有任何错误,但我不认为所有功能都可用。所以我检查了makefile并找到了这个特定的部分。
ifeq ($(ARCH),x86_64)
EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone
这似乎是唯一依赖于架构的部分。在谷歌上一段时间后,我发现 -mcmodel=kernel 用于内核代码模型,而 -mno-red-zone 是为了避免在内存中使用红色区域,它们都是针对 x86_64 的。但我不清楚,它将 cmodel 设置为内核有什么影响?
(非常感谢您对 arm 问题的任何见解。)
【问题讨论】:
【参考方案1】:The x86 Options section of the GCC manual 说:
-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
(like these) 的情况下没有出现链接错误,则可能是a gcc that makes PIE executables by default(在最近的发行版中很常见),因此它避免了绝对寻址。
【讨论】:
以上是关于在 x86 平台中使用 -mcmodel=kernel 标志的主要内容,如果未能解决你的问题,请参考以下文章