在eBPF中获取被调用函数的名称

时间:2018-11-19 11:43:57

标签: trace bpf ebpf

我想跟踪特定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.

1 个答案:

答案 0 :(得分: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