Skip to content

Commit b576e09

Browse files
committed
tracing/probes: Support function parameters if BTF is available
Support function or tracepoint parameters by name if BTF support is enabled and the event is for function entry (this feature can be used with kprobe- events, fprobe-events and tracepoint probe events.) Note that the BTF variable syntax does not require a prefix. If it starts with an alphabetic character or an underscore ('_') without a prefix like '$' and '%', it is considered as a BTF variable. If you specify only the BTF variable name, the argument name will also be the same name instead of 'arg*'. # echo 'p vfs_read count pos' >> dynamic_events # echo 'f vfs_write count pos' >> dynamic_events # echo 't sched_overutilized_tp rd overutilized' >> dynamic_events # cat dynamic_events p:kprobes/p_vfs_read_0 vfs_read count=count pos=pos f:fprobes/vfs_write__entry vfs_write count=count pos=pos t:tracepoints/sched_overutilized_tp sched_overutilized_tp rd=rd overutilized=overutilized Link: https://lore.kernel.org/all/168507474014.913472.16963996883278039183.stgit@mhiramat.roam.corp.google.com/ Signed-off-by: Masami Hiramatsu (Google) <[email protected]> Reviewed-by: Alan Maguire <[email protected]> Tested-by: Alan Maguire <[email protected]>
1 parent 1b8b0cd commit b576e09

File tree

6 files changed

+270
-31
lines changed

6 files changed

+270
-31
lines changed

kernel/trace/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,18 @@ config FPROBE_EVENTS
664664
and the kprobe events on function entry and exit will be
665665
transparently converted to this fprobe events.
666666

667+
config PROBE_EVENTS_BTF_ARGS
668+
depends on HAVE_FUNCTION_ARG_ACCESS_API
669+
depends on FPROBE_EVENTS || KPROBE_EVENTS
670+
depends on DEBUG_INFO_BTF && BPF_SYSCALL
671+
bool "Support BTF function arguments for probe events"
672+
default y
673+
help
674+
The user can specify the arguments of the probe event using the names
675+
of the arguments of the probed function, when the probe location is a
676+
kernel function entry or a tracepoint.
677+
This is available only if BTF (BPF Type Format) support is enabled.
678+
667679
config KPROBE_EVENTS
668680
depends on KPROBES
669681
depends on HAVE_REGS_AND_STACK_ACCESS_API

kernel/trace/trace.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5698,7 +5698,11 @@ static const char readme_msg[] =
56985698
"\t args: <name>=fetcharg[:type]\n"
56995699
"\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
57005700
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
5701+
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
5702+
"\t $stack<index>, $stack, $retval, $comm, $arg<N>, <argname>\n"
5703+
#else
57015704
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
5705+
#endif
57025706
#else
57035707
"\t $stack<index>, $stack, $retval, $comm,\n"
57045708
#endif

kernel/trace/trace_fprobe.c

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ static void free_trace_fprobe(struct trace_fprobe *tf)
366366
static struct trace_fprobe *alloc_trace_fprobe(const char *group,
367367
const char *event,
368368
const char *symbol,
369+
struct tracepoint *tpoint,
369370
int maxactive,
370371
int nargs, bool is_return)
371372
{
@@ -385,6 +386,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
385386
else
386387
tf->fp.entry_handler = fentry_dispatcher;
387388

389+
tf->tpoint = tpoint;
388390
tf->fp.nr_maxactive = maxactive;
389391

390392
ret = trace_probe_init(&tf->tp, event, group, false);
@@ -930,8 +932,12 @@ static int __trace_fprobe_create(int argc, const char *argv[])
930932
int maxactive = 0;
931933
char buf[MAX_EVENT_NAME_LEN];
932934
char gbuf[MAX_EVENT_NAME_LEN];
933-
unsigned int flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE;
935+
char sbuf[KSYM_NAME_LEN];
934936
bool is_tracepoint = false;
937+
struct tracepoint *tpoint = NULL;
938+
struct traceprobe_parse_context ctx = {
939+
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
940+
};
935941

936942
if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2)
937943
return -ECANCELED;
@@ -995,14 +1001,6 @@ static int __trace_fprobe_create(int argc, const char *argv[])
9951001
goto parse_error;
9961002
}
9971003

