Debugging Linux Kernel using KProbes - Counting number of processes created

Kernel provides a lot of techniques for debugging Linux Kernel. Most of the developers use printk for its ease and simplicity. There are some cons using printk.

  • Difficult when frequent changes are required
  • Time-consuming, as recompiling, installing and rebooting the kernel is required 
We have already seen kgdb in our previous posts, In this post, we will learn KProbes.

What are KProbes?

KProbes is a debugging technique for Linux Kernel using which you can
  • Monitor events
  • Filter out performance bottlenecks
  • Log Specific Events
  • Trace Problems etc
KProbes enables you to dynamically break into any kernel function and collect debugging and performance information.  

How KProbes work?

1. User needs to know the address or symbol which needs to be debugged
2. Create pre and post handlers which will be called before and after the instruction execution at the address or symbol
Prototype: 
int pre_handler(struct kprobe *p, struct pt_regs *regs);
void post_handler(struct kprobe *p, struct pt_regs *regs,
  unsigned long flags);
3. You can retrieve the address from /proc/kallsyms

Kernel Configuration for KProbes

CONFIG_KPROBES
CONFIG_MODULES
CONFIG_MODULE_UNLOAD
CONFIG_KALLSYMS
CONFIG_DEBUG_INFO

Sample driver code which will increment the counter when fork is called

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>

MODULE_LICENSE("GPL");
static unsigned int counter = 0;
static struct kprobe kp;

int pre_handler(struct kprobe *p, struct pt_regs *regs)
{
    printk(KERN_INFO"%s:counter:%d\n",__func__, counter++);
    return 0;
}

void post_handler(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
    printk(KERN_INFO"%s:counter:%d\n",__func__, counter++);
}
static int test_kprobe_init(void)
{
    printk(KERN_INFO"%s: In init\n", __func__);
    kp.pre_handler = pre_handler;
    kp.post_handler = post_handler;
    kp.symbol_name = "_do_fork";
    register_kprobe(&kp);
    return 0;
}

static void test_kprobe_exit(void)
{
    unregister_kprobe(&kp);
    printk(KERN_INFO"%s: In exit\n", __func__);
}
module_init(test_kprobe_init);
module_exit(test_kprobe_exit);

dmesg output:






Comments

Popular posts from this blog

bb.utils.contains yocto

make config vs oldconfig vs defconfig vs menuconfig vs savedefconfig

PR, PN and PV Variable in Yocto