linux kernel module compilation pre-requisites - c

I've just started to learn about linux kernel modules and the book I'm referring to says:
"For this [compilation] to work, the kernel source has to be suitably prepared; in particular it has to have a configuration file (.config in the main kernel source directory) and proper dependencies setup"
However, as far as I know (and have tried), the .config file is generated by the make menuconfig (or any of the equivalent make config commands) - and that doesn't seem to be enough for my module files to compile. What's the bare minimum I need to do in the kernel source directory?
make modules?

Yes, the .config file is generated using make *config.
Here are some of them:
make defconfig creates the default configuration for your architecture.
make config is the most primitive method, it prompts on every configuration.
make menuconfig is ncurses config menu. That's the one I prefer if I'm not editing .config file directly.
make gconfig is like menuconfig, but using gtk+.
Don't forget that make oldconfig should be called after modifying the .config file yourself.
Your current config might also be stored somewhere on your disk. For many linux versions, it's location is /boot/config-$(uname -r) If it exists, you can start with it. If not, your best bet is make defconfig, then editing the config file to suit your needs.
After configuration:
Before building modules, you might want to compile the kernel since your modules will not be used by the current kernel and even if you make your current kernel use those modules, it'll most probably cause a panic since symbol tables will not be in the order that your compiled modules assumes. make -jN is the most used method for compiling, N being twice your CPU core count. This also compiles modules, but creates .ko files for them, instead of embedding into the vmlinuz file.
After that, you can sudo make install to install your kernel. This usually wraps the kernel object you've just compiled into a suitable format and puts under /boot (it doesn't have to be /boot, actually).
Then you sudo make modules_install to copy the created .ko files into /lib/modules/$(uname -r). This builds all modules.
After doing that, you might prefer only building your own module, instead of all of them. When on the kernel tree root, you may make M=your_modules_relative_path to only build your module.
I don't know which book you're reading, but if you're building a module externally, you still have to perform the work above. After that, you may use LDD examples as a starting point for your makefiles.
See https://github.com/duxing2007/ldd3-examples-3.x

Related

Virtual environment for C library development

Original
I am looking for a way to create a non-isolated development environment for a C-library.
I will most likely use cmake to build the library and my IDE is a simple text editor.
The problem now is that I do not only create the library but also some sample "applications" using the library.
Therefore I need to install the library's headers and the shared object (I'm using GNU/Linux) somewhere and I do not want to install it to /usr/local/lib or (the even worse) /usr/lib.
Is there a way to create a virtual environment similar to python's pyvenv (and similar) where I can install the everything to but still have access to the host libraries?
Also I do not want to rewrite my $PATH/$LD_LIBRARY_PATH, setup a VM, container, or chroot.
The usage would then look like:
# switch to environment somehow
loadenv library1
# for library
cd library
make && make install
# for application
cd ../application1
make && ./application1
Is this possible?
Edit 1
So basically my directory structure will look like this:
library/
library/src/
library/src/<files>.c
library/include/<files>.h
application/
application/src/
application/src/<files>.c
First I need to compile the library and install the binary and header files.
These should be installed in a fake system-location.
Then I can compile the application and run it.
Edit 2
I thought a bit about it and it seems all I need is a filesystem sandbox.
So basically I want to open up a shell where every write to disk is not committed to the filesystem but rather temporarily saved in e.g. a ramfs/tmpfs just to be dropped when the shell exits.
This way I can exactly test how everything would behave if compiled, deployed and executed on the real machine without any danger to existing files or directories and without accidentally creating files or directories without cleaning them up.
You don't really need to 'install' the library, you can work in the development tree.
(1) for compilation all you need to do is use -I flag to specify where the libraries header files are, and this can be a relative path, for example in your case you could do -I../../library/include
(2) for linking you need to tell the linker where the library is located at, you can use the -L flag append to the library search order.
(3) for testing the application, you are correct that the application needs to be able to find the library. You have a couple of options:
(a) make sure the library and the executable are in the same directory
(b) you can temporarily modify your LD_LIBRARY_PATH, in your current shell only, for testing:
export LD_LIBRARY_PATH=abs_path_to_library:$LD_LIBRARY_PATH
note that this will only effect the current shell (command terminal) you are working in. Any other shells you may have open, or open later will have your normal LD_LIBRARY_PATH. I know you specified that you don't want to modify your PATH or LD_LIBRARY_PATH, but being local to the shell that the command is executed it is a nice, easy way to do this.
(c) embed the path to the library in the client executable. To do this you need to pass an option to the linker. The command for gcc is:
-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)
see this how-to

