From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D6F81C8603; Sat, 20 Jun 2026 15:17:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781968647; cv=none; b=mYNnJIvImEJD/pP2QwHJl6fxpn58j4hN42bdSqYurVuo1jxL9gYVFpbLZ9fKqzBuh78QN5EdePF18lCAc8XNEuqHUFcaqgKZqqCOwzXpiBUV5M5D1osWM0vaFAfeb63gxq7zYqbvP3NCL8r7oZzYPrj53HLMdnbw8kiCOdUx6Wk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781968647; c=relaxed/simple; bh=G2ftNhH/1OJLr+8QEXAHIkKtnsVoxWbNsvZXaibTgSY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NYGF4InVw9f/R8sGnGY0/mVfgQ3TxebVR7uPlVrRbqIhq+uTL+oJjizrl3if9BxcblD7QtLknSN/lqfGdRHQG1UM64hvifHAzmrx1OeX0uEonCQVetC4ognSM2LBOlXGXnV5r9B8xtWFmGc6UN39gkNORg/2VubAGv6MwRb9idg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TkSq6DYx; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TkSq6DYx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2AEA51F000E9; Sat, 20 Jun 2026 15:17:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1781968646; bh=1eYljiNWldxMT0Zj9sKzV+fvmKH+CTMnb4kw7KPnsEU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=TkSq6DYxdPancncqZtuUpfOaSo4JldjmETD5wi4hZJjJgSybvS9g9CnQo9pPcERxk NryEa8RZxKhbrewWkdTwSetlxf01rF6BiB7JNGTqfXa/2OwEDoQEoNDcfL4dh7I2P0 k73WuGHOw2Gi2Sn3mWvHd4GCiZ9FOWgnqVUDcOBvU1RMtq0/zexWkeGNHLtnrxodJ9 0UuFF0WbG3YglY1ZmD9vbApgc/XbAgp2HZRgNzS2rOjXzsSkrNQNDRPIzeW6Rj26WO x+3Or+e7KkmTBZoM++5UP/+ueUHW7yze6Vj0c2pag7tQRPidtWb/cXJjmihtP9wkJH o12m3En7lLCNA== From: "Masami Hiramatsu (Google)" To: Steven Rostedt , Mathieu Desnoyers Cc: Jonathan Corbet , Shuah Khan , Masami Hiramatsu , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v6 2/8] tracing/probes: Support typecast for various probe events Date: Sun, 21 Jun 2026 00:17:21 +0900 Message-ID: <178196864187.560995.15050848765197490040.stgit@devnote2> X-Mailer: git-send-email 2.43.0 In-Reply-To: <178196862271.560995.5255615288323003663.stgit@devnote2> References: <178196862271.560995.5255615288323003663.stgit@devnote2> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit From: Masami Hiramatsu (Google) Support BTF typecast feature on other probe events, but only if it is kernel function entry or return, and must use function parameter name or $retval. This means you can do: (STRUCT)PARAM->MEMBER Note: you can not use other variables like $stackN, %reg etc. That needs nesting support. To support other probe events, we just need to use last_struct type when we find a function parameter in parse_btf_arg(). This also updates /README file to show struct typecast. Signed-off-by: Masami Hiramatsu (Google) --- Changes in v5: - Add comments about $retval with typecast. - Even if the type of retvalue is not known, if user specifies typecast, use it for its type. Changes in v3: - Clarify the limitation. Changes in v2: - Fix to re-enable typecast on eprobe. --- Documentation/trace/fprobetrace.rst | 3 +++ Documentation/trace/kprobetrace.rst | 4 ++++ kernel/trace/trace.c | 2 +- kernel/trace/trace_probe.c | 23 +++++++++++++++++------ kernel/trace/trace_probe.h | 5 +++++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst index b4c2ca3d02c1..7435ded2d66d 100644 --- a/Documentation/trace/fprobetrace.rst +++ b/Documentation/trace/fprobetrace.rst @@ -57,6 +57,9 @@ Synopsis of fprobe-events (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types (x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr" and bitfield are supported. + (STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to + a pointer to STRUCT and then derference the pointer defined by + ->MEMBER. (\*1) This is available only when BTF is enabled. (\*2) only for the probe on function entry (offs == 0). Note, this argument access diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst index 3b6791c17e9b..f73614997d52 100644 --- a/Documentation/trace/kprobetrace.rst +++ b/Documentation/trace/kprobetrace.rst @@ -61,6 +61,10 @@ Synopsis of kprobe_events (x8/x16/x32/x64), VFS layer common type(%pd/%pD), "char", "string", "ustring", "symbol", "symstr" and bitfield are supported. + (STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to + a pointer to STRUCT and then derference the pointer defined by + ->MEMBER. Note that this is available only when the probe is + on function entry. (\*1) only for the probe on function entry (offs == 0). Note, this argument access is best effort, because depending on the argument type, it may be passed on diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6eb4d3097a4d..aa93e7b01146 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4325,7 +4325,7 @@ static const char readme_msg[] = #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API "\t $stack, $stack, $retval, $comm, $arg,\n" #ifdef CONFIG_PROBE_EVENTS_BTF_ARGS - "\t [->field[->field|.field...]],\n" + "\t [(structname)][->field[->field|.field...]],\n" #endif #else "\t $stack, $stack, $retval, $comm,\n" diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 9d174cd1fb1c..76ee3ca48d6a 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -706,7 +706,7 @@ static int parse_btf_arg(char *varname, if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) { code->op = FETCH_OP_RETVAL; - /* Check whether the function return type is not void */ + /* Check whether the function return type is not void, even with typecast. */ if (query_btf_context(ctx) == 0) { if (ctx->proto->type == 0) { trace_probe_log_err(ctx->offset, NO_RETVAL); @@ -715,6 +715,13 @@ static int parse_btf_arg(char *varname, tid = ctx->proto->type; goto found; } + /* + * Even if we can not find appropriate BTF info, we can still access + * the field via typecast. + */ + if (ctx->struct_btf) + goto found; + if (field) { trace_probe_log_err(ctx->offset + field - varname, NO_BTF_ENTRY); @@ -759,7 +766,10 @@ static int parse_btf_arg(char *varname, return -ENOENT; found: - type = btf_type_skip_modifiers(ctx->btf, tid, &tid); + if (ctx->struct_btf) + type = ctx->last_struct; + else + type = btf_type_skip_modifiers(ctx->btf, tid, &tid); found_type: if (!type) { trace_probe_log_err(ctx->offset, BAD_BTF_TID); @@ -836,10 +846,11 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode, char *tmp; int ret; - /* Currently this only works for eprobes */ - if (!(ctx->flags & TPARG_FL_TEVENT)) { - trace_probe_log_err(ctx->offset, TYPECAST_NOT_EVENT); - return -EINVAL; + if (!(tparg_is_event_probe(ctx->flags) || + tparg_is_function_entry(ctx->flags) || + tparg_is_function_return(ctx->flags))) { + trace_probe_log_err(ctx->offset, NOSUP_BTFARG); + return -EOPNOTSUPP; } tmp = strchr(arg, ')'); diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index b428ef42b229..e112424f3529 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -431,6 +431,11 @@ static inline bool tparg_is_function_return(unsigned int flags) return (flags & TPARG_FL_LOC_MASK) == (TPARG_FL_KERNEL | TPARG_FL_RETURN); } +static inline bool tparg_is_event_probe(unsigned int flags) +{ + return !!(flags & TPARG_FL_TEVENT); +} + struct traceprobe_parse_context { struct trace_event_call *event; /* BTF related parameters */