From patchwork Mon Jul 17 15:23:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315931 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DE28C001B0 for ; Mon, 17 Jul 2023 15:23:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231511AbjGQPX5 (ORCPT ); Mon, 17 Jul 2023 11:23:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231761AbjGQPXx (ORCPT ); Mon, 17 Jul 2023 11:23:53 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 345C410DA; Mon, 17 Jul 2023 08:23:34 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2AC236112A; Mon, 17 Jul 2023 15:23:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 08EF8C433C7; Mon, 17 Jul 2023 15:23:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607411; bh=cvdO36sarOiv5ZpCKU2EQAmrbByydT2MCd5DqCQtaFA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CiXJ4YoiIgypHxscNLzvVUm/eIK/XxIR43zivwBPTByv4h1w2LYd6zyEgyEiBIBrS UPpJHHiZe+fNd/ZojAuxR4+P5/pPkM9yBbGjByYAoLLiWrZKWf/BHq78hdMY4XJBz2 tgDychYcg15CMuYi3XkTGuGtcnQTIlc3fyLdrXli3bbCl84QOJWRyM74DcLoldDoRn +9nWFfvceH7Ssv+9kw3oj7pABfrbMb4xnYq4MprQx80XHQ32WW8fMLG6JLf6Ne8Ldi CS7YfmLgmDcUeOjnvHW9FuZRgAXPkoWZvbzHEw0H0eoYYkyfesnanBBH6+YJ19s+Kp 6CcB0qvYJ8kBg== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 1/9] tracing/probes: Fix to add NULL check for BTF APIs Date: Tue, 18 Jul 2023 00:23:27 +0900 Message-Id: <168960740754.34107.12202350138610653557.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Since find_btf_func_param() abd btf_type_by_id() can return NULL, the caller must check the return value correctly. Fixes: b576e09701c7 ("tracing/probes: Support function parameters if BTF is available") Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_probe.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index b2b726bea1f9..c68a72707852 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -386,12 +386,12 @@ static const struct btf_type *find_btf_func_proto(const char *funcname) /* Get BTF_KIND_FUNC type */ t = btf_type_by_id(btf, id); - if (!btf_type_is_func(t)) + if (!t || !btf_type_is_func(t)) return ERR_PTR(-ENOENT); /* The type of BTF_KIND_FUNC is BTF_KIND_FUNC_PROTO */ t = btf_type_by_id(btf, t->type); - if (!btf_type_is_func_proto(t)) + if (!t || !btf_type_is_func_proto(t)) return ERR_PTR(-ENOENT); return t; @@ -443,7 +443,7 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code, if (!ctx->params) { params = find_btf_func_param(ctx->funcname, &ctx->nr_params, ctx->flags & TPARG_FL_TPOINT); - if (IS_ERR(params)) { + if (IS_ERR_OR_NULL(params)) { trace_probe_log_err(ctx->offset, NO_BTF_ENTRY); return PTR_ERR(params); } @@ -1273,7 +1273,7 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[], params = find_btf_func_param(ctx->funcname, &nr_params, ctx->flags & TPARG_FL_TPOINT); - if (IS_ERR(params)) { + if (IS_ERR_OR_NULL(params)) { if (args_idx != -1) { /* $arg* requires BTF info */ trace_probe_log_err(0, NOSUP_BTFARG); From patchwork Mon Jul 17 15:23:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315933 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E0D0C001B0 for ; Mon, 17 Jul 2023 15:24:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231560AbjGQPYM (ORCPT ); Mon, 17 Jul 2023 11:24:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231779AbjGQPYE (ORCPT ); Mon, 17 Jul 2023 11:24:04 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E55CB10D3; Mon, 17 Jul 2023 08:23:47 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 59BC16112C; Mon, 17 Jul 2023 15:23:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2FC70C433C8; Mon, 17 Jul 2023 15:23:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607421; bh=BWbI9yDKpcKn7YyhyFkObG82wGckmUlkttodK+RJwNE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JazJuJxIrqcELqrY8aqDYDkCX3z/7enpoNbNDNmbCPPL/49Sj0j4RZ80+cClSQGTx mLZb3QLIx/htHp2zBmnnoLg9zk0iWMTfx61wjzK9tm0qM0ddGuTHaAH9XrGfTDJEyx Wp20YIntLt6HSR6uxMGXRf/GYsjNjrIjlkUnxi23J1deUBCmdwvRu29nnJgMn2cG56 IDLI0XeMZkesBuAacvkEIFUUNw/TgDaeIF2kmj279DFe4FukOlfHgSkCKM7m29fBGZ Khp+fBAVjVjNL/xibMBlNNnvS2pmJRl8edyZNrZ0bOAieh6YHv0LD+Dcb6BpN8VdxG yCza+MzlUFcug== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 2/9] bpf/btf: tracing: Move finding func-proto API and getting func-param API to BTF Date: Tue, 18 Jul 2023 00:23:37 +0900 Message-Id: <168960741686.34107.6330273416064011062.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Move generic function-proto find API and getting function parameter API to BTF library code from trace_probe.c. This will avoid redundant efforts on different feature. Signed-off-by: Masami Hiramatsu (Google) --- include/linux/btf.h | 4 ++++ kernel/bpf/btf.c | 45 ++++++++++++++++++++++++++++++++++++++++ kernel/trace/trace_probe.c | 50 +++++++++++++------------------------------- 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/include/linux/btf.h b/include/linux/btf.h index cac9f304e27a..98fbbcdd72ec 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -221,6 +221,10 @@ const struct btf_type * btf_resolve_size(const struct btf *btf, const struct btf_type *type, u32 *type_size); const char *btf_type_str(const struct btf_type *t); +const struct btf_type *btf_find_func_proto(struct btf *btf, + const char *func_name); +const struct btf_param *btf_get_func_param(const struct btf_type *func_proto, + s32 *nr); #define for_each_member(i, struct_type, member) \ for (i = 0, member = btf_type_member(struct_type); \ diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 817204d53372..e015b52956cb 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -1947,6 +1947,51 @@ btf_resolve_size(const struct btf *btf, const struct btf_type *type, return __btf_resolve_size(btf, type, type_size, NULL, NULL, NULL, NULL); } +/* + * Find a functio proto type by name, and return it. + * Return NULL if not found, or return -EINVAL if parameter is invalid. + */ +const struct btf_type *btf_find_func_proto(struct btf *btf, const char *func_name) +{ + const struct btf_type *t; + s32 id; + + if (!btf || !func_name) + return ERR_PTR(-EINVAL); + + id = btf_find_by_name_kind(btf, func_name, BTF_KIND_FUNC); + if (id <= 0) + return NULL; + + /* Get BTF_KIND_FUNC type */ + t = btf_type_by_id(btf, id); + if (!t || !btf_type_is_func(t)) + return NULL; + + /* The type of BTF_KIND_FUNC is BTF_KIND_FUNC_PROTO */ + t = btf_type_by_id(btf, t->type); + if (!t || !btf_type_is_func_proto(t)) + return NULL; + + return t; +} + +/* + * Get function parameter with the number of parameters. + * This can return NULL if the function has no parameters. + */ +const struct btf_param *btf_get_func_param(const struct btf_type *func_proto, s32 *nr) +{ + if (!func_proto || !nr) + return ERR_PTR(-EINVAL); + + *nr = btf_type_vlen(func_proto); + if (*nr > 0) + return (const struct btf_param *)(func_proto + 1); + else + return NULL; +} + static u32 btf_resolved_type_id(const struct btf *btf, u32 type_id) { while (type_id < btf->start_id) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index c68a72707852..cd89fc1ebb42 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -371,47 +371,23 @@ static const char *type_from_btf_id(struct btf *btf, s32 id) return NULL; } -static const struct btf_type *find_btf_func_proto(const char *funcname) -{ - struct btf *btf = traceprobe_get_btf(); - const struct btf_type *t; - s32 id; - - if (!btf || !funcname) - return ERR_PTR(-EINVAL); - - id = btf_find_by_name_kind(btf, funcname, BTF_KIND_FUNC); - if (id <= 0) - return ERR_PTR(-ENOENT); - - /* Get BTF_KIND_FUNC type */ - t = btf_type_by_id(btf, id); - if (!t || !btf_type_is_func(t)) - return ERR_PTR(-ENOENT); - - /* The type of BTF_KIND_FUNC is BTF_KIND_FUNC_PROTO */ - t = btf_type_by_id(btf, t->type); - if (!t || !btf_type_is_func_proto(t)) - return ERR_PTR(-ENOENT); - - return t; -} - static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr, bool tracepoint) { + struct btf *btf = traceprobe_get_btf(); const struct btf_param *param; const struct btf_type *t; - if (!funcname || !nr) + if (!funcname || !nr || !btf) return ERR_PTR(-EINVAL); - t = find_btf_func_proto(funcname); - if (IS_ERR(t)) + t = btf_find_func_proto(btf, funcname); + if (IS_ERR_OR_NULL(t)) return (const struct btf_param *)t; - *nr = btf_type_vlen(t); - param = (const struct btf_param *)(t + 1); + param = btf_get_func_param(t, nr); + if (IS_ERR_OR_NULL(param)) + return param; /* Hide the first 'data' argument of tracepoint */ if (tracepoint) { @@ -490,8 +466,8 @@ static const struct fetch_type *parse_btf_retval_type( const struct btf_type *t; if (btf && ctx->funcname) { - t = find_btf_func_proto(ctx->funcname); - if (!IS_ERR(t)) + t = btf_find_func_proto(btf, ctx->funcname); + if (!IS_ERR_OR_NULL(t)) typestr = type_from_btf_id(btf, t->type); } @@ -500,10 +476,14 @@ static const struct fetch_type *parse_btf_retval_type( static bool is_btf_retval_void(const char *funcname) { + struct btf *btf = traceprobe_get_btf(); const struct btf_type *t; - t = find_btf_func_proto(funcname); - if (IS_ERR(t)) + if (!btf) + return false; + + t = btf_find_func_proto(btf, funcname); + if (IS_ERR_OR_NULL(t)) return false; return t->type == 0; From patchwork Mon Jul 17 15:23:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315934 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18F0EC001B0 for ; Mon, 17 Jul 2023 15:24:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230284AbjGQPY2 (ORCPT ); Mon, 17 Jul 2023 11:24:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57126 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230285AbjGQPYO (ORCPT ); Mon, 17 Jul 2023 11:24:14 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1CB26F5; Mon, 17 Jul 2023 08:23:58 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5BD9C6104A; Mon, 17 Jul 2023 15:23:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01632C433C7; Mon, 17 Jul 2023 15:23:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607431; bh=DHVTx0hal1LvLnlrU3Axy5dJ3lhJGA8GVR5jpKF4jhU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tZxXXYzhpZFBO4M4QHLtv7C4cVPWjYG+Kxb00IplTDMV86B0B6fGIxBzZRmFSo6D1 NMxlH4ildfklCTLfMXMMXlphdUGZtGnd7tNhC8Fz4TNpxHvUabQl8epBQTkfYOb/0z Hd0QDoaUQkV9YYBj3u0+pqgY33fQcPevyU6Ru+K5neL41+cDZDRRi8LDpIcBI4AW7D YxAicfJQoPumhr3nQBUKYYzP0YTX/Qe7y5lAxpAlbR6ModDj6QiVRiwBuSAIYUChA3 k+tFZP1TvFrlYMSfUAp0VAyGdPU8geUq9qFTejBDEQ2WeFaJO6JO7dXUGAC96syKBf qoAES80/9i45A== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 3/9] bpf/btf: Add a function to search a member of a struct/union Date: Tue, 18 Jul 2023 00:23:47 +0900 Message-Id: <168960742712.34107.9849785489776347376.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Add btf_find_struct_member() API to search a member of a given data structure or union from the member's name. Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Alan Maguire --- include/linux/btf.h | 3 +++ kernel/bpf/btf.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/include/linux/btf.h b/include/linux/btf.h index 98fbbcdd72ec..097fe9b51562 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -225,6 +225,9 @@ const struct btf_type *btf_find_func_proto(struct btf *btf, const char *func_name); const struct btf_param *btf_get_func_param(const struct btf_type *func_proto, s32 *nr); +const struct btf_member *btf_find_struct_member(struct btf *btf, + const struct btf_type *type, + const char *member_name); #define for_each_member(i, struct_type, member) \ for (i = 0, member = btf_type_member(struct_type); \ diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index e015b52956cb..452ffb0393d6 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -1992,6 +1992,44 @@ const struct btf_param *btf_get_func_param(const struct btf_type *func_proto, s3 return NULL; } +/* + * Find a member of data structure/union by name and return it. + * Return NULL if not found, or -EINVAL if parameter is invalid. + */ +const struct btf_member *btf_find_struct_member(struct btf *btf, + const struct btf_type *type, + const char *member_name) +{ + const struct btf_member *members, *ret; + const char *name; + int i, vlen; + + if (!btf || !member_name || !btf_type_is_struct(type)) + return ERR_PTR(-EINVAL); + + vlen = btf_type_vlen(type); + members = (const struct btf_member *)(type + 1); + + for (i = 0; i < vlen; i++) { + if (!members[i].name_off) { + /* unnamed union: dig deeper */ + type = btf_type_by_id(btf, members[i].type); + if (!IS_ERR_OR_NULL(type)) { + ret = btf_find_struct_member(btf, type, + member_name); + if (!IS_ERR_OR_NULL(ret)) + return ret; + } + } else { + name = btf_name_by_offset(btf, members[i].name_off); + if (name && !strcmp(member_name, name)) + return &members[i]; + } + } + + return NULL; +} + static u32 btf_resolved_type_id(const struct btf *btf, u32 type_id) { while (type_id < btf->start_id) From patchwork Mon Jul 17 15:23:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315935 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C2A0EB64DC for ; Mon, 17 Jul 2023 15:24:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232007AbjGQPYe (ORCPT ); Mon, 17 Jul 2023 11:24:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231872AbjGQPYU (ORCPT ); Mon, 17 Jul 2023 11:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99F45198E; Mon, 17 Jul 2023 08:24:02 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 63C976111D; Mon, 17 Jul 2023 15:24:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CC055C433C8; Mon, 17 Jul 2023 15:23:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607441; bh=6fmjmQFY0f+lFuunAgeTFkf6Os4EuVkND2LlVKd924M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UVoNV+JjHeYw0yJfPYyIPz/SBw8QYymGfTRD4EFXK6FOZTEOjNL4djzpMFq09k+UH uiRd8xGONWdUc/cwsqts6tnpxI8xmEJBMgrutqt8KCyB9EVGV3qflzJn8GEsX565lv XCHLzh96VKVl0jR51f8oH4/61kHGu+y/eDLyWWu6NMSYDdwYtWD/6HZ8nDnOYOWvSN xMXU0RJM0g1Xdj7V7k/uioEqSZc6rAP+7KWSbybXPIkC2Vw74nFdEtIAOQS3wmF09E VgydjE5St0h35xEJXBUtygC3i9Ax7nYiWBDlDnfT8Kw/idXq2hdaKo5VRiZgYmsBJU BmKqQXjZ9iqpg== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 4/9] tracing/probes: Support BTF based data structure field access Date: Tue, 18 Jul 2023 00:23:57 +0900 Message-Id: <168960743715.34107.15965496586942658628.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Using BTF to access the fields of a data structure. You can use this for accessing the field with '->' or '.' operation with BTF argument. # echo 't sched_switch next=next->pid vruntime=next->se.vruntime' \ > dynamic_events # echo 1 > events/tracepoints/sched_switch/enable # head -n 40 trace | tail -0 [000] d..3. 272.565382: sched_switch: (__probestub_sched_switch+0x4/0x10) next=26 vruntime=956533179 kcompactd0-26 [000] d..3. 272.565406: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 -0 [000] d..3. 273.069441: sched_switch: (__probestub_sched_switch+0x4/0x10) next=9 vruntime=956533179 kworker/0:1-9 [000] d..3. 273.069464: sched_switch: (__probestub_sched_switch+0x4/0x10) next=26 vruntime=956579181 kcompactd0-26 [000] d..3. 273.069480: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 -0 [000] d..3. 273.141434: sched_switch: (__probestub_sched_switch+0x4/0x10) next=22 vruntime=956533179 kworker/u2:1-22 [000] d..3. 273.141461: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 -0 [000] d..3. 273.480872: sched_switch: (__probestub_sched_switch+0x4/0x10) next=22 vruntime=956585857 kworker/u2:1-22 [000] d..3. 273.480905: sched_switch: (__probestub_sched_switch+0x4/0x10) next=70 vruntime=959533179 sh-70 [000] d..3. 273.481102: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Alan Maguire --- Changes in v2: - Use new BTF API for finding the member. --- kernel/trace/trace_probe.c | 229 +++++++++++++++++++++++++++++++++++++++----- kernel/trace/trace_probe.h | 11 ++ 2 files changed, 213 insertions(+), 27 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index cd89fc1ebb42..dd646d35637d 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -319,16 +319,14 @@ static u32 btf_type_int(const struct btf_type *t) return *(u32 *)(t + 1); } -static const char *type_from_btf_id(struct btf *btf, s32 id) +static const char *fetch_type_from_btf_type(struct btf *btf, + const struct btf_type *type, + struct traceprobe_parse_context *ctx) { - const struct btf_type *t; u32 intdata; - s32 tid; /* TODO: const char * could be converted as a string */ - t = btf_type_skip_modifiers(btf, id, &tid); - - switch (BTF_INFO_KIND(t->info)) { + switch (BTF_INFO_KIND(type->info)) { case BTF_KIND_ENUM: /* enum is "int", so convert to "s32" */ return "s32"; @@ -341,7 +339,7 @@ static const char *type_from_btf_id(struct btf *btf, s32 id) else return "x32"; case BTF_KIND_INT: - intdata = btf_type_int(t); + intdata = btf_type_int(type); if (BTF_INT_ENCODING(intdata) & BTF_INT_SIGNED) { switch (BTF_INT_BITS(intdata)) { case 8: @@ -364,6 +362,10 @@ static const char *type_from_btf_id(struct btf *btf, s32 id) case 64: return "u64"; } + /* bitfield, size is encoded in the type */ + ctx->last_bitsize = BTF_INT_BITS(intdata); + ctx->last_bitoffs += BTF_INT_OFFSET(intdata); + return "u64"; } } /* TODO: support other types */ @@ -401,12 +403,120 @@ static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr return NULL; } -static int parse_btf_arg(const char *varname, struct fetch_insn *code, +/* Return 1 if the field separater is arrow operator ('->') */ +static int split_next_field(char *varname, char **next_field, + struct traceprobe_parse_context *ctx) +{ + char *field; + int ret = 0; + + field = strpbrk(varname, ".-"); + if (field) { + if (field[0] == '-' && field[1] == '>') { + field[0] = '\0'; + field += 2; + ret = 1; + } else if (field[0] == '.') { + field[0] = '\0'; + field += 1; + } else { + trace_probe_log_err(ctx->offset + field - varname, BAD_HYPHEN); + return -EINVAL; + } + *next_field = field; + } + + return ret; +} + +/* + * Parse the field of data structure. The @type must be a pointer type + * pointing the target data structure type. + */ +static int parse_btf_field(char *fieldname, const struct btf_type *type, + struct fetch_insn **pcode, struct fetch_insn *end, + struct traceprobe_parse_context *ctx) +{ + struct btf *btf = traceprobe_get_btf(); + struct fetch_insn *code = *pcode; + const struct btf_member *field; + u32 bitoffs; + char *next; + int is_ptr; + s32 tid; + + do { + /* Outer loop for solving arrow operator ('->') */ + if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) { + trace_probe_log_err(ctx->offset, NO_PTR_STRCT); + return -EINVAL; + } + /* Convert a struct pointer type to a struct type */ + type = btf_type_skip_modifiers(btf, type->type, &tid); + if (!type) { + trace_probe_log_err(ctx->offset, BAD_BTF_TID); + return -EINVAL; + } + + bitoffs = 0; + do { + /* Inner loop for solving dot operator ('.') */ + next = NULL; + is_ptr = split_next_field(fieldname, &next, ctx); + if (is_ptr < 0) + return is_ptr; + + field = btf_find_struct_member(btf, type, fieldname); + if (!field) { + trace_probe_log_err(ctx->offset, NO_BTF_FIELD); + return -ENOENT; + } + + /* Accumulate the bit-offsets of the dot-connected fields */ + if (btf_type_kflag(type)) { + bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset); + ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset); + } else { + bitoffs += field->offset; + ctx->last_bitsize = 0; + } + + type = btf_type_skip_modifiers(btf, field->type, &tid); + if (!type) { + trace_probe_log_err(ctx->offset, BAD_BTF_TID); + return -EINVAL; + } + + ctx->offset += next - fieldname; + fieldname = next; + } while (!is_ptr && fieldname); + + if (++code == end) { + trace_probe_log_err(ctx->offset, TOO_MANY_OPS); + return -EINVAL; + } + code->op = FETCH_OP_DEREF; /* TODO: user deref support */ + code->offset = bitoffs / 8; + *pcode = code; + + ctx->last_bitoffs = bitoffs % 8; + ctx->last_type = type; + } while (fieldname); + + return 0; +} + +static int parse_btf_arg(char *varname, + struct fetch_insn **pcode, struct fetch_insn *end, struct traceprobe_parse_context *ctx) { struct btf *btf = traceprobe_get_btf(); + struct fetch_insn *code = *pcode; const struct btf_param *params; - int i; + const struct btf_type *type; + char *field = NULL; + int i, is_ptr; + u32 tid; if (!btf) { trace_probe_log_err(ctx->offset, NOSUP_BTFARG); @@ -416,6 +526,16 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code, if (WARN_ON_ONCE(!ctx->funcname)) return -EINVAL; + is_ptr = split_next_field(varname, &field, ctx); + if (is_ptr < 0) + return is_ptr; + if (!is_ptr && field) { + /* dot-connected field on an argument is not supported. */ + trace_probe_log_err(ctx->offset + field - varname, + NOSUP_DAT_ARG); + return -EOPNOTSUPP; + } + if (!ctx->params) { params = find_btf_func_param(ctx->funcname, &ctx->nr_params, ctx->flags & TPARG_FL_TPOINT); @@ -436,24 +556,39 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code, code->param = i + 1; else code->param = i; - return 0; + + tid = params[i].type; + goto found; } } trace_probe_log_err(ctx->offset, NO_BTFARG); return -ENOENT; + +found: + type = btf_type_skip_modifiers(btf, tid, &tid); + if (!type) { + trace_probe_log_err(ctx->offset, BAD_BTF_TID); + return -EINVAL; + } + /* Initialize the last type information */ + ctx->last_type = type; + ctx->last_bitoffs = 0; + ctx->last_bitsize = 0; + if (field) { + ctx->offset += field - varname; + return parse_btf_field(field, type, pcode, end, ctx); + } + return 0; } -static const struct fetch_type *parse_btf_arg_type(int arg_idx, +static const struct fetch_type *parse_btf_arg_type( struct traceprobe_parse_context *ctx) { struct btf *btf = traceprobe_get_btf(); const char *typestr = NULL; - if (btf && ctx->params) { - if (ctx->flags & TPARG_FL_TPOINT) - arg_idx--; - typestr = type_from_btf_id(btf, ctx->params[arg_idx].type); - } + if (btf && ctx->last_type) + typestr = fetch_type_from_btf_type(btf, ctx->last_type, ctx); return find_fetch_type(typestr, ctx->flags); } @@ -463,17 +598,43 @@ static const struct fetch_type *parse_btf_retval_type( { struct btf *btf = traceprobe_get_btf(); const char *typestr = NULL; - const struct btf_type *t; + const struct btf_type *type; + s32 tid; if (btf && ctx->funcname) { - t = btf_find_func_proto(btf, ctx->funcname); - if (!IS_ERR_OR_NULL(t)) - typestr = type_from_btf_id(btf, t->type); + type = btf_find_func_proto(btf, ctx->funcname); + if (!IS_ERR_OR_NULL(type)) { + type = btf_type_skip_modifiers(btf, type->type, &tid); + if (!IS_ERR_OR_NULL(type)) + typestr = fetch_type_from_btf_type(btf, type, ctx); + } } return find_fetch_type(typestr, ctx->flags); } +static int parse_btf_bitfield(struct fetch_insn **pcode, + struct traceprobe_parse_context *ctx) +{ + struct fetch_insn *code = *pcode; + + if ((ctx->last_bitsize % 8 == 0) && ctx->last_bitoffs == 0) + return 0; + + code++; + if (code->op != FETCH_OP_NOP) { + trace_probe_log_err(ctx->offset, TOO_MANY_OPS); + return -EINVAL; + } + *pcode = code; + + code->op = FETCH_OP_MOD_BF; + code->lshift = 64 - (ctx->last_bitsize + ctx->last_bitoffs); + code->rshift = 64 - ctx->last_bitsize; + code->basesize = 64 / 8; + return 0; +} + static bool is_btf_retval_void(const char *funcname) { struct btf *btf = traceprobe_get_btf(); @@ -500,14 +661,22 @@ static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr return ERR_PTR(-EOPNOTSUPP); } -static int parse_btf_arg(const char *varname, struct fetch_insn *code, +static int parse_btf_arg(char *varname, + struct fetch_insn **pcode, struct fetch_insn *end, struct traceprobe_parse_context *ctx) { trace_probe_log_err(ctx->offset, NOSUP_BTFARG); return -EOPNOTSUPP; } -#define parse_btf_arg_type(idx, ctx) \ +static int parse_btf_bitfield(struct fetch_insn **pcode, + struct traceprobe_parse_context *ctx) +{ + trace_probe_log_err(ctx->offset, NOSUP_BTFARG); + return -EOPNOTSUPP; +} + +#define parse_btf_arg_type(ctx) \ find_fetch_type(NULL, ctx->flags) #define parse_btf_retval_type(ctx) \ @@ -775,6 +944,8 @@ parse_probe_arg(char *arg, const struct fetch_type *type, code->op = deref; code->offset = offset; + /* Reset the last type if used */ + ctx->last_type = NULL; } break; case '\\': /* Immediate value */ @@ -798,7 +969,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type, trace_probe_log_err(ctx->offset, NOSUP_BTFARG); return -EINVAL; } - ret = parse_btf_arg(arg, code, ctx); + ret = parse_btf_arg(arg, pcode, end, ctx); break; } } @@ -944,6 +1115,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, goto out; code[FETCH_INSN_MAX - 1].op = FETCH_OP_END; + ctx->last_type = NULL; ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1], ctx); if (ret) @@ -951,9 +1123,9 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, /* Update storing type if BTF is available */ if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && !t) { - if (code->op == FETCH_OP_ARG) - parg->type = parse_btf_arg_type(code->param, ctx); - else if (code->op == FETCH_OP_RETVAL) + if (ctx->last_type) + parg->type = parse_btf_arg_type(ctx); + else if (ctx->flags & TPARG_FL_RETURN) parg->type = parse_btf_retval_type(ctx); } @@ -1028,6 +1200,11 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, trace_probe_log_err(ctx->offset + t - arg, BAD_BITFIELD); goto fail; } + } else if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && + ctx->last_type) { + ret = parse_btf_bitfield(&code, ctx); + if (ret) + goto fail; } ret = -EINVAL; /* Loop(Array) operation */ diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index 01ea148723de..050909aaaa1b 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -384,6 +384,9 @@ static inline bool tparg_is_function_entry(unsigned int flags) struct traceprobe_parse_context { struct trace_event_call *event; const struct btf_param *params; + const struct btf_type *last_type; + u32 last_bitoffs; + u32 last_bitsize; s32 nr_params; const char *funcname; unsigned int flags; @@ -495,7 +498,13 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, C(BAD_VAR_ARGS, "$arg* must be an independent parameter without name etc."),\ C(NOFENTRY_ARGS, "$arg* can be used only on function entry"), \ C(DOUBLE_ARGS, "$arg* can be used only once in the parameters"), \ - C(ARGS_2LONG, "$arg* failed because the argument list is too long"), + C(ARGS_2LONG, "$arg* failed because the argument list is too long"), \ + C(ARGIDX_2BIG, "$argN index is too big"), \ + C(NO_PTR_STRCT, "This is not a pointer to union/structure."), \ + C(NOSUP_DAT_ARG, "Non pointer structure/union argument is not supported."),\ + C(BAD_HYPHEN, "Failed to parse single hyphen. Forgot '>'?"), \ + C(NO_BTF_FIELD, "This field is not found."), \ + C(BAD_BTF_TID, "Failed to get BTF type info."), #undef C #define C(a, b) TP_ERR_##a From patchwork Mon Jul 17 15:24:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315937 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94C8EC001B0 for ; Mon, 17 Jul 2023 15:25:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232010AbjGQPZR (ORCPT ); Mon, 17 Jul 2023 11:25:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57724 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231861AbjGQPYx (ORCPT ); Mon, 17 Jul 2023 11:24:53 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57B8E1735; Mon, 17 Jul 2023 08:24:34 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 893F0610F4; Mon, 17 Jul 2023 15:24:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ECED0C433C8; Mon, 17 Jul 2023 15:24:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607452; bh=HNw7NmAJWJoLfuOb7lcwr0tG/Yg91E6W1MXYrCfkES8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BUWZzB8ih/Pn17MNMbs4bLT6F3qq7F/IIIg66MNQnM/DH93rG0K9UG221F0zupoZZ O8oW/qK3mGyNFuNNcZkDuie4iQeVW++xBPymTfa82sLjllXjEsGcNw5l2PsHu/PRvx wF05Fc0Ew3ZII0weMaCacrFY2FKt74DBReB0ND1/u87o8reC3fXiDsXcraOkeRYLGK GqGnDPhFHYD1elbCbub6fi9URBamkp6az5E8dpcjqCzL+r13FIzSxRRUbdxMHXsKyJ QnfxwukYukf9m52v9zeqdsOAM7niAy1zWZ0hxrqZEeaI5gtH3xyW8K9mb1kbkFMScI VYQVMZlWdIX6w== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 5/9] tracing/probes: Support BTF field access from $retval Date: Tue, 18 Jul 2023 00:24:07 +0900 Message-Id: <168960744719.34107.443329109565685838.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Support BTF argument on '$retval' for function return events including kretprobe and fprobe for accessing the return value. This also allows user to access its fields if the return value is a pointer of a data structure. E.g. # echo 'f getname_flags%return +0($retval->name):string' \ > dynamic_events # echo 1 > events/fprobes/getname_flags__exit/enable # ls > /dev/null # head -n 40 trace | tail ls-87 [000] ...1. 8067.616101: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./function_profile_enabled" ls-87 [000] ...1. 8067.616108: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./trace_stat" ls-87 [000] ...1. 8067.616115: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./set_graph_notrace" ls-87 [000] ...1. 8067.616122: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./set_graph_function" ls-87 [000] ...1. 8067.616129: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./set_ftrace_notrace" ls-87 [000] ...1. 8067.616135: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./set_ftrace_filter" ls-87 [000] ...1. 8067.616143: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./touched_functions" ls-87 [000] ...1. 8067.616237: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./enabled_functions" ls-87 [000] ...1. 8067.616245: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./available_filter_functions" ls-87 [000] ...1. 8067.616253: getname_flags__exit: (vfs_fstatat+0x3c/0x70 <- getname_flags) arg1="./set_ftrace_notrace_pid" Signed-off-by: Masami Hiramatsu (Google) --- Changes in v2: - Use '$retval' instead of 'retval' because it is confusing. --- kernel/trace/trace_probe.c | 98 +++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 61 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index dd646d35637d..4442ff9c2728 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -536,6 +536,22 @@ static int parse_btf_arg(char *varname, return -EOPNOTSUPP; } + if (ctx->flags & TPARG_FL_RETURN) { + if (strcmp(varname, "$retval") != 0) { + trace_probe_log_err(ctx->offset, NO_BTFARG); + return -ENOENT; + } + /* Check whether the function return type is not void */ + type = btf_find_func_proto(btf, ctx->funcname); + if (!IS_ERR_OR_NULL(type) && type->type == 0) { + trace_probe_log_err(ctx->offset, NO_RETVAL); + return -ENOENT; + } + code->op = FETCH_OP_RETVAL; + tid = type->type; + goto found; + } + if (!ctx->params) { params = find_btf_func_param(ctx->funcname, &ctx->nr_params, ctx->flags & TPARG_FL_TPOINT); @@ -556,7 +572,6 @@ static int parse_btf_arg(char *varname, code->param = i + 1; else code->param = i; - tid = params[i].type; goto found; } @@ -581,7 +596,7 @@ static int parse_btf_arg(char *varname, return 0; } -static const struct fetch_type *parse_btf_arg_type( +static const struct fetch_type *find_fetch_type_from_btf_type( struct traceprobe_parse_context *ctx) { struct btf *btf = traceprobe_get_btf(); @@ -593,26 +608,6 @@ static const struct fetch_type *parse_btf_arg_type( return find_fetch_type(typestr, ctx->flags); } -static const struct fetch_type *parse_btf_retval_type( - struct traceprobe_parse_context *ctx) -{ - struct btf *btf = traceprobe_get_btf(); - const char *typestr = NULL; - const struct btf_type *type; - s32 tid; - - if (btf && ctx->funcname) { - type = btf_find_func_proto(btf, ctx->funcname); - if (!IS_ERR_OR_NULL(type)) { - type = btf_type_skip_modifiers(btf, type->type, &tid); - if (!IS_ERR_OR_NULL(type)) - typestr = fetch_type_from_btf_type(btf, type, ctx); - } - } - - return find_fetch_type(typestr, ctx->flags); -} - static int parse_btf_bitfield(struct fetch_insn **pcode, struct traceprobe_parse_context *ctx) { @@ -635,20 +630,6 @@ static int parse_btf_bitfield(struct fetch_insn **pcode, return 0; } -static bool is_btf_retval_void(const char *funcname) -{ - struct btf *btf = traceprobe_get_btf(); - const struct btf_type *t; - - if (!btf) - return false; - - t = btf_find_func_proto(btf, funcname); - if (IS_ERR_OR_NULL(t)) - return false; - - return t->type == 0; -} #else static struct btf *traceprobe_get_btf(void) { @@ -676,24 +657,23 @@ static int parse_btf_bitfield(struct fetch_insn **pcode, return -EOPNOTSUPP; } -#define parse_btf_arg_type(ctx) \ - find_fetch_type(NULL, ctx->flags) - -#define parse_btf_retval_type(ctx) \ +#define find_fetch_type_from_btf_type(ctx) \ find_fetch_type(NULL, ctx->flags) -#define is_btf_retval_void(funcname) (false) - #endif #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) -static int parse_probe_vars(char *arg, const struct fetch_type *t, - struct fetch_insn *code, +/* Parse $vars. @orig_arg points '$', which syncs to @ctx->offset */ +static int parse_probe_vars(char *orig_arg, const struct fetch_type *t, + struct fetch_insn **pcode, + struct fetch_insn *end, struct traceprobe_parse_context *ctx) { - unsigned long param; + struct fetch_insn *code = *pcode; int err = TP_ERR_BAD_VAR; + char *arg = orig_arg + 1; + unsigned long param; int ret = 0; int len; @@ -712,18 +692,17 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, goto inval; } - if (strcmp(arg, "retval") == 0) { - if (ctx->flags & TPARG_FL_RETURN) { - if ((ctx->flags & TPARG_FL_KERNEL) && - is_btf_retval_void(ctx->funcname)) { - err = TP_ERR_NO_RETVAL; - goto inval; - } + if (str_has_prefix(arg, "retval")) { + if (!(ctx->flags & TPARG_FL_RETURN)) { + err = TP_ERR_RETVAL_ON_PROBE; + goto inval; + } + if (!(ctx->flags & TPARG_FL_KERNEL) || + !IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS)) { code->op = FETCH_OP_RETVAL; return 0; } - err = TP_ERR_RETVAL_ON_PROBE; - goto inval; + return parse_btf_arg(orig_arg, pcode, end, ctx); } len = str_has_prefix(arg, "stack"); @@ -825,7 +804,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type, switch (arg[0]) { case '$': - ret = parse_probe_vars(arg + 1, type, code, ctx); + ret = parse_probe_vars(arg, type, pcode, end, ctx); break; case '%': /* named register */ @@ -1122,12 +1101,9 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, goto fail; /* Update storing type if BTF is available */ - if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && !t) { - if (ctx->last_type) - parg->type = parse_btf_arg_type(ctx); - else if (ctx->flags & TPARG_FL_RETURN) - parg->type = parse_btf_retval_type(ctx); - } + if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && + !t && ctx->last_type) + parg->type = find_fetch_type_from_btf_type(ctx); ret = -EINVAL; /* Store operation */ From patchwork Mon Jul 17 15:24:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315936 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B00FC001B0 for ; Mon, 17 Jul 2023 15:25:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231915AbjGQPZF (ORCPT ); Mon, 17 Jul 2023 11:25:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232033AbjGQPYr (ORCPT ); Mon, 17 Jul 2023 11:24:47 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E07FE2127; Mon, 17 Jul 2023 08:24:22 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8DD346111D; Mon, 17 Jul 2023 15:24:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01D69C433C7; Mon, 17 Jul 2023 15:24:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607462; bh=jRgqNwwWlmesVuWztk4h6xTjuyWOGZBfgSaCsZjlSG8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kKx2dT1SQ0ADmcZHSuZ5bK1IjU9ciiukuO4i4kYLOl/hFpoeEY5llLJ8XCayyHPv8 3EBEGFIm+0oqNDfyAgv8dljtUNsuEMQVjTcV1z4s7vaNhj2EqLo4tZAeijztI8+MYW WMVRSK/ue0sFGF9kIEIiyrwGgQpc9H/n1lx3xyM0fF3slIy9kkYnouiWSNPWe4uoLw liP6O8+Vo1Xc0EX9U5Y2CKdeuw4lKtzeydwNiF9wrrUIopdYDU11dTwH+/HWa76h+7 uW2hqA5z6YzKAbgjFAPkU6emEtfS87zB7DfpcgbiarGrIId05aldwSWgxjS+9ABKPz 1CdX90mJ66lug== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 6/9] tracing/probes: Add string type check with BTF Date: Tue, 18 Jul 2023 00:24:17 +0900 Message-Id: <168960745735.34107.7883639718251524290.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Add a string type checking with BTF information if possible. This will check whether the given BTF argument (and field) is signed char array or pointer to signed char. If not, it reject the 'string' type. If it is pointer to signed char, it adds a dereference opration so that it can correctly fetch the string data from memory. # echo 'f getname_flags%return retval->name:string' >> dynamic_events # echo 't sched_switch next->comm:string' >> dynamic_events The above cases, 'struct filename::name' is 'char *' and 'struct task_struct::comm' is 'char []'. But in both case, user can specify ':string' to fetch the string data. Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_probe.c | 89 +++++++++++++++++++++++++++++++++++++++++++- kernel/trace/trace_probe.h | 3 + 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 4442ff9c2728..4d1dccb8724b 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -319,6 +319,77 @@ static u32 btf_type_int(const struct btf_type *t) return *(u32 *)(t + 1); } +static bool btf_type_is_char_ptr(struct btf *btf, const struct btf_type *type) +{ + const struct btf_type *real_type; + u32 intdata; + s32 tid; + + real_type = btf_type_skip_modifiers(btf, type->type, &tid); + if (!real_type) + return false; + + if (BTF_INFO_KIND(real_type->info) != BTF_KIND_INT) + return false; + + intdata = btf_type_int(real_type); + return !(BTF_INT_ENCODING(intdata) & BTF_INT_SIGNED) + && BTF_INT_BITS(intdata) == 8; +} + +static bool btf_type_is_char_array(struct btf *btf, const struct btf_type *type) +{ + const struct btf_type *real_type; + const struct btf_array *array; + u32 intdata; + s32 tid; + + if (BTF_INFO_KIND(type->info) != BTF_KIND_ARRAY) + return false; + + array = (const struct btf_array *)(type + 1); + + real_type = btf_type_skip_modifiers(btf, array->type, &tid); + + intdata = btf_type_int(real_type); + return !(BTF_INT_ENCODING(intdata) & BTF_INT_SIGNED) + && BTF_INT_BITS(intdata) == 8; +} + +static int check_prepare_btf_string_fetch(char *typename, + struct fetch_insn **pcode, + struct traceprobe_parse_context *ctx) +{ + struct btf *btf = traceprobe_get_btf(); + + if (!btf || !ctx->last_type) + return 0; + + /* char [] does not need any change. */ + if (btf_type_is_char_array(btf, ctx->last_type)) + return 0; + + /* char * requires dereference the pointer. */ + if (btf_type_is_char_ptr(btf, ctx->last_type)) { + struct fetch_insn *code = *pcode + 1; + + if (code->op == FETCH_OP_END) { + trace_probe_log_err(ctx->offset, TOO_MANY_OPS); + return -E2BIG; + } + if (typename[0] == 'u') + code->op = FETCH_OP_UDEREF; + else + code->op = FETCH_OP_DEREF; + code->offset = 0; + *pcode = code; + return 0; + } + /* Other types are not available for string */ + trace_probe_log_err(ctx->offset, BAD_TYPE4STR); + return -EINVAL; +} + static const char *fetch_type_from_btf_type(struct btf *btf, const struct btf_type *type, struct traceprobe_parse_context *ctx) @@ -660,6 +731,13 @@ static int parse_btf_bitfield(struct fetch_insn **pcode, #define find_fetch_type_from_btf_type(ctx) \ find_fetch_type(NULL, ctx->flags) +static int check_prepare_btf_string_fetch(char *typename, + struct fetch_insn **pcode, + struct traceprobe_parse_context *ctx) +{ + return 0; +} + #endif #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) @@ -1102,8 +1180,15 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, /* Update storing type if BTF is available */ if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && - !t && ctx->last_type) - parg->type = find_fetch_type_from_btf_type(ctx); + ctx->last_type) { + if (!t) { + parg->type = find_fetch_type_from_btf_type(ctx); + } else if (strstr(t, "string")) { + ret = check_prepare_btf_string_fetch(t, &code, ctx); + if (ret) + goto fail; + } + } ret = -EINVAL; /* Store operation */ diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index 050909aaaa1b..604d6fb9c5ff 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -504,7 +504,8 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, C(NOSUP_DAT_ARG, "Non pointer structure/union argument is not supported."),\ C(BAD_HYPHEN, "Failed to parse single hyphen. Forgot '>'?"), \ C(NO_BTF_FIELD, "This field is not found."), \ - C(BAD_BTF_TID, "Failed to get BTF type info."), + C(BAD_BTF_TID, "Failed to get BTF type info."),\ + C(BAD_TYPE4STR, "This type does not fit for string."), #undef C #define C(a, b) TP_ERR_##a From patchwork Mon Jul 17 15:24:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315940 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87BA3EB64DC for ; Mon, 17 Jul 2023 15:26:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231653AbjGQP0E (ORCPT ); Mon, 17 Jul 2023 11:26:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231343AbjGQPZe (ORCPT ); Mon, 17 Jul 2023 11:25:34 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8A75F2704; Mon, 17 Jul 2023 08:24:59 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B3F5C61123; Mon, 17 Jul 2023 15:24:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 239C4C433C7; Mon, 17 Jul 2023 15:24:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607472; bh=Ud+/WgVDgP+xcku85SFsEC4AToiKRsKLRxeToviMbLw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dRLWgmFjqOYNpjJ7uT98XQf53pRsqoJ4KmYQWSnI4dydNJiKY+NUpsytf0n08osMl bVICQQ33luLAfE1ZmrCsyk8Xbu2GIQanzzFIlTnoi/YVyASFCwDX2OlrfAAp/RNGcu s3JUM/jYOhZyt7JPBTY9K/c48UNAEr9Xz80nb6FVW4FP3ftIqkTyLym+QUvSSs+HMo w6odgw62hH6rmuzXxgGnwOHMUm+GDEWTEf1bQPB7ro8WMzecBIVVoxPZXUSrCQn92U 4inLw+VzOJrEaOP5xrkXWOnF69dfEcUyq34fSbGX4UXG8Na9YBu9YTlqld0wQo1jq/ wX4MzPAn06RvA== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 7/9] tracing/fprobe-event: Assume fprobe is a return event by $retval Date: Tue, 18 Jul 2023 00:24:27 +0900 Message-Id: <168960746736.34107.3486065330592238119.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Assume the fprobe event is a return event if there is $retval is used in the probe's argument without %return. e.g. echo 'f:myevent vfs_read $retval' >> dynamic_events then 'myevent' is a return probe event. Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_fprobe.c | 58 +++++++++++++++----- .../ftrace/test.d/dynevent/fprobe_syntax_errors.tc | 2 - 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index dfe2e546acdc..3ac0e04071aa 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -898,6 +898,46 @@ static struct tracepoint *find_tracepoint(const char *tp_name) return data.tpoint; } +static int parse_symbol_and_return(int argc, const char *argv[], + char **symbol, bool *is_return, + bool is_tracepoint) +{ + char *tmp = strchr(argv[1], '%'); + int i; + + if (tmp) { + int len = tmp - argv[1]; + + if (!is_tracepoint && !strcmp(tmp, "%return")) { + *is_return = true; + } else { + trace_probe_log_err(len, BAD_ADDR_SUFFIX); + return -EINVAL; + } + *symbol = kmemdup_nul(argv[1], len, GFP_KERNEL); + } else + *symbol = kstrdup(argv[1], GFP_KERNEL); + if (!*symbol) + return -ENOMEM; + + if (*is_return) + return 0; + + /* If there is $retval, this should be a return fprobe. */ + for (i = 2; i < argc; i++) { + tmp = strstr(argv[i], "$retval"); + if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') { + *is_return = true; + /* + * NOTE: Don't check is_tracepoint here, because it will + * be checked when the argument is parsed. + */ + break; + } + } + return 0; +} + static int __trace_fprobe_create(int argc, const char *argv[]) { /* @@ -927,7 +967,7 @@ static int __trace_fprobe_create(int argc, const char *argv[]) struct trace_fprobe *tf = NULL; int i, len, new_argc = 0, ret = 0; bool is_return = false; - char *symbol = NULL, *tmp = NULL; + char *symbol = NULL; const char *event = NULL, *group = FPROBE_EVENT_SYSTEM; const char **new_argv = NULL; int maxactive = 0; @@ -983,20 +1023,10 @@ static int __trace_fprobe_create(int argc, const char *argv[]) trace_probe_log_set_index(1); /* a symbol(or tracepoint) must be specified */ - symbol = kstrdup(argv[1], GFP_KERNEL); - if (!symbol) - return -ENOMEM; + ret = parse_symbol_and_return(argc, argv, &symbol, &is_return, is_tracepoint); + if (ret < 0) + goto parse_error; - tmp = strchr(symbol, '%'); - if (tmp) { - if (!is_tracepoint && !strcmp(tmp, "%return")) { - *tmp = '\0'; - is_return = true; - } else { - trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX); - goto parse_error; - } - } if (!is_return && maxactive) { trace_probe_log_set_index(0); trace_probe_log_err(1, BAD_MAXACT_TYPE); diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc index 812f5b3f6055..72563b2e0812 100644 --- a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc +++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc @@ -30,11 +30,11 @@ check_error 'f:^ vfs_read' # NO_EVENT_NAME check_error 'f:foo/^12345678901234567890123456789012345678901234567890123456789012345 vfs_read' # EVENT_TOO_LONG check_error 'f:foo/^bar.1 vfs_read' # BAD_EVENT_NAME -check_error 'f vfs_read ^$retval' # RETVAL_ON_PROBE check_error 'f vfs_read ^$stack10000' # BAD_STACK_NUM check_error 'f vfs_read ^$arg10000' # BAD_ARG_NUM +check_error 'f vfs_read $retval ^$arg1' # BAD_VAR check_error 'f vfs_read ^$none_var' # BAD_VAR check_error 'f vfs_read ^'$REG # BAD_VAR From patchwork Mon Jul 17 15:24:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315938 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA0D8C001B0 for ; Mon, 17 Jul 2023 15:25:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231743AbjGQPZk (ORCPT ); Mon, 17 Jul 2023 11:25:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231753AbjGQPZQ (ORCPT ); Mon, 17 Jul 2023 11:25:16 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A06C719B0; Mon, 17 Jul 2023 08:24:45 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id BBDA86104A; Mon, 17 Jul 2023 15:24:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B870C433C7; Mon, 17 Jul 2023 15:24:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607482; bh=ApAG9WsE51kt31Nr613fs76Un6BDs5WAbX0BxsdpAn8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CXPeI9Olpd2PQ2cSmU1m8gegxcK4xVk5lVci7yDw8I96t9olXP89EYoBZyaYneToh 76Ytj785hrK0Fc6BmJ9QWoFW4K1kDH4qVftLjgxKIEyfv98xxZbrHxCmPjFLY6i/r7 +4z8fO2yZJAwyiHRz/wuVWBDq3EGn/O0a3aoCzPoOvYyjPuTR5ZSfWj2fhbJ/F/4ux gDZRWt0hxpyGAcAtgkcFG30czTMmtbibdjIQI7zFNi13neGJ1DSfl15vJMzzlaIqnb xIUgJO7bxp18mG797lKvbjacfit1O9feYVfWPGeeC99spMmBTzExUyriXbeMaobdVe FfTbZdcpoUcVw== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 8/9] selftests/ftrace: Add BTF fields access testcases Date: Tue, 18 Jul 2023 00:24:37 +0900 Message-Id: <168960747750.34107.6104527579648222887.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Add test cases for accessing the data structure fields using BTF info. This includes the field access from parameters and retval, and accessing string information. Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Alan Maguire --- Changes in v2: - Use '$retval' instead of 'retval'. - Add a test that use both '$retval' and '$arg1' for fprobe. --- .../ftrace/test.d/dynevent/add_remove_btfarg.tc | 11 +++++++++++ .../ftrace/test.d/dynevent/fprobe_syntax_errors.tc | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc index b89de1771655..93b94468967b 100644 --- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc @@ -21,6 +21,8 @@ echo 0 > events/enable echo > dynamic_events TP=kfree +TP2=kmem_cache_alloc +TP3=getname_flags if [ "$FPROBES" ] ; then echo "f:fpevent $TP object" >> dynamic_events @@ -33,6 +35,7 @@ echo > dynamic_events echo "f:fpevent $TP "'$arg1' >> dynamic_events grep -q "fpevent.*object=object" dynamic_events + echo > dynamic_events echo "f:fpevent $TP "'$arg*' >> dynamic_events @@ -45,6 +48,14 @@ fi echo > dynamic_events +echo "t:tpevent $TP2 name=s->name:string" >> dynamic_events +echo "f:fpevent ${TP3}%return path=\$retval->name:string" >> dynamic_events + +grep -q "tpevent.*name=s->name:string" dynamic_events +grep -q "fpevent.*path=\$retval->name:string" dynamic_events + +echo > dynamic_events + if [ "$KPROBES" ] ; then echo "p:kpevent $TP object" >> dynamic_events grep -q "kpevent.*object=object" dynamic_events diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc index 72563b2e0812..49758f77c923 100644 --- a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc +++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc @@ -103,6 +103,10 @@ check_error 'f vfs_read%return ^$arg*' # NOFENTRY_ARGS check_error 'f vfs_read ^hoge' # NO_BTFARG check_error 'f kfree ^$arg10' # NO_BTFARG (exceed the number of parameters) check_error 'f kfree%return ^$retval' # NO_RETVAL +check_error 'f vfs_read%return $retval->^foo' # NO_PTR_STRCT +check_error 'f vfs_read file->^foo' # NO_BTF_FIELD +check_error 'f vfs_read file^-.foo' # BAD_HYPHEN +check_error 'f vfs_read ^file:string' # BAD_TYPE4STR else check_error 'f vfs_read ^$arg*' # NOSUP_BTFARG check_error 't kfree ^$arg*' # NOSUP_BTFARG From patchwork Mon Jul 17 15:24:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 13315939 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 83124C001B0 for ; Mon, 17 Jul 2023 15:25:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230386AbjGQPZ4 (ORCPT ); Mon, 17 Jul 2023 11:25:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232077AbjGQPZW (ORCPT ); Mon, 17 Jul 2023 11:25:22 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8137E1709; Mon, 17 Jul 2023 08:24:53 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C343E6111E; Mon, 17 Jul 2023 15:24:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4DF3FC433C7; Mon, 17 Jul 2023 15:24:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689607492; bh=jfsyJNrolIUjYdnOxE9K/vaKVHqekN0muXVvxqmYTwY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M0QIKRYqbqOunmlZej0c6MOtavCWOma/HQor1eBeB5aUhCj9cCes5zRUs0EzehPsd 3ZQHFe7jGl3p7a+a3jCxwpZ1wPwGEbCfbGPrbda3oKZ6unysYT6coxbgWNCz8Pu3Ev m7xu4WRWzCaZdRD6Xbu4CqWPgLT5W6Qkx6xKTU23PXgASD0YLan0E/Y0SqyGl4V0a0 3K05gn6FEy626Qhjtkjz6vgioW2Q+tqYg5U2rKLVPVFsyL3umvYBDhRx38B5Bfy7q+ zbFByA7C0PZRE3oU+dhZM/9Uhuzwak/bmBU0KHEQkGAQhwyN3GFck1UY8t8wRkLlm9 7LKpuJFjpofPA== From: "Masami Hiramatsu (Google)" To: linux-trace-kernel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Steven Rostedt , mhiramat@kernel.org, Martin KaFai Lau , bpf@vger.kernel.org, Sven Schnelle , Alexei Starovoitov Subject: [PATCH v2 9/9] Documentation: tracing: Update fprobe event example with BTF field Date: Tue, 18 Jul 2023 00:24:47 +0900 Message-Id: <168960748753.34107.1941635032108706544.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <168960739768.34107.15145201749042174448.stgit@devnote2> References: <168960739768.34107.15145201749042174448.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Update fprobe event example with BTF data structure field specification. Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Alan Maguire --- Changes in v2: - Remove 'retval' and use '$retval'. --- Documentation/trace/fprobetrace.rst | 50 ++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst index 7297f9478459..e9e764fadf14 100644 --- a/Documentation/trace/fprobetrace.rst +++ b/Documentation/trace/fprobetrace.rst @@ -79,9 +79,9 @@ automatically set by the given name. :: f:fprobes/myprobe vfs_read count=count pos=pos It also chooses the fetch type from BTF information. For example, in the above -example, the ``count`` is unsigned long, and the ``pos`` is a pointer. Thus, both -are converted to 64bit unsigned long, but only ``pos`` has "%Lx" print-format as -below :: +example, the ``count`` is unsigned long, and the ``pos`` is a pointer. Thus, +both are converted to 64bit unsigned long, but only ``pos`` has "%Lx" +print-format as below :: # cat events/fprobes/myprobe/format name: myprobe @@ -105,9 +105,33 @@ is expanded to all function arguments of the function or the tracepoint. :: # cat dynamic_events f:fprobes/myprobe vfs_read file=file buf=buf count=count pos=pos -BTF also affects the ``$retval``. If user doesn't set any type, the retval type is -automatically picked from the BTF. If the function returns ``void``, ``$retval`` -is rejected. +BTF also affects the ``$retval``. If user doesn't set any type, the retval +type is automatically picked from the BTF. If the function returns ``void``, +``$retval`` is rejected. + +You can access the data fields of a data structure using allow operator ``->`` +(for pointer type) and dot operator ``.`` (for data structure type.):: + +# echo 't sched_switch preempt prev_pid=prev->pid next_pid=next->pid' >> dynamic_events + +This data field access is available for the return value via ``$retval``, +e.g. ``$retval->name``. + +For these BTF arguments and fields, ``:string`` and ``:ustring`` change the +behavior. If these are used for BTF argument or field, it checks whether +the BTF type of the argument or the data field is ``char *`` or ``char []``, +or not. If not, it rejects applying the string types. Also, with the BTF +support, you don't need a memory dereference operator (``+0(PTR)``) for +accessing the string pointed by a ``PTR``. It automatically adds the memory +dereference operator according to the BTF type. e.g. :: + +# echo 't sched_switch prev->comm:string' >> dynamic_events +# echo 'f getname_flags%return $retval->name:string' >> dynamic_events + +The ``prev->comm`` is an embedded char array in the data structure, and +``$retval->name`` is a char pointer in the data structure. But in both +cases, you can use ``:string`` type to get the string. + Usage examples -------------- @@ -161,10 +185,10 @@ parameters. This means you can access any field values in the task structure pointed by the ``prev`` and ``next`` arguments. For example, usually ``task_struct::start_time`` is not traced, but with this -traceprobe event, you can trace it as below. +traceprobe event, you can trace that field as below. :: - # echo 't sched_switch comm=+1896(next):string start_time=+1728(next):u64' > dynamic_events + # echo 't sched_switch comm=next->comm:string next->start_time' > dynamic_events # head -n 20 trace | tail # TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | @@ -176,13 +200,3 @@ traceprobe event, you can trace it as below. -0 [000] d..3. 5606.690317: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="kworker/0:1" usage=1 start_time=137000000 kworker/0:1-14 [000] d..3. 5606.690339: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0 -0 [000] d..3. 5606.692368: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="kworker/0:1" usage=1 start_time=137000000 - -Currently, to find the offset of a specific field in the data structure, -you need to build kernel with debuginfo and run `perf probe` command with -`-D` option. e.g. -:: - - # perf probe -D "__probestub_sched_switch next->comm:string next->start_time" - p:probe/__probestub_sched_switch __probestub_sched_switch+0 comm=+1896(%cx):string start_time=+1728(%cx):u64 - -And replace the ``%cx`` with the ``next``.