Skip to content

Commit

Permalink
perf probe: Support basic type casting
Browse files Browse the repository at this point in the history
Add basic type casting for arguments to perf probe. This allows
users to specify the actual type of arguments. Of course, if
user sets invalid types, kprobe-tracer rejects that.

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: <20100412171722.3790.50372.stgit@localhost6.localdomain6>
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Masami Hiramatsu authored and Arnaldo Carvalho de Melo committed Apr 14, 2010
1 parent 4984912 commit 11a1ca3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 4 deletions.
3 changes: 2 additions & 1 deletion tools/perf/Documentation/perf-probe.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ PROBE ARGUMENT
--------------
Each probe argument follows below syntax.

[NAME=]LOCALVAR|$retval|%REG|@SYMBOL
[NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]

'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo.

LINE SYNTAX
-----------
Expand Down
23 changes: 22 additions & 1 deletion tools/perf/util/probe-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ 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)
static void parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
{
char *tmp;
struct perf_probe_arg_field **fieldp;
Expand All @@ -445,9 +445,17 @@ static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg)
tmp = strchr(str, '=');
if (tmp) {
arg->name = xstrndup(str, tmp - str);
pr_debug("name:%s ", arg->name);
str = tmp + 1;
}

tmp = strchr(str, ':');
if (tmp) { /* Type setting */
*tmp = '\0';
arg->type = xstrdup(tmp + 1);
pr_debug("type:%s ", arg->type);
}

tmp = strpbrk(str, "-.");
if (!is_c_varname(str) || !tmp) {
/* A variable, register, symbol or special value */
Expand Down Expand Up @@ -603,6 +611,15 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
len -= ret;
field = field->next;
}

if (pa->type) {
ret = e_snprintf(tmp, len, ":%s", pa->type);
if (ret <= 0)
goto error;
tmp += ret;
len -= ret;
}

return tmp - buf;
error:
die("Failed to synthesize perf probe argument: %s", strerror(-ret));
Expand Down Expand Up @@ -825,6 +842,8 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
free(pev->args[i].name);
if (pev->args[i].var)
free(pev->args[i].var);
if (pev->args[i].type)
free(pev->args[i].type);
field = pev->args[i].field;
while (field) {
next = field->next;
Expand Down Expand Up @@ -1145,6 +1164,8 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
if (pev->args[i].name)
tev->args[i].name = xstrdup(pev->args[i].name);
tev->args[i].value = xstrdup(pev->args[i].var);
if (pev->args[i].type)
tev->args[i].type = xstrdup(pev->args[i].type);
}
}

Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/probe-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct perf_probe_arg_field {
struct perf_probe_arg {
char *name; /* Argument name */
char *var; /* Variable name */
char *type; /* Type name */
struct perf_probe_arg_field *field; /* Structure fields */
};

Expand Down
10 changes: 8 additions & 2 deletions tools/perf/util/probe-finder.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,10 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
&die_mem);
vr_die = &die_mem;
}
convert_variable_type(vr_die, pf->tvar);
if (pf->pvar->type)
pf->tvar->type = xstrdup(pf->pvar->type);
else
convert_variable_type(vr_die, pf->tvar);
/* *expr will be cached in libdw. Don't free it. */
return ;
error:
Expand All @@ -560,13 +563,16 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
{
Dwarf_Die vr_die;
char buf[32];
char buf[32], *ptr;

/* TODO: Support arrays */
if (pf->pvar->name)
pf->tvar->name = xstrdup(pf->pvar->name);
else {
synthesize_perf_probe_arg(pf->pvar, buf, 32);
ptr = strchr(buf, ':'); /* Change type separator to _ */
if (ptr)
*ptr = '_';
pf->tvar->name = xstrdup(buf);
}

Expand Down

0 comments on commit 11a1ca3

Please sign in to comment.