perf probe: Support argument name
Set given names to event arguments. The syntax is same as kprobe-tracer,
you can add 'NAME=' right before each argument.
e.g.
./perf probe vfs_read foo=file
then, 'foo' is set to the argument name as below.
./perf probe -l
probe:vfs_read (on vfs_read@linux-2.6-tip/fs/read_write.c with foo)
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100412171653.3790.74624.stgit@localhost6.localdomain6>
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3fc0be7..ab6f53d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -437,22 +437,28 @@
/* Parse perf-probe event argument */
static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg)
{
- const char *tmp;
+ char *tmp;
struct perf_probe_arg_field **fieldp;
pr_debug("parsing arg: %s into ", str);
+ tmp = strchr(str, '=');
+ if (tmp) {
+ arg->name = xstrndup(str, tmp - str);
+ str = tmp + 1;
+ }
+
tmp = strpbrk(str, "-.");
if (!is_c_varname(str) || !tmp) {
/* A variable, register, symbol or special value */
- arg->name = xstrdup(str);
- pr_debug("%s\n", arg->name);
+ arg->var = xstrdup(str);
+ pr_debug("%s\n", arg->var);
return;
}
/* Structure fields */
- arg->name = xstrndup(str, tmp - str);
- pr_debug("%s, ", arg->name);
+ arg->var = xstrndup(str, tmp - str);
+ pr_debug("%s, ", arg->var);
fieldp = &arg->field;
do {
@@ -497,7 +503,7 @@
pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs);
for (i = 0; i < pev->nargs; i++) {
parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
- if (is_c_varname(pev->args[i].name) && pev->point.retprobe)
+ if (is_c_varname(pev->args[i].var) && pev->point.retprobe)
semantic_error("You can't specify local variable for"
" kretprobe");
}
@@ -514,7 +520,7 @@
return true;
for (i = 0; i < pev->nargs; i++)
- if (is_c_varname(pev->args[i].name))
+ if (is_c_varname(pev->args[i].var))
return true;
return false;
@@ -575,7 +581,10 @@
int ret;
char *tmp = buf;
- ret = e_snprintf(tmp, len, "%s", pa->name);
+ if (pa->name && pa->var)
+ ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
+ else
+ ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
if (ret <= 0)
goto error;
tmp += ret;
@@ -803,6 +812,8 @@
for (i = 0; i < pev->nargs; i++) {
if (pev->args[i].name)
free(pev->args[i].name);
+ if (pev->args[i].var)
+ free(pev->args[i].var);
field = pev->args[i].field;
while (field) {
next = field->next;
@@ -1117,8 +1128,11 @@
if (tev->nargs) {
tev->args = xzalloc(sizeof(struct kprobe_trace_arg)
* tev->nargs);
- for (i = 0; i < tev->nargs; i++)
- tev->args[i].value = xstrdup(pev->args[i].name);
+ for (i = 0; i < tev->nargs; i++) {
+ if (pev->args[i].name)
+ tev->args[i].name = xstrdup(pev->args[i].name);
+ tev->args[i].value = xstrdup(pev->args[i].var);
+ }
}
/* Currently just checking function name from symbol map */