0

We are trying to port an existing bcc solution to libbpf + c. The problem is we need to support older kernels too i.e. at least 5.5.

Functionality: uprobe for user executable with function pattern etc i.e. need bpf_program__attach_uprobe_multi functionality. We have to achieve the same with bpf_program__attach_uprobe Looked at examples in libbpf-bootstrap and bcc/libbpf-tools/, and all of them installed one function per uprobe handler.

We are trying to get the address of the traced function with bpf_get_func_ip(void *ctx) but it is returning a zero ip, looks like works only for kprobes.

Is there any way to get the ip of a uprobe function that is traced? Maybe cookies are the way to detect which user function is called. Or should I read from this (void *)PT_REGS_IP(ctx)?

Tried the following example. Is anything missing here? Is there any boilerplate example for the same?

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 program, 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)
{
    __u64 addr = bpf_get_func_ip(ctx);
   const char fmt_str[] = "function fp %lld ip %lld\n";
   bpf_trace_printk(fmt_str, sizeof(fmt_str), (void *)PT_REGS_FP(ctx), addr);

        return 0;
}

SEC("uretprobe")
int handle_uretprobe_ref_ctr(struct pt_regs *ctx)
{
        bpf_printk("handle_uretprobe_ref_ctr \n");
        return 0;
}
some executable operations
void op_add(int a, int b)
 {
 }

 void op_sub(int a, int b)
 {

 }


 int main()
 {
     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);
         sleep(1);
     }

     return 0;
 }

opeonikute
  • 494
  • 1
  • 4
  • 15
nullptr
  • 5
  • 3

0 Answers0