mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Menglong Dong <menglong8.dong@gmail.com>
To: alexei.starovoitov@gmail.com, rostedt@goodmis.org, jolsa@kernel.org
Cc: bpf@vger.kernel.org, Menglong Dong <dongml2@chinatelecom.cn>,
	linux-kernel@vger.kernel.org
Subject: [PATCH bpf-next 21/25] libbpf: add skip_invalid and attach_tracing for tracing_multi
Date: Wed, 28 May 2025 11:47:08 +0800	[thread overview]
Message-ID: <20250528034712.138701-22-dongml2@chinatelecom.cn> (raw)
In-Reply-To: <20250528034712.138701-1-dongml2@chinatelecom.cn>

We add skip_invalid and attach_tracing for tracing_multi for the
selftests.

When we try to attach all the functions in available_filter_functions with
tracing_multi, we can't tell if the target symbol can be attached
successfully, and the attaching will fail. When skip_invalid is set to
true, we will check if it can be attached in libbpf, and skip the invalid
entries.

We will skip the symbols in the following cases:

1. the btf type not exist
2. the btf type is not a function proto
3. the function args count more that 6
4. the return type is struct or union
5. any function args is struct or union

The 5th rule can be a manslaughter, but it's ok for the testings.

"attach_tracing" is used to convert a TRACING prog to TRACING_MULTI. For
example, we can set the attach type to FENTRY_MULTI before we load the
skel. And we can attach the prog with
bpf_program__attach_trace_multi_opts() with "attach_tracing=1". The libbpf
will attach the target btf type of the prog automatically. This is also
used to reuse the selftests of tracing.

