building kernel modules
Hello,
I am using buildroot to build a distro for an ARM ep9xx system. Everything works great except for one kernel module. I am trying to debug it, but it is a pain to make the whole kernel tree to insert a single printk. Also, it looks like I have to do "touch <...>/.configured" to get the kernel to detect the change the compile a new version of the module.
Is there any documentation regarding building kernel modules by themselves after having built the main kernel? Something similar to how userlevel apps get cross compiled. I suppose that somehow I need to access all of the flags that buildroot passes to the kernel when it builds it.
Ideally, I just want to just compile the module, and then insmod it over the NFS rootfs.
Many Thanks,
Roman
So I figured out how to get the external kernel module compilation going. The cross compilation works fine, but the linking fails as there are two undefined symbols. Also, there is a strange error regarding /usr/local/src/mv-kernel/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gcc
However, the compilation proceeds even with that error.
[rchertov at number2 src]$ sh make.sh
make:/usr/local/src/mv-kernel/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gcc:
Command not found
make: Entering directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
LD [M] /proj/tools/can_driver/musec_can/src/musec_can.o Building modules, stage 2.
MODPOST 1 modules
WARNING: "__bad_udelay" [/proj/tools/can_driver/musec_can/src/musec_can.ko] undefined!
WARNING: "__aeabi_uldivmod" [/proj/tools/can_driver/musec_can/src/musec_can.ko] undefined!
LD [M] /proj/tools/can_driver/musec_can/src/musec_can.ko
make: Leaving directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
I believe that the linker uses libc instead of uclibc which was compiled for ARM, and hence the linking step is failing. I would appreciate it if somebody could point out which linker setting I am missing. Below, I listed all of the variables that I redefined for the build.
ARCH=arm CROSS_COMPILE=/<br_dir>/build_arm/staging_dir/usr/bin/arm-linux-uclibcgnueabi-
AS =$(CROSS_COMPILE)as LD =$(CROSS_COMPILE)ld CC =$(CROSS_COMPILE)gcc CPP =$(CC) -E AR =$(CROSS_COMPILE)ar NM =$(CROSS_COMPILE)nm STRIP =$(CROSS_COMPILE)strip
OBJCOPY =$(CROSS_COMPILE)objcopy
OBJDUMP =$(CROSS_COMPILE)objdump
EXTRA_CFLAGS=-I /<br_dir>/project_build_arm/uclibc/linux-2.6.29/include\
-I<br_dir>/build_arm/staging_dir/usr/lib/gcc/arm-linux-uclibcgnueabi/4.3.3/include
LDFLAGS=-L/<br_dir>/build_arm/staging_dir/lib
...
Quoted 26 lines · Roman Chertov
Hello,
I am using buildroot to build a distro for an ARM ep9xx system. Everything works great except for one kernel module. I am trying to debug it, but it is a pain to make the whole kernel tree to insert a single printk. Also, it looks like I have to do "touch <...>/.configured" to get the kernel to detect the change the compile a new version of the module.
Is there any documentation regarding building kernel modules by themselves after having built the main kernel? Something similar to how userlevel apps get cross compiled. I suppose that somehow I need to access all of the flags that buildroot passes to the kernel when it builds it.
Ideally, I just want to just compile the module, and then insmod it over the NFS rootfs.
Many Thanks,
Roman
_______________________________________________
buildroot mailing list
buildroot at busybox.net
http://lists.busybox.net/mailman/listinfo/buildroot
Quoted 7 lines · Roman Chertov
So I figured out how to get the external kernel module compilation going. The cross compilation works fine, but the linking fails as there are two undefined symbols. Also, there is a strange error regarding
/usr/local/src/mv-kernel/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gccHowever, the compilation proceeds even with that error.
Quoted 10 lines
[rchertov at number2 src]$ sh
make.sh
make:/usr/local/src/mv-kernel/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gcc:
Command not found
make: Entering directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
LD [M] /proj/tools/can_driver/musec_can/src/musec_can.o Building modules, stage 2.
MODPOST 1 modules
WARNING: "__bad_udelay"
This error is due to an illegal usage of udelay() in the module code. Calling this function at all is frowned upon, and calling it with too big values fail[*] the kernel compilation for very good reasons. You should rather use schedule_timeout() or timer functions to give CPU time to do something useful while waiting for so long. But, without knowing the sources, it's impossible to give any further hints.
([*] the way they implemented that depending on compile-time constraints
is very nice, btw. Dig through the headers if your curious ;))
Quoted 8 lines
[/proj/tools/can_driver/musec_can/src/musec_can.ko] undefined!
WARNING: "__aeabi_uldivmod" [/proj/tools/can_driver/musec_can/src/musec_can.ko] undefined!
LD [M] /proj/tools/can_driver/musec_can/src/musec_can.ko
make: Leaving directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
Quoted 7 lines
I believe that the linker uses libc instead of uclibc which was compiled for ARM, and hence the linking step is failing. I would appreciate it if somebody could point out which linker setting I am missing. Below, I listed all of the variables that I redefined for the build.
ARCH=arm CROSS_COMPILE=/<br_dir>/build_arm/staging_dir/usr/bin/arm-linux-uclibcgnueabi-
These two look sane.
Quoted 11 lines
AS =$(CROSS_COMPILE)as LD =$(CROSS_COMPILE)ld CC =$(CROSS_COMPILE)gcc CPP =$(CC) -E AR =$(CROSS_COMPILE)ar NM =$(CROSS_COMPILE)nm STRIP =$(CROSS_COMPILE)stripOBJCOPY =$(CROSS_COMPILE)objcopy
OBJDUMP =$(CROSS_COMPILE)objdump
Quoted 6 lines
EXTRA_CFLAGS=-I /<br_dir>/project_build_arm/uclibc/linux-2.6.29/include\
-I<br_dir>/build_arm/staging_dir/usr/lib/gcc/arm-linux-uclibcgnueabi/4.3.3/includeLDFLAGS=-L/<br_dir>/build_arm/staging_dir/lib
...
But don't need all the rest. All you need to provide is ARCH=arm and CROSS_COMPILE=..., the rest is done automatically. The kernel's build system is very self-contained and the sources come with all kind of headers and libraries. No need to point it to any external resources.
Following that should make the 2nd error go away.
Daniel
Quoted 7 lines
This error is due to an illegal usage of
udelay()in the module code. Calling this function at all is frowned upon, and calling it with too big values fail[*] the kernel compilation for very good reasons. You should rather useschedule_timeout()or timer functions to give CPU time to do something useful while waiting for so long. But, without knowing the sources, it's impossible to give any further hints.
I have removed udelay calls in the code. (I am porting an old 2.4 driver to 2.6.29) and the _bad_udelay error went away.
Quoted 7 lines
But don't need all the rest. All you need to provide is ARCH=arm and CROSS_COMPILE=..., the rest is done automatically. The kernel's build system is very self-contained and the sources come with all kind of headers and libraries. No need to point it to any external resources.
Following that should make the 2nd error go away.
I have changed my makefile to this
obj-m := musec_can.o
musec_can-y := main.o hms30c7202_can.o c_can.o \
irq.o open.o close.o read.o write.o ioctl.o
The makefile is then invoked via a shell script:
make ARCH=arm \
CROSS_COMPILE=/<br_dir>/build_arm/staging_dir/usr/bin/arm-linux-uclibcgnueabi-\
-C /proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29 \
M=pwd modules
I have also configured buildroot to use gcc 4.4.1. I also rebuilt uclibc and the kernel with new compiler. When I make the module, I get the following during the linking phase.
make: Entering directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
Building modules, stage 2.
MODPOST 1 modules
WARNING: "__aeabi_uldivmod" [/proj/tools/can_driver/musec_can/src/musec_can.ko] undefined!
make: Leaving directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
Naturally, this module is not loadable as there an undefined symbol in the module. insmod reports the following:
insmod: can't insert './musec_can.ko': unknown symbol in module, or unknown parameter
I would appreciate some help in resolving this.
Thanks,
Roman
Quoted 3 lines
Daniel
Quoted 25 lines · Roman Chertov
Quoted 6 lines
But don't need all the rest. All you need to provide is ARCH=arm and CROSS_COMPILE=..., the rest is done automatically. The kernel's build system is very self-contained and the sources come with all kind of headers and libraries. No need to point it to any external resources.
Following that should make the 2nd error go away.
I have changed my makefile to this
obj-m := musec_can.o
musec_can-y := main.o hms30c7202_can.o c_can.o \
irq.o open.o close.o read.o write.o ioctl.oThe makefile is then invoked via a shell script:
make ARCH=arm \
CROSS_COMPILE=/<br_dir>/build_arm/staging_dir/usr/bin/arm-linux-uclibcgnueabi-\
-C /proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29 \
M=pwdmodulesI have also configured buildroot to use gcc 4.4.1. I also rebuilt uclibc and the kernel with new compiler. When I make the module, I get the following during the linking phase.
Quoted 5 lines
make: Entering directory `/proj/tools/buildroot-2009.08/project_build_arm/uclibc/linux-2.6.29'
Building modules, stage 2.
MODPOST 1 modules
WARNING: "__aeabi_uldivmod"
Hmm. If you only get this error for your own module (and not the kernel itself), you should have a look at the assembly output and see what gcc does there and why. It shouldn't be using the __aeabi_uldivmod function which is part of libgcc which the kernel does not seem to link on your platform. According to the postings below, these errors are likely to be caused by false gcc optimisations.
You should get around that by altering your sources, but again, without the code, this is all speculating.
Those links could also help:
http://www.spinics.net/lists/arm-kernel/msg48776.html
http://lists.arm.linux.org.uk/lurker/message/20080227.081641.1580db5d.en.html
In case you consider bringing your driver mainline, you can also post it to LKML and get some feedback there.
After all, what you're seeing is an effect that has to do with your code, the kernel and gcc. And not with buildroot :)
Daniel
Quoted 10 lines
Hmm. If you only get this error for your own module (and not the kernel itself), you should have a look at the assembly output and see what gcc does there and why. It shouldn't be using the
__aeabi_uldivmodfunction which is part of libgcc which the kernel does not seem to link on your platform. According to the postings below, these errors are likely to be caused by false gcc optimisations.You should get around that by altering your sources, but again, without the code, this is all speculating.
Turns out it was a division of a long that was causing that. After I changed the long to a uint32_t then the problem went away. Now, I have to figure out why I cannot insert the module.
musec_can: unknown relocation: 40
insmod: can't insert '/proj/tools/can_driver/musec_can/src/musec_can.ko': invalid module format
Modules built during the kernel built work fine. I guess I have to figure out what linker setting I am missing.
Quoted 8 lines
Those links could also help:
http://www.spinics.net/lists/arm-kernel/msg48776.html
http://lists.arm.linux.org.uk/lurker/message/20080227.081641.1580db5d.en.htmlIn case you consider bringing your driver mainline, you can also post it to LKML and get some feedback there.
That would be down the road once I actually test the driver and iron out any problems that might occur.
Quoted 3 lines
After all, what you're seeing is an effect that has to do with your code, the kernel and gcc. And not with buildroot :)
True. I was just hoping that somebody would give me a starting point as
I new to cross compiling :) Thanks for the help.
Roman
Quoted 3 lines
Daniel
Quoted 10 lines · Roman Chertov
Turns out it was a division of a long that was causing that. After I changed the long to a
uint32_tthen the problem went away. Now, I have to figure out why I cannot insert the module.
musec_can: unknown relocation: 40
insmod: can't insert '/proj/tools/can_driver/musec_can/src/musec_can.ko': invalid module formatModules built during the kernel built work fine. I guess I have to figure out what linker setting I am missing.
See dmesg for more of the reason. There's a comprehensive guideline I can point you to, just in case that differs from what you did:
http://lwn.net/Articles/21823/
Quoted 5 lines
Quoted 2 lines
After all, what you're seeing is an effect that has to do with your code, the kernel and gcc. And not with buildroot :)
True. I was just hoping that somebody would give me a starting point as
I new to cross compiling :) Thanks for the help.
No problem :)
Daniel
Quoted 8 lines · Daniel Mack
Quoted 7 lines · Roman Chertov
Turns out it was a division of a long that was causing that. After I changed the long to a
uint32_tthen the problem went away. Now, I have to figure out why I cannot insert the module.
musec_can: unknown relocation: 40
insmod: can't insert '/proj/tools/can_driver/musec_can/src/musec_can.ko': invalid module format
This was due to a kernel bug
http://lkml.indiana.edu/hypermail/linux/kernel/0903.3/02813.html
The patch provided in the link fixed the problem for me.
Quoted 18 lines
Quoted 3 lines
Modules built during the kernel built work fine. I guess I have to figure out what linker setting I am missing.
See dmesg for more of the reason. There's a comprehensive guideline I can point you to, just in case that differs from what you did:
http://lwn.net/Articles/21823/
Quoted 4 lines
Quoted 2 lines
After all, what you're seeing is an effect that has to do with your code, the kernel and gcc. And not with buildroot :)
True. I was just hoping that somebody would give me a starting point as
I new to cross compiling :) Thanks for the help.No problem :)
Daniel