diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-04-12 13:16:53 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-04-14 17:26:04 -0300 |
commit | 48481938b02471d505296d7557ed296eb093d496 (patch) | |
tree | 7549d861d76621d1e3d2ddd75eae4575901f1fd0 /tools/perf/util | |
parent | fcd1498405c2c88ac632e7c3c3fce3213d9196db (diff) |
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>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/probe-event.c | 34 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 27 |
3 files changed, 41 insertions, 21 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 3fc0be741b8..ab6f53deaba 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -437,22 +437,28 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) /* 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 @@ void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 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 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 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 synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 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 @@ void clear_perf_probe_event(struct perf_probe_event *pev) 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 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, 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 */ diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 9d99fc24c4f..10411f59632 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -55,6 +55,7 @@ struct perf_probe_arg_field { /* Perf probe probing argument */ struct perf_probe_arg { char *name; /* Argument name */ + char *var; /* Variable name */ struct perf_probe_arg_field *field; /* Structure fields */ }; diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index a8513772df0..105e95c95ee 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -484,35 +484,40 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) convert_location(expr, pf); if (pf->pvar->field) - convert_variable_fields(vr_die, pf->pvar->name, + convert_variable_fields(vr_die, pf->pvar->var, pf->pvar->field, &pf->tvar->ref); /* *expr will be cached in libdw. Don't free it. */ return ; error: /* TODO: Support const_value */ die("Failed to find the location of %s at this address.\n" - " Perhaps, it has been optimized out.", pf->pvar->name); + " Perhaps, it has been optimized out.", pf->pvar->var); } /* Find a variable in a subprogram die */ static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die vr_die; - char buf[128]; + char buf[32]; - /* TODO: Support struct members and arrays */ - if (!is_c_varname(pf->pvar->name)) { + /* TODO: Support arrays */ + if (pf->pvar->name) + pf->tvar->name = xstrdup(pf->pvar->name); + else { + synthesize_perf_probe_arg(pf->pvar, buf, 32); + pf->tvar->name = xstrdup(buf); + } + + if (!is_c_varname(pf->pvar->var)) { /* Copy raw parameters */ - pf->tvar->value = xstrdup(pf->pvar->name); + pf->tvar->value = xstrdup(pf->pvar->var); } else { - synthesize_perf_probe_arg(pf->pvar, buf, 128); - pf->tvar->name = xstrdup(buf); pr_debug("Searching '%s' variable in context.\n", - pf->pvar->name); + pf->pvar->var); /* Search child die for local variables and parameters. */ - if (!die_find_variable(sp_die, pf->pvar->name, &vr_die)) + if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) die("Failed to find '%s' in this function.", - pf->pvar->name); + pf->pvar->var); convert_variable(&vr_die, pf); } } |