I am trying to build my own module for usbhid.ko
, but after I compiled, I can't load the module. dmesg
says no symbol version for module_layout
. I am wondering what is the problem? I have already used the kernel source provided by Ubuntu and I have also make sure the kernel version is the same.
Specifically what the problem is that when you built your module, the kernel source tree was probably missing the Modules.symvers file. The kbuild system actually warns you about this when you build your module. If Modules.symvers is missing, you'll see:
If your kernel has
CONFIG_MODVERSIONS
enabled, then during the modpost phase of building your driver it will run scripts/mod/modpost with the -m option. If you're brave and take a look at the scripts/mod/modpost.c source, you'll see that the -m option adds the _module_layout_ symbol from vmlinux, however if you don't have Modules.symvers from your kernel, you'll not get the CRC value for this symbol and you'll end up with this error message.So there are two ways around this.
1) run a full build of your running kernel to generate Modules.symvers, then rebuild your module. [http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt][1]
2) The other option is to tell stupid modprobe to just ignore all that crap and just load your module anyways:
I tend to favor option 2 :)
Have both the
linux-headers
andlinux-source
packages corresponding to your kernel installed. For example for kernel3.2.0-27-generic-pae
you need:linux-headers-3.2.0-27-generic-pae
andlinux-source-3.2.0-27-generic-pae
.In case the version for the packages above doesn't match your running kernel version then you need to replace
$(uname -r)
with the version string from your installed kernel package from above.For the above example the package version is
3.2.0-27-generic-pae
. When you rununame -r
and its output is something different then3.2.0-27-generic-pae
then you need to replace each$(uname -r)
below to match the version string from the installed packages.cd /usr/src/linux-source-$Version
and unpack the .tar.bz2 archive in place and cd into the extracted directory - I guess you already did thiscp /boot/config-$(uname -r) .config
into the kernel source directorycp /usr/src/linux-headers-$(uname -r)/Module.symvers .
into the kernel source directoryAfter you've done that, in the kernel source directory, do this:
make prepare
make scripts
make M=drivers/usb/serial
- change the path afterM=
to suit your needsUnfortunately, I don't know how to build a specific module while keeping
Module.symvers
untouched. Doingmake drivers/usb/serial/option.ko
, for example, kills theModule.symvers
file, and you end up with your original problem. Using theM=
parameter doesn't kill it, but you have to build all the modules in the specified path - and I haven't found a way around it yet.You must use the precisely identical kernel configuration prior to running
make prepare
. Also, if you're building it out-of-tree, you need to be building it against the precisely identical kernel headers matching your currently running kernel (or the target one if you aren't running it at time of compilation).