lcc/glcc/lib/ebpf/ebpf_kprobe.c (79 lines of code) (raw):

#include "ebpf_kprobe.h" #define KPROBE_MAGIC 0x22 static __always_inline void __bpf_kprobe_run(struct bpf_prog *prog, u64 *args) { rcu_read_lock(); preempt_disable(); (void)BPF_PROG_RUN(prog, args); preempt_enable(); rcu_read_unlock(); } static int bpf_kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) { struct bpf_kprobe_event *bke = container_of(kp, struct bpf_kprobe_event, rp.kp); __bpf_kprobe_run(bke->prog, (u64 *)regs); return 0; } static int bpf_kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) { struct bpf_kprobe_event *bke = container_of(ri->rp, struct bpf_kprobe_event, rp); __bpf_kprobe_run(bke->prog, (u64 *)regs); return 0; } struct bpf_kprobe_event *alloc_bpf_kprobe_event(struct bpf_prog *prog, const char *symbol, bool is_return) { struct bpf_kprobe_event *bke; int err = 0; bke = kzalloc(sizeof(*bke), GFP_USER); if (!bke) return ERR_PTR(-ENOMEM); bke->is_return = is_return; // todo: alloc nhit if (symbol) { bke->symbol = kstrdup(symbol, GFP_USER); if (!bke->symbol) { err = -ENOMEM; goto free_bke; } bke->rp.kp.symbol_name = bke->symbol; } else { printk(KERN_ERR "BUG: no symbol exists\n"); err = -EINVAL; goto free_bke; } if (is_return) bke->rp.handler = bpf_kretprobe_dispatcher; else bke->rp.kp.pre_handler = bpf_kprobe_dispatcher; bke->prog = prog; return bke; // free_symbol: // kfree(bke->symbol); free_bke: kfree(bke); return ERR_PTR(err); } void free_bpf_kprobe_event(struct bpf_kprobe_event *bke) { kfree(bke->symbol); kfree(bke); } // attach k(ret)probe int bpf_kprobe_register(struct bpf_kprobe_event *bke) { int err; if (bke->is_return) err = register_kretprobe(&bke->rp); else err = register_kprobe(&bke->rp.kp); printk("Register %s: name - %s, error: %u\n", bke->is_return ? "kretprobe" : "kprobe", bke->symbol, err); return err; } void bpf_kprobe_unregister(struct bpf_kprobe_event *bke) { if (bke->is_return) unregister_kretprobe(&bke->rp); else unregister_kprobe(&bke->rp.kp); printk("Unegister %s: name - %s\n", bke->is_return ? "kretprobe" : "kprobe", bke->symbol); }