998-
if (is_return)
999-
flags |= TPARG_FL_RETURN;
1000-
else
1001-
flags |= TPARG_FL_FENTRY;
1002-
1003-
if (is_tracepoint)
1004-
flags |= TPARG_FL_TPOINT;
1005-
10061004
trace_probe_log_set_index(0);
10071005
if (event) {
10081006
ret = traceprobe_parse_event_name(&event, &group, gbuf,
@@ -1014,16 +1012,36 @@ static int __trace_fprobe_create(int argc, const char *argv[])
10141012
if (!event) {
10151013
/* Make a new event name */
10161014
if (is_tracepoint)
1017-
strscpy(buf, symbol, MAX_EVENT_NAME_LEN);
1015+
snprintf(buf, MAX_EVENT_NAME_LEN, "%s%s",
1016+
isdigit(*symbol) ? "_" : "", symbol);
10181017
else
10191018
snprintf(buf, MAX_EVENT_NAME_LEN, "%s__%s", symbol,
10201019
is_return ? "exit" : "entry");
10211020
sanitize_event_name(buf);
10221021
event = buf;
10231022
}
10241023

1024+
if (is_return)
1025+
ctx.flags |= TPARG_FL_RETURN;
1026+
else
1027+
ctx.flags |= TPARG_FL_FENTRY;
1028+
1029+
if (is_tracepoint) {
1030+
ctx.flags |= TPARG_FL_TPOINT;
1031+
tpoint = find_tracepoint(symbol);
1032+
if (!tpoint) {
1033+
trace_probe_log_set_index(1);
1034+
trace_probe_log_err(0, NO_TRACEPOINT);
1035+
goto parse_error;
1036+
}
1037+
ctx.funcname = kallsyms_lookup(
1038+
(unsigned long)tpoint->probestub,
1039+
NULL, NULL, NULL, sbuf);
1040+
} else
1041+
ctx.funcname = symbol;
1042+
10251043
/* setup a probe */
1026-
tf = alloc_trace_fprobe(group, event, symbol, maxactive,
1044+
tf = alloc_trace_fprobe(group, event, symbol, tpoint, maxactive,
10271045
argc - 2, is_return);
10281046
if (IS_ERR(tf)) {
10291047
ret = PTR_ERR(tf);
@@ -1032,24 +1050,15 @@ static int __trace_fprobe_create(int argc, const char *argv[])
10321050
goto out; /* We know tf is not allocated */
10331051
}
10341052

1035-
if (is_tracepoint) {
1036-
tf->tpoint = find_tracepoint(tf->symbol);
1037-
if (!tf->tpoint) {
1038-
trace_probe_log_set_index(1);
1039-
trace_probe_log_err(0, NO_TRACEPOINT);
1040-
goto parse_error;
1041-
}
1053+
if (is_tracepoint)
10421054
tf->mod = __module_text_address(
10431055
(unsigned long)tf->tpoint->probestub);
1044-
}
10451056

10461057
argc -= 2; argv += 2;
1047-
10481058
/* parse arguments */
10491059
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
1050-
struct traceprobe_parse_context ctx = { .flags = flags };
1051-
10521060
trace_probe_log_set_index(i + 2);
1061+
ctx.offset = 0;
10531062
ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx);
10541063
if (ret)
10551064
goto error; /* This can be -ENOMEM */

kernel/trace/trace_kprobe.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
742742
void *addr = NULL;
743743
char buf[MAX_EVENT_NAME_LEN];
744744
char gbuf[MAX_EVENT_NAME_LEN];
745-
unsigned int flags = TPARG_FL_KERNEL;
745+
struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
746746

747747
switch (argv[0][0]) {
748748
case 'r':
@@ -823,10 +823,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])
823823
goto parse_error;
824824
}
825825
if (is_return)
826-
flags |= TPARG_FL_RETURN;
826+
ctx.flags |= TPARG_FL_RETURN;
827827
ret = kprobe_on_func_entry(NULL, symbol, offset);
828828
if (ret == 0 && !is_return)
829-
flags |= TPARG_FL_FENTRY;
829+
ctx.flags |= TPARG_FL_FENTRY;
830830
/* Defer the ENOENT case until register kprobe */
831831
if (ret == -EINVAL && is_return) {
832832
trace_probe_log_err(0, BAD_RETPROBE);
@@ -856,7 +856,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
856856

857857
/* setup a probe */
858858
tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
859-
argc - 2, is_return);
859+
argc - 2, is_return);
860860
if (IS_ERR(tk)) {
861861
ret = PTR_ERR(tk);
862862
/* This must return -ENOMEM, else there is a bug */
@@ -866,10 +866,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])
866866
argc -= 2; argv += 2;
867867

868868
/* parse arguments */
869+
ctx.funcname = symbol;
869870
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
870-
struct traceprobe_parse_context ctx = { .flags = flags };
871-
872871
trace_probe_log_set_index(i + 2);
872+
ctx.offset = 0;
873873
ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);
874874
if (ret)
875875
goto error; /* This can be -ENOMEM */

0 commit comments

Comments
 (0)