summaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_fprobe.c
diff options
context:
space:
mode:
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>2023-06-06 21:39:56 +0900
committerMasami Hiramatsu (Google) <mhiramat@kernel.org>2023-06-06 21:39:56 +0900
commitb576e09701c7d045bbe5cd85d53e2f34426aa214 (patch)
tree20d10ab0213b47f5640051cf45a6510c8f1d625a /kernel/trace/trace_fprobe.c
parent1b8b0cd754cdbb54058165992456368495a695ac (diff)
downloadlinux-b576e09701c7d045bbe5cd85d53e2f34426aa214.tar.gz
linux-b576e09701c7d045bbe5cd85d53e2f34426aa214.tar.bz2
linux-b576e09701c7d045bbe5cd85d53e2f34426aa214.zip
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) <mhiramat@kernel.org> Reviewed-by: Alan Maguire <alan.maguire@oracle.com> Tested-by: Alan Maguire <alan.maguire@oracle.com>
Diffstat (limited to 'kernel/trace/trace_fprobe.c')
-rw-r--r--kernel/trace/trace_fprobe.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index 7d144e4a3fb6..2dd884609321 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -366,6 +366,7 @@ static void free_trace_fprobe(struct trace_fprobe *tf)
static struct trace_fprobe *alloc_trace_fprobe(const char *group,
const char *event,
const char *symbol,
+ struct tracepoint *tpoint,
int maxactive,
int nargs, bool is_return)
{
@@ -385,6 +386,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
else
tf->fp.entry_handler = fentry_dispatcher;
+ tf->tpoint = tpoint;
tf->fp.nr_maxactive = maxactive;
ret = trace_probe_init(&tf->tp, event, group, false);
@@ -930,8 +932,12 @@ static int __trace_fprobe_create(int argc, const char *argv[])
int maxactive = 0;
char buf[MAX_EVENT_NAME_LEN];
char gbuf[MAX_EVENT_NAME_LEN];
- unsigned int flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE;
+ char sbuf[KSYM_NAME_LEN];
bool is_tracepoint = false;
+ struct tracepoint *tpoint = NULL;
+ struct traceprobe_parse_context ctx = {
+ .flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
+ };
if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2)
return -ECANCELED;
@@ -995,14 +1001,6 @@ static int __trace_fprobe_create(int argc, const char *argv[])
goto parse_error;
}
- if (is_return)
- flags |= TPARG_FL_RETURN;
- else
- flags |= TPARG_FL_FENTRY;
-
- if (is_tracepoint)
- flags |= TPARG_FL_TPOINT;
-
trace_probe_log_set_index(0);
if (event) {
ret = traceprobe_parse_event_name(&event, &group, gbuf,
@@ -1014,7 +1012,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
if (!event) {
/* Make a new event name */
if (is_tracepoint)
- strscpy(buf, symbol, MAX_EVENT_NAME_LEN);
+ snprintf(buf, MAX_EVENT_NAME_LEN, "%s%s",
+ isdigit(*symbol) ? "_" : "", symbol);
else
snprintf(buf, MAX_EVENT_NAME_LEN, "%s__%s", symbol,
is_return ? "exit" : "entry");
@@ -1022,8 +1021,27 @@ static int __trace_fprobe_create(int argc, const char *argv[])
event = buf;
}
+ if (is_return)
+ ctx.flags |= TPARG_FL_RETURN;
+ else
+ ctx.flags |= TPARG_FL_FENTRY;
+
+ if (is_tracepoint) {
+ ctx.flags |= TPARG_FL_TPOINT;
+ tpoint = find_tracepoint(symbol);
+ if (!tpoint) {
+ trace_probe_log_set_index(1);
+ trace_probe_log_err(0, NO_TRACEPOINT);
+ goto parse_error;
+ }
+ ctx.funcname = kallsyms_lookup(
+ (unsigned long)tpoint->probestub,
+ NULL, NULL, NULL, sbuf);
+ } else
+ ctx.funcname = symbol;
+
/* setup a probe */
- tf = alloc_trace_fprobe(group, event, symbol, maxactive,
+ tf = alloc_trace_fprobe(group, event, symbol, tpoint, maxactive,
argc - 2, is_return);
if (IS_ERR(tf)) {
ret = PTR_ERR(tf);
@@ -1032,24 +1050,15 @@ static int __trace_fprobe_create(int argc, const char *argv[])
goto out; /* We know tf is not allocated */
}
- if (is_tracepoint) {
- tf->tpoint = find_tracepoint(tf->symbol);
- if (!tf->tpoint) {
- trace_probe_log_set_index(1);
- trace_probe_log_err(0, NO_TRACEPOINT);
- goto parse_error;
- }
+ if (is_tracepoint)
tf->mod = __module_text_address(
(unsigned long)tf->tpoint->probestub);
- }
argc -= 2; argv += 2;
-
/* parse arguments */
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
- struct traceprobe_parse_context ctx = { .flags = flags };
-
trace_probe_log_set_index(i + 2);
+ ctx.offset = 0;
ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx);
if (ret)
goto error; /* This can be -ENOMEM */