libbpf: Add bpf_program__set_insns function
authorJiri Olsa <jolsa@kernel.org>
Tue, 10 May 2022 07:46:57 +0000 (09:46 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 11 May 2022 12:15:17 +0000 (14:15 +0200)
Adding bpf_program__set_insns that allows to set new instructions
for a BPF program.

This is a very advanced libbpf API and users need to know what
they are doing. This should be used from prog_prepare_load_fn
callback only.

We can have changed instructions after calling prog_prepare_load_fn
callback, reloading them.

One of the users of this new API will be perf's internal BPF prologue
generation.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20220510074659.2557731-2-jolsa@kernel.org
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/bpf/libbpf.map

index 0e74fae2589623b9b809895be1471e777cb9dcae..4867a930628b524eeb653505e45327ae0fa53313 100644 (file)
@@ -6860,6 +6860,8 @@ static int bpf_object_load_prog_instance(struct bpf_object *obj, struct bpf_prog
                                prog->name, err);
                        return err;
                }
+               insns = prog->insns;
+               insns_cnt = prog->insns_cnt;
        }
 
        if (obj->gen_loader) {
@@ -8788,6 +8790,26 @@ size_t bpf_program__insn_cnt(const struct bpf_program *prog)
        return prog->insns_cnt;
 }
 
+int bpf_program__set_insns(struct bpf_program *prog,
+                          struct bpf_insn *new_insns, size_t new_insn_cnt)
+{
+       struct bpf_insn *insns;
+
+       if (prog->obj->loaded)
+               return -EBUSY;
+
+       insns = libbpf_reallocarray(prog->insns, new_insn_cnt, sizeof(*insns));
+       if (!insns) {
+               pr_warn("prog '%s': failed to realloc prog code\n", prog->name);
+               return -ENOMEM;
+       }
+       memcpy(insns, new_insns, new_insn_cnt * sizeof(*insns));
+
+       prog->insns = insns;
+       prog->insns_cnt = new_insn_cnt;
+       return 0;
+}
+
 int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
                          bpf_program_prep_t prep)
 {
index a1fb91810378818b702678d2f2a47ed8316d195f..21984dcd6dbec1cb5b8d2a78b6b3455aa285d5da 100644 (file)
@@ -323,6 +323,24 @@ struct bpf_insn;
  * different.
  */
 LIBBPF_API const struct bpf_insn *bpf_program__insns(const struct bpf_program *prog);
+
+/**
+ * @brief **bpf_program__set_insns()** can set BPF program's underlying
+ * BPF instructions.
+ *
+ * WARNING: This is a very advanced libbpf API and users need to know
+ * what they are doing. This should be used from prog_prepare_load_fn
+ * callback only.
+ *
+ * @param prog BPF program for which to return instructions
+ * @param new_insns a pointer to an array of BPF instructions
+ * @param new_insn_cnt number of `struct bpf_insn`'s that form
+ * specified BPF program
+ * @return 0, on success; negative error code, otherwise
+ */
+LIBBPF_API int bpf_program__set_insns(struct bpf_program *prog,
+                                     struct bpf_insn *new_insns, size_t new_insn_cnt);
+
 /**
  * @brief **bpf_program__insn_cnt()** returns number of `struct bpf_insn`'s
  * that form specified BPF program.
index 80819e26a976dda8852f7dcf60a8c32a96a14669..008da8db1d94c085f9732b88b76701d5ea7d6d01 100644 (file)
@@ -449,6 +449,7 @@ LIBBPF_0.8.0 {
                bpf_program__attach_kprobe_multi_opts;
                bpf_program__attach_trace_opts;
                bpf_program__attach_usdt;
+               bpf_program__set_insns;
                libbpf_register_prog_handler;
                libbpf_unregister_prog_handler;
 } LIBBPF_0.7.0;