Commit 5bfdd32d authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov
Browse files

libbpf: Add support for u[ret]probe.multi[.s] program sections



Adding support for several uprobe_multi program sections
to allow auto attach of multi_uprobe programs.

Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20230809083440.3209381-16-jolsa@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 3140cf12
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line Diff line number Diff line
@@ -8701,6 +8701,7 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin
static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);
static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);


@@ -8716,6 +8717,10 @@ static const struct bpf_sec_def section_defs[] = {
	SEC_DEF("uretprobe.s+",		KPROBE, 0, SEC_SLEEPABLE, attach_uprobe),
	SEC_DEF("uretprobe.s+",		KPROBE, 0, SEC_SLEEPABLE, attach_uprobe),
	SEC_DEF("kprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
	SEC_DEF("kprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
	SEC_DEF("kretprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
	SEC_DEF("kretprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
	SEC_DEF("uprobe.multi+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
	SEC_DEF("uretprobe.multi+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
	SEC_DEF("uprobe.multi.s+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi),
	SEC_DEF("uretprobe.multi.s+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi),
	SEC_DEF("ksyscall+",		KPROBE,	0, SEC_NONE, attach_ksyscall),
	SEC_DEF("ksyscall+",		KPROBE,	0, SEC_NONE, attach_ksyscall),
	SEC_DEF("kretsyscall+",		KPROBE, 0, SEC_NONE, attach_ksyscall),
	SEC_DEF("kretsyscall+",		KPROBE, 0, SEC_NONE, attach_ksyscall),
	SEC_DEF("usdt+",		KPROBE,	0, SEC_NONE, attach_usdt),
	SEC_DEF("usdt+",		KPROBE,	0, SEC_NONE, attach_usdt),
@@ -10922,6 +10927,37 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
	return libbpf_get_error(*link);
	return libbpf_get_error(*link);
}
}


static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link)
{
	char *probe_type = NULL, *binary_path = NULL, *func_name = NULL;
	LIBBPF_OPTS(bpf_uprobe_multi_opts, opts);
	int n, ret = -EINVAL;

	*link = NULL;

	n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%ms",
		   &probe_type, &binary_path, &func_name);
	switch (n) {
	case 1:
		/* handle SEC("u[ret]probe") - format is valid, but auto-attach is impossible. */
		ret = 0;
		break;
	case 3:
		opts.retprobe = strcmp(probe_type, "uretprobe.multi") == 0;
		*link = bpf_program__attach_uprobe_multi(prog, -1, binary_path, func_name, &opts);
		ret = libbpf_get_error(*link);
		break;
	default:
		pr_warn("prog '%s': invalid format of section definition '%s'\n", prog->name,
			prog->sec_name);
		break;
	}
	free(probe_type);
	free(binary_path);
	free(func_name);
	return ret;
}

static void gen_uprobe_legacy_event_name(char *buf, size_t buf_sz,
static void gen_uprobe_legacy_event_name(char *buf, size_t buf_sz,
					 const char *binary_path, uint64_t offset)
					 const char *binary_path, uint64_t offset)
{
{