cebpfbpflibbpfuprobe

adding code to bpf _kernel.c file for uprobe SEC routines (libbpf +c)


I am trying function count for given executable and pattern. trying to explore latest introduced API bpf_program__attach_uprobe_multi, couldn't find example for the same. below code failing with invalid argument. added prints in libbpf code, looks like path, pattern, variable taken properly ibbpf: func pattern op_* path /data/expr/operations from libbps cnt 2 libbpf: offsets 4521 4538

libbpf: prog 'test_uprobe': failed to attach multi-uprobe: Invalid argument

Not sure what am i missing here.

Below is hardcode in kernel bpf code.

`// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
`int main(int argc, char **argv)
{
        size_t offset1;
        size_t offset2;
        int err, i;
        char filename[256];
        pid_t pid;
        struct bpf_object *obj = NULL;
        struct bpf_program *prog[2];
        static struct bpf_link *bpflinks[2];
        static struct bpf_link *ubpflinks[2];

        if (argc < 2) {
                printf("Error return \n");
                return 0;
        }
        pid = strtoul(argv[1], NULL, 10);
        snprintf(filename, 256, "/proc/%d/exe", pid);
       

        offset1 = get_elf_func_offset("/data/expr/operations", "op_add");
        offset2 = get_elf_func_offset("/data/expr/operations", "op_sub");
       
        snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
        obj = bpf_object__open_file(filename, NULL);
        if (libbpf_get_error(obj)) {
                fprintf(stderr, "ERROR: opening BPF object file failed\n");
                obj = NULL;
                goto cleanup;
        }
    
          /* load BPF program */
        if (bpf_object__load(obj)) {
                fprintf(stderr, "ERROR: loading BPF object file failed\n");
                goto cleanup;
        }
        prog[0] = bpf_object__find_program_by_name(obj, "handle_uprobe_ref_ctr");
       // prog[1] = bpf_object__find_program_by_name(obj, "handle_uretprobe_ref_ctr");

        ubpflinks[0] =
                bpf_program__attach_uprobe(prog[0], false /* not uretprobe */,
                                pid, "/data/expr/operations" , offset1);
        if (!ubpflinks[0])
                printf("failed at link0\n");

        ubpflinks[1] =
                bpf_program__attach_uprobe(prog[0], false /* not uretprobe */,
                                pid, "/data/expr/operations" , offset2);
        if (!ubpflinks[1])
                printf("failed at link1\n");
//      bpflinks[0] = bpf_program__attach(prog[0]);  // do we need to attach already probes attached
      


        getchar();
cleanup:
        bpf_link__destroy(ubpflinks[0]);
        bpf_link__destroy(ubpflinks[1]);
        return -err;
}


char LICENSE[] SEC("license") = "Dual BSD/GPL";

SEC("uprobe")
int handle_uprobe_ref_ctr(struct pt_regs *ctx)
{
    
   const char fmt_str[] = "function fp %lld ip %lld\n";
   bpf_trace_printk(fmt_str, sizeof(fmt_str), (void *)PT_REGS_FP(ctx));

        return 0;
}

SEC("uretprobe")
int handle_uretprobe_ref_ctr(struct pt_regs *ctx)
{
        bpf_printk("handle_uretprobe_ref_ctr \n");
        return 0;
}
`

Solution

  • The uprobe multi-attach support has been merged in bpf-next, but hasn't been released yet. I'd expect it to make it into Linux v6.6.

    For older kernels, you will have to rely on bpf_program__attach_uprobe:

    LIBBPF_API struct bpf_link * bpf_program__attach_uprobe (const struct bpf_program *prog, bool retprobe, pid_t pid, const char *binary_path, size_t func_offset)
    

    Note the bpf_program__attach_uprobe_multi function from libbpf also hasn't been released yet. Libbpf v1.2.2 only has bpf_program__attach_uprobe.