I am trying to cross compile a device driver built for x86 architecture to arm platform. It got compiled without any errors, but I dont think whole features are available. So I checked the makefile and found this particular part.
ifeq ($(ARCH),x86_64)
EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone
This is the only part that depends on architecture it seems. After some time on google, I found that -mcmodel=kernel is for kernel code model and -mno-red-zone is to avoid using red zone in memory and both them were for x86_64. But its not clear to me, what impact does it make setting cmodel to kernel?
(Any insight into the problem with arm is also greatly appreciated.)
The x86 Options section of the GCC manual says:
-mcmodel=kernel
Generate code for the kernel code model. The kernel runs in the negative 2 GB of the address space.
(i.e. the upper 2GiB, addresses like 0xffffffff80001234
)
In the kernel code model, static symbol addresses don't fit in 32-bit zero-extended constants (unlike the default small code model where mov eax, imm32
(5 bytes) is the most efficient way to put a symbol address in a register).
But they do fit in sign-extended 32-bit constants, unlike the large
code model for example. So mov rax, sign_extended_imm32
(7 bytes) works, and is the same size but on some CPUs slightly more efficient than lea rax, [rip + symbol]
.
But more importantly mov eax, [table + rdi*4]
works, because disp32 displacements are sign-extended to 64 bits. -mcmodel=kernel
tells gcc it can do this but not mov eax, OFFSET table
.
Neither of those are position-independent, so would require runtime fixups. It's common I think to compile the Linux kernel as position-independent so its virtual address can be randomized at boot.
RIP-relative addressing can also reach any symbol from any code address (with a rel32 +-2GiB offset), so -fPIC
or -fPIE
will also make your code work, at the minor expense of not taking advantage of 32-bit absolute addressing in cases where it's useful. (e.g. indexing static arrays).
If you didn't get link errors without -mcmodel=kernel
(like these), you probably have a gcc that makes PIE executables by default (common on recent distros), so it avoids absolute addressing.