Skip to content

support: 如何获取 tp/kprobe 函数本身的 IP #14

@Ghostbaby

Description

@Ghostbaby
  1. kprobe/fentry 等类型使用 bpf_get_func_ip
  2. tracepoint 类型,bpf_get_func_ip() 返回的是触发 tracepoint 的函数地址,而不是 tracepoint 本身的地址。
// 使用  bpf_get_stack() 
struct {
    __uint(type, BPF_MAP_TYPE_STACK_TRACE);
    __uint(max_entries, 1024);
} stack_traces SEC(".maps");

SEC("tracepoint/syscalls/sys_enter_open")
int trace_open_stack(struct trace_event_raw_sys_enter *ctx)
{
    u64 stack_id = bpf_get_stackid(ctx, &stack_traces, BPF_F_FAST_STACK_CMP);
    
    // 或者直接获取栈帧
    u64 stack[10];
    int ret = bpf_get_stack(ctx, stack, sizeof(stack), 0);
    if (ret > 0) {
        // stack[0] 是当前执行的指令地址
        bpf_printk("Current IP: 0x%lx\n", stack[0]);
    }
    
    return 0;
}

// 使用 task_struct 获取到 寄存器信息,然后通过 bpf_get_func_ip(ctx) 
SEC("tracepoint/syscalls/sys_enter_open")
int trace_open_task(struct trace_event_raw_sys_enter *ctx)
{
    struct task_struct *task = (struct task_struct *)bpf_get_current_task();
    
    // 从任务结构中读取 pt_regs(如果可用)
    // 这种方法较为复杂,需要了解内核内部结构
    
    return 0;
}

tracepoint 介绍

tracepoint 是编译时就确定的静态插桩点,不像 kprobe 是动态插桩:

// 内核代码中的 tracepoint 定义示例
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
    trace_sys_enter(regs, __NR_open);  // 这里触发 tracepoint
    
    // 实际的系统调用逻辑
    long ret = do_sys_open(AT_FDCWD, filename, flags, mode);
    
    trace_sys_exit(regs, ret);         // 这里触发 tracepoint
    return ret;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions