在eBPF中记下被叫函数的名称

问题描述 投票:1回答:1

我想跟踪特定PID的功能并收集一些统计数据(总调用次数,总次数等),对于我如何使用funcname + my_struct对创建BPF_HASH并不完全清楚。

有没有办法在BPF程序中获取被调用函数的名称?

我想我应该使用“PT_REGS_IP(ctx)”读取IP寄存器,但我不完全理解如何将值转换为人类可读的字符串。

目前,BPF计划以下列方式展望:

#include <uapi/linux/ptrace.h>
#include <linux/sched.h>

struct data_t {
    u32 pid;
    u64 delta;
    u64 start;
} __attribute__((packed));

BPF_HASH(faddr, u64, struct data_t);
BPF_PERF_OUTPUT(events);

int do_entry(struct pt_regs *ctx) {
    struct data_t *data;
    data->start = bpf_ktime_get_ns();
    u64 ip = PT_REGS_IP(ctx);
    faddr.update(&ip, data);

    return 0;
}

int do_return(struct pt_regs *ctx) {
    struct data_t *data;
    u64 ip = PT_REGS_IP(ctx);
    data = faddr.lookup(&ip);

    if (data->start == 0)
        return 0;       // missed start

    data->delta = bpf_ktime_get_ns() - data->start;
    data->pid = bpf_get_current_pid_tgid();

    events.perf_submit(ctx, &data, sizeof(data));
    faddr.delete(&ip);

    return 0;
}

但在创业时我得到了:

error: <unknown>:0:0: in function do_entry i32 (%struct.pt_regs*): A call to built-in function 'abort' is not supported.
trace bpf ebpf
1个回答
2
投票

你的do_entry函数有错误。您正尝试取消引用空指针:

struct data_t *data;
data->start = bpf_ktime_get_ns();

以下应该更好:

int do_entry(struct pt_regs *ctx) {
    struct data_t data = {}; // initializes data with zeros.
    data.start = bpf_ktime_get_ns();
    u64 ip = PT_REGS_IP(ctx);
    faddr.update(&ip, &data);
    return 0;
}

我不明白为什么错误信息提及abort虽然。我会四处询问。


如何将内存地址转换为函数名将取决于您正在使用的用户空间库。如果你正在使用密件抄送,你可以使用ksym方法。我不知道是否有相当于gobpf的东西。


你在do_return中至少还有一个错误:

data = faddr.lookup(&ip);
if (data->start == 0)
    return 0;       // missed start

在解除引用之前,您需要检查data是否为null。否则,验证者将拒绝您的程序。

data = faddr.lookup(&ip);
if (!data || data->start == 0)
    return 0;       // missed start
© www.soinside.com 2019 - 2024. All rights reserved.