Create, Build and Debugging a GNU/Linux Kernel Module


Creating the 'luv' Kernel Module

  1. Create a scratch directory as our "work" environment
    mkdir luv_demo
  2. Hop into the work
    cd luv_demo
  3. Download the Linux kernel (2.6.36)
    wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.36.tar.bz2
  4. Uncompress and untar the kernel source code
    tar -jxf linux-2.6.36.tar.bz2
  5. Hop into the directory
    cd linux-2.6.36
  6. Create a directory for our module, we will put it in drivers/
    mkdir drivers/luv
  7. Hop into the luv
    cd drivers/luv
  8. Write the sourcecode, Makefile, Kconfig files, or just copy from here:
  9. Hop to the 'drivers' directory so we can tell the build system about our added 'luv' module
    cd ../
  10. Modify the driver directory's Makefile so it know about the luv directory
    echo 'obj-$(CONFIG_LUV) += luv/' >> Makefile
  11. Modify the driver directory's Kconfig so users can choose to have the luv module built at kernel compilation time
    sed -i -e '/endmenu/ i source "drivers/luv/Kconfig"' Kconfig

Building the Kernel With the 'luv' Module

Remember: We are currently where we last left off, in the 'luv_demo/linux-2.6.36/drivers' directory.
  1. Hop into the toplevel of the kernel source tree: luv_demo/linux-2.6.36/
    cd ../
  2. Create a default .config telling the kernel what features and modules to build, using a 32-bit x86 architecture (gdb and qemu can nicely debug this, even from a 64-bit machine).
    make defconfig ARCH=i386
  3. Enable the LUV module and debugging options (running 'make menuconfig ARCH=i386' is easier but the following can be done as well). Also, we will disable loadable module support, so all modules will be built directly into the kernel (static modules). This eases our example.
    sed -i -e 's/.*CONFIG_LUV .*$/CONFIG_LUV=y/' .config
    sed -i -e 's/.*CONFIG_DEBUG_KERNEL .*$/CONFIG_DEBUG_KERNEL=y/' .config
    sed -i -e 's/.*CONFIG_DEBUG_INFO .*$/CONFIG_DEBUG_INFO=y/' .config
    sed -i -e 's/^CONFIG_MODULES/#CONFIG_MODULES/' .config
  4. Build this puppy. The build system will query you about adding additional features into your kernel, just accept the default by pressing 'enter'
    make bzImage ARCH=i386
  5. Make some coffee, twiddle thumbs, wait...

Debugging the 'luv' Module

Remember: We are currently where we last left off, in the 'luv_demo/linux-2.6.36/' directory.
  1. Start qemu telling by specifying our freshly built kernel, telling it to not start the CPU of the qemu image. GDB will be used to unhalt the qemu instance
    qemu -kernel arch/i386/boot/bzImage -S -s
  2. Start a new terminal and hop into the luv_demo/linux-2.6.36 directory
  3. Start gdb using the uncompressed kernel image for debugging
    gdb vmlinux
  4. From the gdb terminal, tell gdb to connect to our qemu instance
    target remote localhost:1234
  5. From the gdb terminal, set a break point on our module's initialization routine
    break luv_init
  6. Fire-up the kernel and wait for the break point to trip, from GDB
    continue
-Matt