Disagrees about version of symbol symbol_name after insmod

I am new in kernel programming.
For implementing my project work, I have downloaded the latest stable kernel (v4.3) from kernel.org.
Just for checking I have copied a few files from the kernel directories into my project directory. Made changes to it and inserted a few more code to it.
Then I compiled on SLES11 Linux kernel using
make -C /lib/modules/$(uname -r)/build M=$PWD modules
I have used the below makefile
obj-m := my_module.o
my_module-objs := module_main.0 other_module1.o other_module2.o other_module3.o
It compiled successfully.
But when I tried to insert into the kernel using
insmod my_sample.ko
It showed the following
disagrees about version of symbol symbol_name
You need to build your kernel module against the same version kernel you are going to run. Thus if you have kernel 4.3 sources that you have downloaded you need to compile that version of the kernel and boot with that running before trying to load your kernel.
You have two solutions then:
Download the kernel sources for the kernel you are currently running (you can install those with zypper install kernel-source on SLES or an equivalent command on other distributions.)
Compile and install the 4.3 kernel in to your operating system. If you need help with this then ask a separate question (and it probably belongs on superuser not here). Note that if kernel and glibc are tightly coupled, and it is possible that you can't run a new kernel if you have a very old C library.
The problem here is that your Kernel module is using the exported symbols of other kernel modules which in this case appears to be the linux InfiniBand RDMA stack's exported methods or symbols.
To solve the symbol version problems, copy the Module.symvers file from the
/usr/src/ofa-kernel
directory and paste it to your current working directory. Then you make your modules again. Now the insmod should work perfectly fine.
NOTE: The Module.symvers file contains information of all the kernel
module exported symbol. So by copying it to your working directory,
you are helping kbuild to know more about the used exported symbols.
And if you don't find Module.symvers or it is empty, then create one using create_Module.symvers.sh
make -C /lib/modules/$(uname -r)/build M=$PWD modules,
"$(uname -r)" shows that you are compiling against the kernel version you are running now so you should be able to insmod the module in the current kernel if you haven't changed the headers.
From your text,
"Just for checking I have copied a few files from the kernel directories into my project directory. Made changes to it and inserted a few more code to it."
If you have made modifications to the kernel source then you may need to recompile the new kernel and boot with the new updated kernel. Then you should be able to compile your kernel module with the modified headers.
Looks like you built agAinst right kernel.something to do with how your kernel is compiled. (See Config_conversions). Try --force

Compiling an individual kernel module (Debian/Ubuntu)

I need to modify the ELF loader's kernel implementation of an Ubuntu 14.04 distribution. Having downloaded the sources using:
sudo apt-get source linux-image-$(uname -r)
I ran the configuration script:
make config
in the root source tree. After a seemingly endless sequence of input requests, the script created the .config file needed to build the kernel(or a set of modules). The kernel version I am using is linux-3.13.0 and has the following source tree layout:
$ ls
arch COPYING crypto Documentation dropped.txt FileSystemMakefile fs init Kbuild kernel MAINTAINERS mm README samples security sound ubuntu virt
block CREDITS debian.master drivers elf.dat firmware include ipc Kconfig lib Makefile net REPORTING-BUGS scripts shortcuts tools usr
The ELF loader is located in /path/to/source/fs/binfmt_elf.c. Following this question,in order to compile an individual module it is sufficient to run
make /path/to/module/directory.
In this case that would be:
make ./path/to/source/fs
The compilation is quite lengthy; it takes about twenty minutes(on a virtual machine) and the output is written(by default) in the same directory in which the module is located. I've found the object files by running:
find . -name "*.o"
in /path/to/source/fs. Filtering by name the ELF loader can be located by running:
find . -name "*elf*.o"
In the current sources it is written(by default) in:
/path/to/source/fs/binfmt_elf.o
Having gone through this tutorial, I've noticed that kernel modules have the naming convention [module_name].ko in order to distinguish them from user space object files.
My question is how can I insert the new(modified) ELF loader into the kernel given that the current ELF loader is present(as unloading it may prevent binaries from being executed)?
What you have described is not really compiling a "kernel module" as it is commonly referred to. You have built an object that is statically linked into the kernel and there is no way that you can load just that object into a running kernel.
"kernel module" usually refers to "loadable kernel module" (LKM). Building and loading the fs as an LKM is what you need/want. Take a look at the below HOWTO. Follow that to build the desired fs as an LKM. Then you can just replace that one LKM (.ko) file and reboot (normally you can dynamically remove and insert LKMs but not sure how that will affect something fundamental like the ELF fs - you can try rmmod/modprobe without a reboot first if you ike).
http://www.tldp.org/HOWTO/Module-HOWTO/x73.html

