History

tracing/probes: Add $current variable support

Since we can use the BTF to cast value to a structure pointer type, it is useful to introduce "$current" special variable support to fetcharg. User can define a fetcharg to access current task_struct properties using BTF info. e.g. $current->cpus_ptr Link: https://lore.kernel.org/all/178271366709.1176915.15320906169981578568.stgit@devnote2/

Masami Hiramatsu (Google) committed 4 months ago

Commit 738b78e1 parent f2183456 files · +44 −3Browse files

Showing the changes to kernel (4 of 6 files). Show all

Unified · Split

4 files
  1. kernel/trace/trace.c +2 −2
  2. kernel/trace/trace_probe.c +36 −1
  3. kernel/trace/trace_probe.h +1 −0
  4. kernel/trace/trace_probe_tmpl.h +3 −0
kernel/trace/trace.c+2−2
@@ -4320,13 +4320,13 @@ static const char readme_msg[] = · 4319 unmodified lines
4320 "\t args: <name>=fetcharg[:type]\n"4320 "\t args: <name>=fetcharg[:type]\n"
4321 "\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"4321 "\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
4322#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API4322#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
4323 "\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"4323 "\t $stack<index>, $stack, $retval, $comm, $arg<N>, $current\n"
4324#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS4324#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
4325 "\t [(structname[,field])]<argname>[->field[->field|.field...]],\n"4325 "\t [(structname[,field])]<argname>[->field[->field|.field...]],\n"
4326 "\t [(structname[,field])](fetcharg)->field[->field|.field...],\n"4326 "\t [(structname[,field])](fetcharg)->field[->field|.field...],\n"
4327#endif4327#endif
4328#else4328#else
4329 "\t $stack<index>, $stack, $retval, $comm,\n"4329 "\t $stack<index>, $stack, $retval, $comm, $current\n"
4330#endif4330#endif
4331 "\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"4331 "\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
4332 "\t kernel return probes support: $retval, $arg<N>, $comm\n"4332 "\t kernel return probes support: $retval, $arg<N>, $comm\n"
kernel/trace/trace_probe.c+36−1
@@ -692,7 +692,9 @@ static int parse_btf_arg(char *varname, · 691 unmodified lines
692 int i, is_ptr, ret;692 int i, is_ptr, ret;
693 u32 tid;693 u32 tid;
694 694
695 if (!ctx->funcname && !(ctx->flags & TPARG_FL_TEVENT))695 /* Note: field is not separated at this point, so check prefix. */
696 if (!str_has_prefix(varname, "$current") &&
697 !ctx->funcname && !(ctx->flags & TPARG_FL_TEVENT))
696 return -EINVAL;698 return -EINVAL;
697 699
698 is_ptr = split_next_field(varname, &field, ctx);700 is_ptr = split_next_field(varname, &field, ctx);
@@ -705,6 +707,20 @@ static int parse_btf_arg(char *varname, · 6 unmodified lines
705 return -EOPNOTSUPP;707 return -EOPNOTSUPP;
706 }708 }
707 709
710 if (!strcmp(varname, "$current")) {
711 code->op = FETCH_OP_CURRENT;
712 /* If no typecast is specified for $current, use task_struct by default */
713 ret = bpf_find_btf_id("task_struct", BTF_KIND_STRUCT, &ctx->struct_btf);
714 if (ret < 0) {
715 trace_probe_log_err(ctx->offset, NO_BTF_ENTRY);
716 return -ENOENT;
717 }
718 tid = (u32)ret;
719 type = ctx->last_struct =
720 btf_type_skip_modifiers(ctx->struct_btf, tid, NULL);
721 goto found_type;
722 }
723
708 if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) {724 if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) {
709 code->op = FETCH_OP_RETVAL;725 code->op = FETCH_OP_RETVAL;
710 /* Check whether the function return type is not void, even with typecast. */726 /* Check whether the function return type is not void, even with typecast. */
@@ -761,6 +777,7 @@ static int parse_btf_arg(char *varname, · 50 unmodified lines
761 777
762found:778found:
763 type = btf_type_skip_modifiers(ctx->btf, tid, NULL);779 type = btf_type_skip_modifiers(ctx->btf, tid, NULL);
780found_type:
764 if (!type) {781 if (!type) {
765 trace_probe_log_err(ctx->offset, BAD_BTF_TID);782 trace_probe_log_err(ctx->offset, BAD_BTF_TID);
766 return -EINVAL;783 return -EINVAL;
@@ -1270,6 +1287,24 @@ static int parse_probe_vars(char *orig_arg, const struct fetch_type *t, · 503 unmodified lines
1270 return 0;1287 return 0;
1271 }1288 }
1272 1289
1290 /* $current returns the address of the current task_struct. */
1291 if (str_has_prefix(arg, "current")) {
1292 /* $current is only supported by kernel probe. */
1293 if (!(ctx->flags & TPARG_FL_KERNEL)) {
1294 err = TP_ERR_BAD_VAR;
1295 goto inval;
1296 }
1297 arg += strlen("current");
1298 if (*arg == '-' && IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS))
1299 return parse_btf_arg(orig_arg, pcode, end, ctx);
1300
1301 if (*arg != '\0')
1302 goto inval;
1303
1304 code->op = FETCH_OP_CURRENT;
1305 return 0;
1306 }
1307
1273#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API1308#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
1274 len = str_has_prefix(arg, "arg");1309 len = str_has_prefix(arg, "arg");
1275 if (len) {1310 if (len) {
kernel/trace/trace_probe.h+1−0
@@ -92,6 +92,7 @@ typedef int (*print_type_func_t)(struct trace_seq *, void *, void *); · 91 unmodified lines
92 FETCH_OP(RETVAL, none), /* Return value */ \92 FETCH_OP(RETVAL, none), /* Return value */ \
93 FETCH_OP(IMM, imm), /* Immediate: .immediate */ \93 FETCH_OP(IMM, imm), /* Immediate: .immediate */ \
94 FETCH_OP(COMM, none), /* Current comm */ \94 FETCH_OP(COMM, none), /* Current comm */ \
95 FETCH_OP(CURRENT, none), /* Current task_struct address */\
95 FETCH_OP(ARG, param), /* Argument: .param = index */ \96 FETCH_OP(ARG, param), /* Argument: .param = index */ \
96 FETCH_OP(FOFFS, imm), /* File offset: .immediate */ \97 FETCH_OP(FOFFS, imm), /* File offset: .immediate */ \
97 FETCH_OP(IMMSTR, string), /* Allocated string: .data */ \98 FETCH_OP(IMMSTR, string), /* Allocated string: .data */ \
kernel/trace/trace_probe_tmpl.h+3−0
@@ -112,6 +112,9 @@ process_common_fetch_insn(struct fetch_insn *code, unsigned long *val) · 111 unmodified lines
112 case FETCH_OP_IMMSTR:112 case FETCH_OP_IMMSTR:
113 *val = (unsigned long)code->data;113 *val = (unsigned long)code->data;
114 break;114 break;
115 case FETCH_OP_CURRENT:
116 *val = (unsigned long)current;
117 break;
115 default:118 default:
116 return -EILSEQ;119 return -EILSEQ;
117 }120 }