Fault location technology on Red Hat Linux

  

kprobe is the implementation of systemTap probing function for kernel functions in the kernel. Since the kernel provides a formal API to use kprobe, it may be more convenient for many kernel programmers to use kprobe directly than to use SystemTap. Three types of kprobe handlers are provided in the kernel, namely jprobe, kprobe, kretprobe. The following code uses these three probes to observe the return result of the ip_route_input() call in the TCP/IP arp_process function execution. This code also Shows the method of sharing parameters between the Entry handler and the Ret handler of the same function probe. The code is as follows:

arp_probe.c /* * arp_probe.c, by Qianfeng Zhang ([email protected]) * /

#include #include #include #include #include #include #include #include#br>

MODULE_AUTHOR("[email protected]"); MODULE_DESCRIPTION("A module to track the Call results of ip_route_input() inside arp_process using jprobe and kretprobe"); MODULE_LICENSE("GPL");

static int j_arp_process(struct sk_buff *skb) { struct net_d Evice *dev = skb->dev; struct in_device *in_dev; int no_addr, rpf;

in_dev = in_dev_get(dev); no_addr = ( in_dev->ifa_list == NULL ); rpf = IN_DEV_RPFILTER( in_dev); in_dev_put (in_dev); printk (" \\ narp_process () is called with interface device% s, in_dev (no_addr =% d, rpf =% d) \\ n ", dev- & gt; name, no_addr, rpf) Jprobe_return(); return(0); };

static int j_fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, struct net_device *dev, __be32 *spec_dst, u32 *itag, u32 mark)

{ printk("fib_validate_source() is called with dst=0x%x, oif=%d \ ", dst, oif); jprobe_return(); return(0); };

static struct jprobe my_jp1 = { .entry = j_arp_process, .kp.symbol_name = "arp_process" };


static struct jprobe my_jp2 = { .entry = j_fib_validate_source, .kp .symbol_name = "fib_validate_source" };

static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { printk("Calling: %s()\ ", ri-> ;rp->kp.symbol_name); return(0); };

static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { int eax;

eax = regs ->ax & 0xffff ; printk("Returning: %s() with a return value: 0x%lx(64bit) 0x%x(32bit)\ ", ri->rp->kp.symbol_name , regs->ax, eax);

return(0); };

static int fib_lookup_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { struct fib_result *resp;< Br>

resp = (struct fib_result *) regs->dx; printk("Calling: %s()\ ", ri->rp->kp.symbol_name); *((struct fib_result **)ri->data) = resp;

return(0); };


static int fib_lookup_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs { struct fib_result *resp; int eax;

eax = regs->ax & 0xffff ; resp = *((struct fib_result **) ri->data); printk("Returning: ;: fib_lookup () with a return value type 0x% 0x% lx (64bit) (32bit), result- & gt x:% d \\ n ", regs- & gt; ax, eax, resp- & gt; type);

return (0);}

static struct kretprobe my_rp1 = {.handler = return_handler, .entry_handler = entry_handler, .kp.symbol_name = " ip_route_input_slow "};


static struct kretprobe my_rp2 = {.handler = return_handler, .entry_handler = entry_handler, .kp.symbol_name = " fib_validate_source "};


static struct kretprobe my_rp3 = { .handler = fib_lookup_return_handler, .entry_handler = fib_lookup_entry_handler, .kp.symbol_name = "fib_lookup", .data_size = sizeof(struct fib_result *) };

static int __init init_myprobe(void { int ret;

printk("RTN_UNICAST is %d\ ", RTN_UNICAST); if ( (ret = register_jprobe(&my_jp1)) < 0) { printk("register_jprobe %s failed, returned% d \\ n ", my_jp1.kp.symbol_name, ret); return (-1);}

if ((ret = register_jprobe (& my_jp2)) & lt; 0) {printk ( "register_jprobe %s failed, returned %d\ ", my_jp2.kp.symbol_name, ret); return(-1); }< Br>

if ( (ret = register_kretprobe(&my_rp1)) < 0 ) { printk("register_kretprobe %s failed, returned %d\ ", my_rp1.kp.symbol_name, ret); unregister_jprobe(& ; my_jp1); unregister_jprobe (& my_jp2); return (-1);}

if ((ret = register_kretprobe (& my_rp2)) & lt; 0) {printk (" register_kretprobe% s failed, Return %d\ ", my_rp2.kp.symbol_name, ret); unregister_jprobe(&my_jp1); unregister_jprobe(&my_jp2); unregister_kretprobe(&my_rp1); return(-1); }

If ( (ret = register_kretprobe(&my_rp3)) < 0 ) { printk("register_kretprobe %s failed, returned %d\ ", my_rp3.kp.symbol_name, ret); unregister_jprobe(&my_jp1); unregister_jprobe (&my_jp2); unregister_kretprobe(&my_rp1); unregister_kretprobe(&my_rp2); return(-1); }

return 0; }

Copyright © Windows knowledge All Rights Reserved