Error compiling Kernel-aodv for ARM

I'm about to implement AODV on ARM board SabreLite and I'm facing some problems.
So, I use the latest version of AODV located here (sourceforge.net/projects/aodvuu/). I've follow the instruction given in README file but at the end, i get the error:
kaodv-mod.c:22:27: fatal error: linux/version.h: No such file or directory
#include
Since the board use 3.0.35 kernel version, i download it and I just change the kernel directory in Makefile. And, it should normally worked based on the instruction (http://w3.antd.nist.gov/wctg/aodv_kernel/kaodv_arm.html). The above error suggests that i don't have the version.h but I checked and I have all of linux header files installed, so it can't be that.
On the step number 6 of the tutorial (README file), i did not compile the kernel 3.0.35 because i'm pretty positive that it has the proper netfilter support for AODV-UU as it is a kernel young version. ( It is actually a configuration suggestion on kernel 2.4 and 2.6 but i think i should not obliged to do that here)
What can be the solution of this ?
Do i really need to compile this kernel version (3.0.35) before keep going ?
Do i have to change the AODV code, and if so, which files do i have to modify ?
Thanks in advance !!!
Thanks for your response, but unfortunately, i've already done that. By saying that, i mean, i've choosen the kernel source tree that matches the target kernel (linux-imx6-boundary-imx_3.0.35_4.1.0). I've also set up my cross compiler to have my environment variables ready for the cross compilation. Here is the output.
echo $CC:
arm-oe-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/usr/local/oecore-x86_64/sysroots/cortexa9hf-vfp-neon-oe-linux-gnueabi
and some of my env variables looks like this:
ARCH=arm
CROSS_COMPILE=arm-oe-linux-gnueabi-
CFLAGS= -O2 -pipe -g -feliminate-unused-debug-types
RANLIB=arm-oe-linux-gnueabi-ranlib
After, all of these configurations, i still got the error. I really don't think that i have to recompile the kernel
In order to build modules, you need a kernel source tree in a state that matches the target kernel, i.e. not an untouched freshly-downloaded one. Don't confuse the presence of extra board-specific patches/drivers/etc. in a vendor kernel for configuration - to get the source tree into the right state to use, you still need to:
configure it correctly: make ARCH=arm <whatever>_defconfig (and/or any .config tweaks your board needs)
then build it: make ARCH=arm CROSS_COMPILE=<your toolchain triplet>
You need to actually build the kernel because there are many important files that don't exist yet, like the contents of include/generated (where the aforementioned version.h is created), the corresponding arch/$ARCH/include/generated, the checksums for module versioning, and probably more, which will all be different depending on which architecture and particular configuration options were chosen.
My bad for missing the mention of the crucial detail in the question, but upon downloading the linked AODV to try this myself, it became clear: the makefile is designed for the 2.4 build system which was rather different (and I'm not familiar with). Getting that one to build against a post-2.6 kernel will require writing a new makefile.

Can we only recompile a kernel module in kernel source tree?

Let's say we install a kernel 2.6.32.el6, then we download the 2.6.32.el6.src.rpm, can we just install the source and modify some module, and use make -C 2.6.32.el6.src.source.directry -M$PWD in the module directory to compile the module, then we copy into /lib/modules/2.6.32.el6/kernel/moduledirectory and the new module would work?
I try to modify kvm modules and compile it, but when I recompile the module and copy it into the directory, machine said when booting:
kvm: no symbol version for module_layout
kvm_intel: no symbol version for module_layout
Anyone knows what is wrong?
Probably linux kernel 2.6.32.el6 has been compiled with modversions but your module was compiled without it. Check if you have CONFIG_MODVERSIONS selected or deselected in your kernel config file. Compare it with /proc/.config file which is the kernel confguration file - of course if you have it.
In other words - probably your linux kernel requires that modules supports versioning, but your module doesn't provide it.

Resources