Commit b63b3c49 authored by Jiri Olsa's avatar Jiri Olsa Committed by Daniel Borkmann
Browse files

libbpf: Add bpf_program__set_insns function



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: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20220510074659.2557731-2-jolsa@kernel.org
parent 5eefe17c
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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)
{
+18 −0
Original line number Diff line number Diff line
@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -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;