Requirement is attaching tmultiple target functions for the same uprobe handler. With bpftool generated skeleton code, attaching uprobe gives multiple links but skeleton data structure doesn't have prior information. how to manage this with skeleton code.
below code is trying to attach multiple user functions (add and sub) to same uprobe handler, will get two bpf_links that are not known to skeleton code. they can't be assigned to skeleton managed program links because skeleton code created one link for one program handler. Can't skip calling uprobe_bpf__attach(obj) there are other programs in the skeleton that needs to be attached.
Skeleton code
struct uprobe_bpf {
struct bpf_object_skeleton *skeleton;
struct bpf_object *obj;
struct {
struct bpf_map *rodata_str1_1;
struct bpf_map *rodata;
} maps;
struct {
struct bpf_program *uprobe_handler;
struct bpf_program *uretprobe_handler;
} progs;
struct {
struct bpf_link *uprobe_handler;
struct bpf_link *uretprobe_handler;
} links;
};
int main(int argc, char *argv[])
{
int err;
struct bpf_link *ulink[2] = {NULL};
struct uprobe_bpf *obj = NULL;
unsigned long func_offset[2];
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
libbpf_set_print(libbpf_print_fn);
err = argp_parse(&argp, argc, argv, 0, 0, &env);
if (err)
return err;
pid_t pid = env.pid;
printf("PID %d \n ", pid);
func_offset[0] = get_elf_func_offset("/data/expr/operations", "op_add");
func_offset[1] = get_elf_func_offset("/data/expr/operations", "op_sub");
// uprobe_opts.retprobe = false;
obj = uprobe_bpf__open_and_load();
if (!obj) {
printf("errr skel not found \n");
return 0;
}
uprobe_opts.bpf_cookie = 24;
uprobe_opts.retprobe = false;
ulink[0] = bpf_program__attach_uprobe_opts(obj->progs.uprobe_handler,
pid, "/data/expr/operations" , func_offset[0], &uprobe_opts);
if (!ulink[0]) {
printf("failed at 0\n");
goto cleanup;
}
uprobe_opts.bpf_cookie = 26;
ulink[1] =
bpf_program__attach_uprobe_opts(obj->progs.uprobe_handler,
pid, "/data/expr/operations" , func_offset[1], &uprobe_opts);
if (!ulink[1]) {
printf(" failed at 1\n");
goto cleanup;
}
err = uprobe_bpf__attach(obj); // will it attach uprobe handler again ??
if (err) {
printf("attach failed \n");
goto cleanup;
}
getchar();
cleanup:
bpf_link__destroy(ulink[0]);
bpf_link__destroy(ulink[1]);
uprobe_bpf__destroy(obj);
return 0;
}
kernel bpf program
SEC("uprobe")
int uprobe_handler(struct pt_regs *ctx)
{
__u64 cookie = bpf_get_attach_cookie(ctx);
const char fmt_str[] = "function ip %lld cookie %lld \n";
bpf_trace_printk(fmt_str, sizeof(fmt_str), (void *)PT_REGS_IP(ctx), cookie);
return 0;
}
SEC("uretprobe")
int uretprobe_handler(struct pt_regs *ctx)
{
bpf_printk("handle_uretprobe_ref_ctr \n");
return 0;
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";
// some operations executable
void op_add(int a, int b)
{
}
void op_sub(int a, int b)
{
}
int main()
{
int fcount = 0;
printf("add %p sub %p \n", &op_add, &op_sub);
printf("pid %d\n",getpid());
for (int i = 0;; i++) {
/* trigger our BPF programs */
fprintf(stderr, ".");
op_add(i, i + 1);
op_sub(i * i, i);
}
return 0;
}