From patchwork Sat Jun 17 09:47: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: 13283484 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 1F660EB64D9 for ; Sat, 17 Jun 2023 09:47:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345766AbjFQJrP (ORCPT ); Sat, 17 Jun 2023 05:47:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46806 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231894AbjFQJrO (ORCPT ); Sat, 17 Jun 2023 05:47: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 4D55E10CF; Sat, 17 Jun 2023 02:47:12 -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 ABE8860B00; Sat, 17 Jun 2023 09:47:11 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DCE0CC433C0; Sat, 17 Jun 2023 09:47:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1686995231; bh=oVwqmRQaH2ufbP0ltBUTQ/C0zTTZTGE8OotgvdeC0Rg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rFen5P1EDCfQ5EueLyibDVh4iDbxRmgK7O7g3M2rHr2j5FZHwEBCTOx7lFunvDOTd oyGZJEGvoOQM3eZcxV0pY4VkZZtfqC7Fv7q156nMKDsgW4QX4Bd+Fh2o2+pJVCKMB6 +dJ6RgnRc5uArfSzGMPrf8Vo6ClPeYF6tZKuVDRokWSXVxeYZJP5s50glHAdMKDokE YAEck8cDbvo8oqPEcsjZ/xyBBmpYpEdjH71W7sfkAmB+xUcl4VP75qfrJSubsrU62I IsD8Zcd9tpjpiVa2Z3t1bZnxzV/8LUisRzWBcIUl+IG7b9YqbG7ebOeC8eXg0CDo8h 3i1mGQ+DrI2ig== 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 Subject: [PATCH 1/5] tracing/probes: Support BTF based data structure field access Date: Sat, 17 Jun 2023 18:47:07 +0900 Message-ID: <168699522768.528797.12822003087750644635.stgit@mhiramat.roam.corp.google.com> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog In-Reply-To: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> References: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> 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) --- kernel/trace/trace_probe.c | 254 +++++++++++++++++++++++++++++++++++++++----- kernel/trace/trace_probe.h | 11 ++ 2 files changed, 238 insertions(+), 27 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 643aa3a51d5a..1f05c819633f 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 */ @@ -425,12 +427,145 @@ 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, +static const struct btf_member *find_btf_field(const struct btf_type *type, + const char *name) +{ + struct btf *btf = traceprobe_get_btf(); + const struct btf_member *fields; + int i, vlen; + u32 kind; + + kind = BTF_INFO_KIND(type->info); + if (kind != BTF_KIND_STRUCT && kind != BTF_KIND_UNION) + return NULL; + + vlen = btf_type_vlen(type); + fields = (const struct btf_member *)(type + 1); + for (i = 0; i < vlen; i++) { + const char *_name = btf_name_by_offset(btf, fields[i].name_off); + + /* TODO: support anonymous union/struct */ + if (_name && !strcmp(_name, name)) + return fields + i; + } + + return NULL; +} + +/* 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 = find_btf_field(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); @@ -440,6 +575,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); @@ -460,24 +605,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); } @@ -487,17 +647,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 = find_btf_func_proto(ctx->funcname); - if (!IS_ERR(t)) - typestr = type_from_btf_id(btf, t->type); + type = find_btf_func_proto(ctx->funcname); + if (!IS_ERR(type)) { + type = btf_type_skip_modifiers(btf, type->type, &tid); + if (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) { const struct btf_type *t; @@ -520,14 +706,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) \ @@ -795,6 +989,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 */ @@ -818,7 +1014,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; } } @@ -964,6 +1160,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) @@ -971,9 +1168,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); } @@ -1048,6 +1245,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 Sat Jun 17 09:47:16 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: 13283485 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 4B863EB64DA for ; Sat, 17 Jun 2023 09:47:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345655AbjFQJr3 (ORCPT ); Sat, 17 Jun 2023 05:47:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345853AbjFQJrX (ORCPT ); Sat, 17 Jun 2023 05:47:23 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1157C172A; Sat, 17 Jun 2023 02:47:21 -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 A2D3360A2C; Sat, 17 Jun 2023 09:47:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD3CCC433C0; Sat, 17 Jun 2023 09:47:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1686995240; bh=xuogGb7rV3OR5mTY5x/kVEP90kY4oCcvhU0IrpGAk1M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rLzGxA4qB2mn3c+bhmXxbeRenqE+jTL1VIi1LV0Az/YyY9J0dnc7dx5922Dphv1qO 9K+EKQ67dHSgzOzs3i8QDYOlXZuqQHVPi5mZuL7GNS+BLLyhmgcHVIiUHqnSSr45a2 5MNk8EAAUZ62y7UfLkNCFZptRKcIkMAcKoENV4oLBSMex0beUD7VpT2MH7hJ+CQR8m ZRc6ftcr9rX/mJpcuGyVBGjVuTB/PaaN9ATz6xplopx9BQXMS4XmOAFc+WyxGUdiQ0 /weAGIEiOxBX+V057hxt7T0CDuL65DVRqMLKSYNgTEN9zV5zKkGXalCeoZQMxdt3ts 8baAL2IbB5C2A== 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 Subject: [PATCH 2/5] tracing/probes: Support BTF field access from retval Date: Sat, 17 Jun 2023 18:47:16 +0900 Message-ID: <168699523643.528797.2114547152033345802.stgit@mhiramat.roam.corp.google.com> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog In-Reply-To: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> References: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> 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) Introduce 'retval' (Not '$retval') BTF argument 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) --- kernel/trace/trace_probe.c | 54 +++++++++++++++++--------------------------- kernel/trace/trace_probe.h | 7 ++++++ 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 1f05c819633f..0149d0abb5fd 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -585,6 +585,21 @@ 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; + } + type = find_btf_func_proto(ctx->funcname); + if (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); @@ -605,7 +620,6 @@ static int parse_btf_arg(char *varname, code->param = i + 1; else code->param = i; - tid = params[i].type; goto found; } @@ -630,7 +644,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(); @@ -642,26 +656,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 = find_btf_func_proto(ctx->funcname); - if (!IS_ERR(type)) { - type = btf_type_skip_modifiers(btf, type->type, &tid); - if (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) { @@ -721,10 +715,7 @@ 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) @@ -1010,7 +1001,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type, break; default: if (isalpha(arg[0]) || arg[0] == '_') { /* BTF variable */ - if (!tparg_is_function_entry(ctx->flags)) { + if (!tparg_is_btf_available(ctx->flags)) { trace_probe_log_err(ctx->offset, NOSUP_BTFARG); return -EINVAL; } @@ -1167,12 +1158,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 */ diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index 050909aaaa1b..7aae50633819 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -381,6 +381,13 @@ static inline bool tparg_is_function_entry(unsigned int flags) return (flags & TPARG_FL_LOC_MASK) == (TPARG_FL_KERNEL | TPARG_FL_FENTRY); } +/* BTF is available at the kernel function entry and exit */ +static inline bool tparg_is_btf_available(unsigned int flags) +{ + return (flags & TPARG_FL_KERNEL) && + (flags & (TPARG_FL_FENTRY | TPARG_FL_RETURN)); +} + struct traceprobe_parse_context { struct trace_event_call *event; const struct btf_param *params; From patchwork Sat Jun 17 09:47:25 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: 13283486 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 180EBEB64DA for ; Sat, 17 Jun 2023 09:47:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346157AbjFQJrn (ORCPT ); Sat, 17 Jun 2023 05:47:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47164 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346111AbjFQJre (ORCPT ); Sat, 17 Jun 2023 05:47:34 -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 DBC4D213F; Sat, 17 Jun 2023 02:47:29 -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 573FA60FD3; Sat, 17 Jun 2023 09:47:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 64846C433C0; Sat, 17 Jun 2023 09:47:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1686995248; bh=vJO4M0HM7FCevR0pjwlrbpVfGQ59SezS/bPy03sX8pU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WyGEQgw4Q2w72iPZXh5b1bxNwyXW4JXDynPgp5zWd1ABzGpYi9g3u045HfMzERpy3 2h2xEsvd0jbDYSVJagz/twLhNVin8adIAlIxLubOBAJf01Tz/cQTi0RTbCImjTkRQC GAQ0k69BDhz86FrmQhgCmPPjwZJ2Md/cTf/Hv57JgBu25br7YhCflm1tjsBJaBdFPr sB7lT8yMIqBXt4/ELvJIMoup5ntDsyLcvnZbvhw+WI2qUbFX6rKEf+O64uHWBOLS3M F/7mhU3ZOqCvVr7MAD090JsCaEEcKLE2LPZhKGfbyT1LwxyEOnjXrlceH04rGBIIO1 Qm1vZe1NMEKFQ== 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 Subject: [PATCH 3/5] tracing/probes: Add string type check with BTF Date: Sat, 17 Jun 2023 18:47:25 +0900 Message-ID: <168699524550.528797.10869028703938811455.stgit@mhiramat.roam.corp.google.com> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog In-Reply-To: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> References: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> 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 0149d0abb5fd..85c9c939424c 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) @@ -720,6 +791,13 @@ static int parse_btf_bitfield(struct fetch_insn **pcode, #define is_btf_retval_void(funcname) (false) +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)) @@ -1159,8 +1237,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 7aae50633819..c6da67afa62c 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -511,7 +511,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 Sat Jun 17 09:47:34 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: 13283487 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 30049EB64D9 for ; Sat, 17 Jun 2023 09:47:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234017AbjFQJr6 (ORCPT ); Sat, 17 Jun 2023 05:47:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345853AbjFQJrr (ORCPT ); Sat, 17 Jun 2023 05:47:47 -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 B19142D57; Sat, 17 Jun 2023 02:47:38 -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 36C8760FD3; Sat, 17 Jun 2023 09:47:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 80B76C433C8; Sat, 17 Jun 2023 09:47:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1686995257; bh=CcwbWOQ4OramJFaq7GvKNk6UZrAxKnsXUYiWXTp2YLw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=omINw6hIKCE2V19jvlvAfpBxjFVYhWclregmAAU1iGSkUXgOf3qDsbaFO69ELoKHv fOHMkmYQ2cYVbLZkSlYMiU4nblxel71wYMYUZpAo+OHKcPcDe6nlPDpwjTO3EzVPPu chZpCnKSG9i/Ixr3uchf6NzpH6LL8I9JeOrUCNSVJG5ZGT2LfHGEfF+MbXeCQey17s AuuTSvv4cNHwThdoQXzOL3VPOpxMhJPnEjckjiInCtpT/D3KbveOl0ygUTYsnuHBq8 DkkE47kBmzQ59JSqg5xzUtCw1CI04eztT2GiwXrOuTXR9rhSR66/czjNQNwRyf4Hpu DYiO0g/TVXUNg== 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 Subject: [PATCH 4/5] selftests/ftrace: Add BTF fields access testcases Date: Sat, 17 Jun 2023 18:47:34 +0900 Message-ID: <168699525410.528797.4712561681569320532.stgit@mhiramat.roam.corp.google.com> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog In-Reply-To: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> References: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> 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) --- .../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..1c46906ebf54 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 812f5b3f6055..c948095d0d15 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 Sat Jun 17 09:47:43 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: 13283488 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 B8EF1EB64DA for ; Sat, 17 Jun 2023 09:48:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346127AbjFQJsH (ORCPT ); Sat, 17 Jun 2023 05:48:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346227AbjFQJr6 (ORCPT ); Sat, 17 Jun 2023 05:47:58 -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 906192702; Sat, 17 Jun 2023 02:47: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 1C34C60C78; Sat, 17 Jun 2023 09:47:47 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F483C433C8; Sat, 17 Jun 2023 09:47:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1686995266; bh=wcKHQ83tUBIj4P7lFgG+UJ1CdvhUlPrZ2dz37C5OMt8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lMUmoh/DayBP4TRAA2aa5Pr3Ju0C9Dby8NsXJt6cQVtdvbFu6qLj1Zj90fd0HZsWD 5Px+qh8uJRL/LZBy39ie7kcc4XAufO5rJO6sTEnxco/o0X5wpxE2Sk5xFhrIkuw7do tkpQAkpF6tGYIm92QePx1nAicbxGChsNzYZFpOF7jbxzyYZ9z+WVBwUhureoA+yjig yBK2Otsl1LnJYSacXDuC2+/33jnLOe03/ovlyArKOYS0lwwXY+Fifi4iVF97r52EaL H+rU/bizpwjTJP0UxR+UvIq4nqCRu8leAlRj0XQLQHkl2AByR5yYiIpYA76UW/9RCr GakVeg6prv9vg== 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 Subject: [PATCH 5/5] Documentation: tracing: Update fprobe event example with BTF field Date: Sat, 17 Jun 2023 18:47:43 +0900 Message-ID: <168699526301.528797.1373223673372258578.stgit@mhiramat.roam.corp.google.com> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog In-Reply-To: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> References: <168699521817.528797.13179901018528120324.stgit@mhiramat.roam.corp.google.com> 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) --- 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..c141f900afda 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, for this purpose +``retval`` special variable name needs to be used. 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``.