BruceChen7 / gitblog

My blog
6 stars 1 forks source link

pwru的分析 #52

Open BruceChen7 opened 1 year ago

BruceChen7 commented 1 year ago

参考资料

(usage:: C 代码如何与 go 代码联动)

// main_amd64.go
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (C) 2021 Authors of Cilium */

//go:generate sh -c "echo Generating for amd64"
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang KProbePWRU ./bpf/kprobe_pwru.c -- -DOUTPUT_SKB -D__TARGET_ARCH_x86 -I./bpf/headers -Wno-address-of-packed-member
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang KProbeMultiPWRU ./bpf/kprobe_pwru.c -- -DOUTPUT_SKB -DHAS_KPROBE_MULTI -D__TARGET_ARCH_x86 -I./bpf/headers -Wno-address-of-packed-member
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang KProbePWRUWithoutOutputSKB ./bpf/kprobe_pwru.c -- -D__TARGET_ARCH_x86 -I./bpf/headers -Wno-address-of-packed-member
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang KProbeMultiPWRUWithoutOutputSKB ./bpf/kprobe_pwru.c -- -D HAS_KPROBE_MULTI -D__TARGET_ARCH_x86 -I./bpf/headers -Wno-address-of-packed-member
//go:generate go run ./tools/getgetter.go -struct ^(KProbePWRU|KProbeMultiPWRU|KProbePWRUWithoutOutputSKB|KProbeMultiPWRUWithoutOutputSKB)(Programs|Maps)$
package main

定义探针

#ifdef HAS_KPROBE_MULTI
#define PWRU_KPROBE_TYPE "kprobe.multi"
#define PWRU_HAS_GET_FUNC_IP true
#else
#define PWRU_KPROBE_TYPE "kprobe"
#define PWRU_HAS_GET_FUNC_IP false
#endif /* HAS_KPROBE_MULTI */

// 添加相关的探针
#define PWRU_ADD_KPROBE(X)                                                     \
  SEC(PWRU_KPROBE_TYPE "/skb-" #X)                                             \
  int kprobe_skb_##X(struct pt_regs *ctx) {                                    \
    struct sk_buff *skb = (struct sk_buff *) PT_REGS_PARM##X(ctx);             \
    return handle_everything(skb, ctx, PWRU_HAS_GET_FUNC_IP);                  \
  }

PWRU_ADD_KPROBE(1)
PWRU_ADD_KPROBE(2)
PWRU_ADD_KPROBE(3)
PWRU_ADD_KPROBE(4)
PWRU_ADD_KPROBE(5)

#undef PWRU_KPROBE
#undef PWRU_HAS_GET_FUNC_IP
#undef PWRU_KPROBE_TYPE

char __license[] SEC("license") = "GPL";

定义 map

struct {
    __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY)
} events SEC(".maps")

struct {
    __uint(type, BPF_MAP_TYPE_STACK_TRACE);
    __uint(max_entries, 256);
    __uint(key_size, sizeof(u32));
    __uint(value_size, MAX_STACK_DEPTH * sizeof(u64));
} print_stack_map SEC(".maps");

主要逻辑

static __noinline int
handle_everything(struct sk_buff *skb, struct pt_regs *ctx, bool has_get_func_ip) {
    struct event_t event = {};

    if (cfg->is_set) {
        if (!filter(skb)) {
            return 0;
        }

        set_output(ctx, skb, &event);
    }

    event.pid = bpf_get_current_pid_tgid();
    event.addr = has_get_func_ip ? bpf_get_func_ip(ctx) : PT_REGS_IP(ctx);
    event.skb_addr = (u64) skb;
    event.ts = bpf_ktime_get_ns();
    event.cpu_id = bpf_get_smp_processor_id();
    event.param_second = PT_REGS_PARM2(ctx);

    bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));

    return 0;
}

type/code #type/ebpf #public