Using LLVM to cross compile Linux kernel modules in Windows

Simple common hello program cross compile Click here.

Environment construction

I'm not doing well, or even stupid, but no one teaches me.
The current skill is to compile a kernel module and Makefile in linux normally. After normal use, look for the specific command to execute for decomposition:
(the steps are general, maybe the paths are different.)
1. Enter / usr/src/linux-headers-3.4.9-rtai-686-pae/Makefile
2. Enter / usr/src/linux-headers-3.4.9-common-rtai/Makefile
3. Enter / usr / SRC / linux-headers-3.4.9-common-rtai/scripts/ Makefile.build (there are some functions in Kbuild.include Defined):

# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
	$(call cmd,force_checksrc)
	$(call if_changed_rule,cc_o_c)

The key is on the last line. The actual call is rule_cc_o_c function (defined by Makefile), print as follows:

        @echo "cmd is :",$(cmd_cc_o_c)

Save return to make:

gcc -nostdinc -isystem /usr/lib/gcc/i586-linux-gnu/4.9/include 
-I/usr/src/linux-headers-3.4-9-common-rtai/arch/x86/include 
-Iarch/x86/include/generated -Iinclude -I/usr/src/linux-headers-3.4-9-common-rtai/include ...

There will be similar printing, so you can roughly copy the linux folder to the window.

Compilation steps

1. Target file (. o) to generate source file:

clang  --target=i586-linux-guneabi -std=gnu89 -fno-builtin -nostdinc -isystem 
D:\BUILDPATH\linux_X86/usr/lib/gcc/i586-linux-gnu/4.9/include -
ID:\BUILDPATH\linux_X86/usr/src/linux-headers-3.4-9-common-rtai/arch/x86/include -
ID:\BUILDPATH\linux_X86\usr\src\linux-headers-3.4-9-rtai-686-pae\arch/x86/include/generated 
-ID:\BUILDPATH\linux_X86\usr\src\linux-headers-3.4-9-rtai-686-pae\include -
ID:\BUILDPATH\linux_X86/usr/src/linux-headers-3.4-9-common-rtai/include -include 
D:\BUILDPATH\linux_X86/usr/src/linux-headers-3.4-9-common-rtai/include/linux/kconfig.h -
D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-
common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-
checks -O3 -m32 -msoft-float -mregparm=3 -freg-struct-return  -march=i686 -mtune=generic  -
ffreestanding -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -
DCONFIG_AS_CFI_SECTIONS=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse 
-mstack-alignment=2 -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -Wframe-larger-than=1024 -Wno-
unused-but-set-variable -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-
sign -fno-strict-overflow -DCC_HAVE_ASM_GOTO -w -g -ID:\BUILDPATH\linux_X86/usr/src/linux-
headers-3.4-9-common-rtai/. -I. -ID:\BUILDPATH\linux_X86/usr/realtime-3.4-9-rtai-686-
pae/include -ID:\BUILDPATH\linux_X86/usr/src/linux-headers-3.4-9-common-rtai/. -I. -
ID:\BUILDPATH\linux_X86/usr/realtime-3.4-9-rtai-686-pae/include -
ID:\BUILDPATH\linux_X86/usr/include/i386-linux-gnu -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -
fno-math-errno -funsafe-math-optimizations -fno-rounding-math -fno-signaling-nans -mhard-
float -DRTAI=3 -fno-fast-math -mieee-fp -fno-unsafe-math-optimizations -DRTAPI -
D_GNU_SOURCE -Drealtime -D__MODULE__ -
ID:\BUILDPATH\linux_X86/opt/linuxahead/include/linuxcnc -Wframe-larger-than=2560 = -DMODULE 
-DKBUILD_STR\(s\)=#s -DKBUILD_BASENAME=KBUILD_STR\(test_0\) -DKBUILD_MODNAME=KBUILD_STR\
(mod_test_0\) -c -o D:\BUILDPATH\linux_X86/test_0.o D:\BUILDPATH\linux_X86/test_0.c

Of course you can have more than one of these. o, all of them are the same. There are some problems in the middle, and some confusion I haven't understood yet. See Note 1.

2. Merge int o one

This step is relatively simple, one command:

ld.lld  -m elf_i386 -r -o mod_test_0.o test_0.o test_1.o ..

3. The following steps are carried out in linux, not fully compiled in window s.

(1) Generate mod.c

This mod.c is quite confusing. The current understanding is that this file contains our previous mod_ test_ All external symbols used in 0. O and their CRC values. It is mainly used to match whether the kernel module matches the kernel version when it is loaded again? (CRC can be used to check whether the referenced symbol corresponds to the kernel symbol position.). I'm just misleading here.

Why I don't compile in window? It's because I don't know how to compile in window.

linux generates. mod.c:

 cd /usr/src/linux-headers-3.4-9-rtai-686-pae/
scripts/mod/modpost -m -i /usr/src/linux-headers-3.4-9-rtai-686-pae/Module.symvers 
-I /home/aheadtechs/XCompilation/PLC/Module.symvers -e /usr/realtime-3.4-9-rtai-686-pae/modules/linuxcnc/Module.symvers 
-e /usr/realtime-3.4-9-rtai-686-pae/modules/ethercat/Module.symvers 
-o /home/aheadtechs/XCompilation/PLC/Module.symvers -S -w -c -s 
/home/USER/mod_test_0.o

You can see that modpost generates the. mod.c file according to the. o generated by us!

(2) Generate. mod.o

This step is similar to the command in the previous step.

(3) Generate. ko

ld -r -m elf_i386 -T /usr/src/linux-headers-3.4-9-common-rtai/scripts/module-common.lds 
--build-id -o /home/USE/mod_test_0.ko /home/USE/mod_test_0.o /home/USE/mod_test_0.mod.o

It can be seen that ko is using the last. o and our mod.o

(4) Copy to the responding directory

cp mod_test_0.ko /XXX/

matters needing attention

1

1. Error reported by. o at the beginning of window compilation:

expanded from macro 'BUILD_BUG_ON'
((void)sizeof(char[1 - 2*!!(condition)]));

There will be errors when using linux-o0 optimization, but we default to - O2 optimization, but not in clang. How can I do it? I went to the source file to comment out this!

Here it is:

static __always_inline
void __kfree_rcu(struct rcu_head *head, unsigned long offset)
{
	typedef void (*rcu_callback)(struct rcu_head *);

	//BUILD_BUG_ON(!__builtin_constant_p(offset)); that's it

	/* See the kfree_rcu() header comment. */
	BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));

	kfree_call_rcu(head, (rcu_callback)offset);
}

Operation is too brainless. I don't know if there is any problem!

2.fmax symbol table conflict

Every small. o I generate has the symbol of fmax, while linux compilation does not. Here I add - std=gnu89 to solve the problem. I suspect that it is a built-in function. fmax belongs to a built-in function in gnu89 standard? Let's talk about it later.

3.clang is missing parameters of gcc:

The following byte alignment settings are changed to:

-mpreferred-stack-boundary=2       ==> clang: -mstack-alignment =2
?:  -fconserve-stack 
?:  -fcx-limited-range
?:  -Wa,-mtune=generic32

These three parameters have not been found, and the specific functions will be studied again. First, they are removed from the clang command.

conclusion

. mod.c and the following parts are not compiled on window s. I'm not satisfied. And I still can't confirm whether the. o above can be used normally. Simple test can be done, but if there is a problem, please update it.

Tags: Linux Makefile

Posted on Fri, 12 Jun 2020 06:05:28 -0400 by spec36