trace系列5 - kretprobe学习笔记

本文详细介绍了kretprobe的工作流程,包括kretprobe的注册、断点指令的插入及kretprobe回调的执行过程。通过具体示例blk_update_request函数,深入解析了kretprobe如何在函数返回时捕获并执行特定的回调。

1.前言

本文主要是根据阅码场 《Linux内核tracers的实现原理与应用》视频课程在aarch64上的实践。通过观察钩子函数的创建过程以及替换过程,理解trace的原理。本文同样以blk_update_request函数为例进行说明kretprobe的工作原理,此处的kretprobe是基于trace event来实现,同时使用了ftrace的框架。

kernel版本:5.10
平台:arm64

2. kretprobe领域模型

在这里插入图片描述
trace系列3 - kretprobe学习笔记
kretprobe_instance : 记录了原始的返回地址,以及所属的kretprobe,作为kretprobe实例连入kretprobe的free_instancesl链表,当kretprobe_instance 被初始化后,它将从free_instancesl链表移除;重新连入全局kretprobe_inst_table链表

3. kretprobe创建

在执行如下指令时,会完成kretprobe的创建:

#echo 'r:blk_update blk_update_request $retval' > /sys/kernel/debug/tracing/kprobe_events

此过程主要通过调用create_or_delete_trace_kprobe,最主要的设置pre_handler为pre_handler_kretprobe,同时设置了打印格式,并完成trace_kprobe的注册。与kprobe创建时的主要区别在于:rp->kp.pre_handler初始化和kretprobe.handler初始化

3.1 rp->kp.pre_handler初始化

create_or_delete_trace_kprobe -> 
    trace_kprobe_create ->
        register_trace_kprobe -> 
            __register_trace_kprobe

会调用register_kretprobe,它初始化了pre_handler为pre_handler_kretprobe

int register_kretprobe(struct kretprobe *rp)
{
   
   
        int ret = 0;
        struct kretprobe_instance *inst;
        int i;
        void *addr;

        if (!kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset))
                return -EINVAL;

        if (kretprobe_blacklist_size) {
   
   
                addr = kprobe_addr(&rp->kp);
                if (IS_ERR(addr))
                        return PTR_ERR(addr);

                for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
   
   
                        if (kretprobe_blacklist[i].addr == addr)
                                return -EINVAL;
                }
        }
        //初始化pre_handler回调
        rp->kp.pre_handler = pre_handler_kretprobe;
        rp->kp.post_handler = NULL;
        rp->kp.fault_handler = NULL;

        /* Pre-allocate memory for max kretprobe instances */
        if (rp->maxactive <= 0) {
   
   
#ifdef CONFIG_PREEMPTION
                //此处为10
                rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus());
#else
                rp->maxactive = num_possible_cpus();
#endif
        }
        raw_spin_lock_init(&rp->lock);
        INIT_HLIST_HEAD(&rp->free_instances);
        //本例中rp->maxactive为10,循环创建10个kretprobe_instance,并连入kretprobe.free_instances链表
        //此处可以看出一个kretprobe可以有多个kretprobe_instance实例
        for (i = 0; i < rp->maxactive; i++) {
   
   
                inst = kmalloc(sizeof(struct kretprobe_instance) +
                               rp->data_size, GFP_KERNEL);
                if (inst == NULL) {
   
   
                        free_rp_inst(rp);
                        return -ENOMEM;
                }    
                INIT_HLIST_NODE(&inst->hlist);
                hlist_add_head(&inst->hlist, &rp->free_instances);
        }

        rp->nmissed = 0;
        /* Establish function entry probe point */
        ret = register_kprobe(&rp->kp);
        if (ret != 0)
                free_rp_inst(rp);
        return ret;
}

3.2 kretprobe.handler初始化

create_or_delete_trace_kprobe -> 
    trace_kprobe_create ->
       alloc_trace_kprobe
  • alloc_trace_kprobe:为trace_kprobe分配空间,主要初始化了kreprobe的handler为kretprobe_dispatcher

4. kretprobe brk指令替换

先来看下未替换指令前blk_update_request的反汇编:

Dump of assembler code for function blk_update_request:
   0xffff8000104ec1f0 <+0>:     sub     sp, sp, #0x60
   0xffff8000104ec1f4 <+4>:     stp     x29, x30, [sp,#16]
   0xffff8000104ec1f8 <+8>:     add     x29, sp, #0x10
   0xffff8000104ec1fc <+12>:    stp     x19, x20, [sp,#32]
   0xffff8000104ec200 <+16>:    stp     x21, x22, [sp,#48]
   0xffff8000104ec204 <+20>:    stp     x23, x24, [sp,#64]
   0xffff8000104ec208 <+24>:    str     x25, [sp,#80]
   0xffff8000104ec20c <+28>:    mov     x22, x0
   0xffff8000104ec210 <+32>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值