(Oh my goodness! What am I doing?)

Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
 tools/lib/bpf/libbpf.c | 97 ++++++++++++++++++++++++++++++++++++------
 tools/lib/bpf/libbpf.h |  6 ++-
 2 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 4a903102e0c7..911fda3f678c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -10132,7 +10132,8 @@ static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd, int t
 
 static int find_kernel_btf_id(struct bpf_object *obj, const char *attach_name,
 			      enum bpf_attach_type attach_type,
-			      int *btf_obj_fd, int *btf_type_id, bool use_hash)
+			      int *btf_obj_fd, int *btf_type_id, bool use_hash,
+			      const struct btf **btf)
 {
 	int ret, i, mod_len, err;
 	const char *fn_name, *mod_name = NULL;
@@ -10156,6 +10157,8 @@ static int find_kernel_btf_id(struct bpf_object *obj, const char *attach_name,
 		if (ret > 0) {
 			*btf_obj_fd = 0; /* vmlinux BTF */
 			*btf_type_id = ret;
+			if (btf)
+				*btf = obj->btf_vmlinux;
 			return 0;
 		}
 		if (ret != -ENOENT)
@@ -10183,6 +10186,8 @@ static int find_kernel_btf_id(struct bpf_object *obj, const char *attach_name,
 		if (ret > 0) {
 			*btf_obj_fd = mod->fd;
 			*btf_type_id = ret;
+			if (btf)
+				*btf = mod->btf;
 			return 0;
 		}
 		if (ret == -ENOENT)
@@ -10226,7 +10231,7 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac
 	} else {
 		err = find_kernel_btf_id(prog->obj, attach_name,
 					 attach_type, btf_obj_fd,
-					 btf_type_id, false);
+					 btf_type_id, false, NULL);
 	}
 	if (err) {
 		pr_warn("prog '%s': failed to find kernel BTF type ID of '%s': %s\n",
@@ -12836,6 +12841,53 @@ static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_
 	return libbpf_get_error(*link);
 }
 
+static bool is_trace_valid(const struct btf *btf, int btf_type_id, const char *name)
+{
+	const struct btf_type *t;
+
+	t = skip_mods_and_typedefs(btf, btf_type_id, NULL);
+	if (btf_is_func(t)) {
+		const struct btf_param *args;
+		__u32 nargs, m;
+
+		t = skip_mods_and_typedefs(btf, t->type, NULL);
+		if (!btf_is_func_proto(t)) {
+			pr_debug("skipping no function btf type for %s\n",
+				 name);
+			return false;
+		}
+
+		args = (const struct btf_param *)(t + 1);
+		nargs = btf_vlen(t);
+		if (nargs > 6) {
+			pr_debug("skipping args count more than 6 for %s\n",
+				 name);
+			return false;
+		}
+
+		t = skip_mods_and_typedefs(btf, t->type, NULL);
+		if (btf_is_struct(t) || btf_is_union(t) ||
+		    (nargs && args[nargs - 1].type == 0)) {
+			pr_debug("skipping invalid return type for %s\n",
+				 name);
+			return false;
+		}
+
+		for (m = 0; m < nargs; m++) {
+			t = skip_mods_and_typedefs(btf, args[m].type, NULL);
+			if (btf_is_struct(t) || btf_is_union(t)) {
+				pr_debug("skipping not supported arg type %s\n",
+					 name);
+				break;
+			}
+		}
+		if (m < nargs)
+			return false;
+	}
+
+	return true;
+}
+
 struct bpf_link *bpf_program__attach_trace_multi_opts(const struct bpf_program *prog,
 						      const struct bpf_trace_multi_opts *opts)
 {
@@ -12856,7 +12908,7 @@ struct bpf_link *bpf_program__attach_trace_multi_opts(const struct bpf_program *
 
 	cnt = OPTS_GET(opts, cnt, 0);
 	if (opts->syms) {
-		int btf_obj_fd, btf_type_id, i;
+		int btf_obj_fd, btf_type_id, i, j = 0;
 
 		if (opts->btf_ids || opts->tgt_fds) {
 			pr_warn("can set both opts->syms and opts->btf_ids\n");
@@ -12870,23 +12922,41 @@ struct bpf_link *bpf_program__attach_trace_multi_opts(const struct bpf_program *
 			goto err_free;
 		}
 		for (i = 0; i < cnt; i++) {
+			const struct btf *btf = NULL;
+			bool func_hash;
+
 			/* only use btf type function hashmap when the count
 			 * is big enough.
 			 */
-			bool func_hash = cnt > 1024;
-
-
+			func_hash = cnt > 1024;
 			btf_obj_fd = btf_type_id = 0;
 			err = find_kernel_btf_id(prog->obj, opts->syms[i],
-					 prog->expected_attach_type, &btf_obj_fd,
-					 &btf_type_id, func_hash);
-			if (err)
-				goto err_free;
-			btf_ids[i] = btf_type_id;
-			tgt_fds[i] = btf_obj_fd;
+					prog->expected_attach_type, &btf_obj_fd,
+					&btf_type_id, func_hash, &btf);
+			if (err) {
+				if (!opts->skip_invalid)
+					goto err_free;
+
+				pr_debug("can't find btf type for %s, skip\n",
+					 opts->syms[i]);
+				continue;
+			}
+
+			if (opts->skip_invalid &&
+			    !is_trace_valid(btf, btf_type_id, opts->syms[i]))
+				continue;
+
+			btf_ids[j] = btf_type_id;
+			tgt_fds[j] = btf_obj_fd;
+			j++;
 		}
+		cnt = j;
 		link_opts.tracing_multi.btf_ids = btf_ids;
 		link_opts.tracing_multi.tgt_fds = tgt_fds;
+	} else if (opts->attach_tracing) {
+		link_opts.tracing_multi.btf_ids = &prog->attach_btf_id;
+		link_opts.tracing_multi.tgt_fds = &prog->attach_btf_obj_fd;
+		cnt = 1;
 	} else {
 		link_opts.tracing_multi.btf_ids = OPTS_GET(opts, btf_ids, 0);
 		link_opts.tracing_multi.tgt_fds = OPTS_GET(opts, tgt_fds, 0);
@@ -13957,7 +14027,8 @@ int bpf_program__set_attach_target(struct bpf_program *prog,
 			return libbpf_err(err);
 		err = find_kernel_btf_id(prog->obj, attach_func_name,
 					 prog->expected_attach_type,
-					 &btf_obj_fd, &btf_id, false);
+					 &btf_obj_fd, &btf_id, false,
+					 NULL);
 		if (err)
 			return libbpf_err(err);
 	}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index d7f0db7ab586..c087525ad25a 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -846,8 +846,12 @@ struct bpf_trace_multi_opts {
 	__u64 *cookies;
 	/* number of elements in syms/btf_ids/cookies arrays */
 	size_t cnt;
+	/* skip the invalid btf type before attaching */
+	bool skip_invalid;
+	/* attach a TRACING prog as TRACING_MULTI */
+	bool attach_tracing;
 };
-#define bpf_trace_multi_opts__last_field cnt
+#define bpf_trace_multi_opts__last_field attach_tracing
 
 LIBBPF_API struct bpf_link *
 bpf_program__attach_trace_multi_opts(const struct bpf_program *prog,
-- 
2.39.5


  parent reply	other threads:[~2025-05-28  3:50 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-28  3:46 [PATCH bpf-next 00/25] bpf: tracing multi-link support Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 01/25] add per-function metadata storage support Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 02/25] x86: implement per-function metadata storage for x86 Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 03/25] arm64: implement per-function metadata storage for arm64 Menglong Dong
2025-05-28 12:16   ` kernel test robot
2025-05-28  3:46 ` [PATCH bpf-next 04/25] bpf: make kfunc_md support global trampoline link Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 05/25] x86,bpf: add bpf_global_caller for global trampoline Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 06/25] ftrace: factor out ftrace_direct_update from register_ftrace_direct Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 07/25] ftrace: add reset_ftrace_direct_ips Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 08/25] bpf: introduce bpf_gtramp_link Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 09/25] bpf: tracing: add support to record and check the accessed args Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 10/25] bpf: refactor the modules_array to ptr_array Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 11/25] bpf: verifier: add btf to the function args of bpf_check_attach_target Menglong Dong
2025-05-28  3:46 ` [PATCH bpf-next 12/25] bpf: verifier: move btf_id_deny to bpf_check_attach_target Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 13/25] x86,bpf: factor out __arch_get_bpf_regs_nr Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 14/25] bpf: tracing: add multi-link support Menglong Dong
2025-05-28 11:34   ` kernel test robot
2025-05-28  3:47 ` [PATCH bpf-next 15/25] ftrace: factor out __unregister_ftrace_direct Menglong Dong
2025-05-28 12:37   ` kernel test robot
2025-05-28  3:47 ` [PATCH bpf-next 16/25] ftrace: supporting replace direct ftrace_ops Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 17/25] bpf: make trampoline compatible with global trampoline Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 18/25] libbpf: don't free btf if tracing_multi progs existing Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 19/25] libbpf: support tracing_multi Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 20/25] libbpf: add btf type hash lookup support Menglong Dong
2025-05-28  3:47 ` Menglong Dong [this message]
2025-05-28  3:47 ` [PATCH bpf-next 22/25] selftests/bpf: use the glob_match() from libbpf in test_progs.c Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 23/25] selftests/bpf: add get_ksyms and get_addrs to test_progs.c Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 24/25] selftests/bpf: add testcases for multi-link of tracing Menglong Dong
2025-05-28  3:47 ` [PATCH bpf-next 25/25] selftests/bpf: add performance bench test for trace prog Menglong Dong
2025-05-28 13:51 ` [PATCH bpf-next 00/25] bpf: tracing multi-link support Steven Rostedt
2025-05-29  1:44   ` Menglong Dong
2025-06-11  3:32 ` Alexei Starovoitov
2025-06-11 12:58   ` Menglong Dong
2025-06-11 16:11     ` Alexei Starovoitov
2025-06-12  0:07       ` Menglong Dong
2025-06-12  0:58         ` Alexei Starovoitov
2025-06-12  3:18           ` Menglong Dong
2025-06-15  8:35           ` Menglong Dong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250528034712.138701-22-dongml2@chinatelecom.cn \
    --to=menglong8.dong@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=bpf@vger.kernel.org \
    --cc=dongml2@chinatelecom.cn \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®