perf probe: Support tracing an entry of array
Add array-entry tracing support to perf probe. This enables to trace an entry of array which is indexed by constant value, e.g. array[0]. For example: $ perf probe -a 'bio_split bi->bi_io_vec[0]' Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20100519195742.2885.5344.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
73317b9540
commit
b2a3c12b74
@@ -557,7 +557,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
|
||||
/* Parse perf-probe event argument */
|
||||
static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
|
||||
{
|
||||
char *tmp;
|
||||
char *tmp, *goodname;
|
||||
struct perf_probe_arg_field **fieldp;
|
||||
|
||||
pr_debug("parsing arg: %s into ", str);
|
||||
@@ -580,7 +580,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
|
||||
pr_debug("type:%s ", arg->type);
|
||||
}
|
||||
|
||||
tmp = strpbrk(str, "-.");
|
||||
tmp = strpbrk(str, "-.[");
|
||||
if (!is_c_varname(str) || !tmp) {
|
||||
/* A variable, register, symbol or special value */
|
||||
arg->var = strdup(str);
|
||||
@@ -590,10 +590,11 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Structure fields */
|
||||
/* Structure fields or array element */
|
||||
arg->var = strndup(str, tmp - str);
|
||||
if (arg->var == NULL)
|
||||
return -ENOMEM;
|
||||
goodname = arg->var;
|
||||
pr_debug("%s, ", arg->var);
|
||||
fieldp = &arg->field;
|
||||
|
||||
@@ -601,22 +602,38 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
|
||||
*fieldp = zalloc(sizeof(struct perf_probe_arg_field));
|
||||
if (*fieldp == NULL)
|
||||
return -ENOMEM;
|
||||
if (*tmp == '.') {
|
||||
str = tmp + 1;
|
||||
(*fieldp)->ref = false;
|
||||
} else if (tmp[1] == '>') {
|
||||
str = tmp + 2;
|
||||
if (*tmp == '[') { /* Array */
|
||||
str = tmp;
|
||||
(*fieldp)->index = strtol(str + 1, &tmp, 0);
|
||||
(*fieldp)->ref = true;
|
||||
} else {
|
||||
semantic_error("Argument parse error: %s\n", str);
|
||||
return -EINVAL;
|
||||
if (*tmp != ']' || tmp == str + 1) {
|
||||
semantic_error("Array index must be a"
|
||||
" number.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
tmp++;
|
||||
if (*tmp == '\0')
|
||||
tmp = NULL;
|
||||
} else { /* Structure */
|
||||
if (*tmp == '.') {
|
||||
str = tmp + 1;
|
||||
(*fieldp)->ref = false;
|
||||
} else if (tmp[1] == '>') {
|
||||
str = tmp + 2;
|
||||
(*fieldp)->ref = true;
|
||||
} else {
|
||||
semantic_error("Argument parse error: %s\n",
|
||||
str);
|
||||
return -EINVAL;
|
||||
}
|
||||
tmp = strpbrk(str, "-.[");
|
||||
}
|
||||
|
||||
tmp = strpbrk(str, "-.");
|
||||
if (tmp) {
|
||||
(*fieldp)->name = strndup(str, tmp - str);
|
||||
if ((*fieldp)->name == NULL)
|
||||
return -ENOMEM;
|
||||
if (*str != '[')
|
||||
goodname = (*fieldp)->name;
|
||||
pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
|
||||
fieldp = &(*fieldp)->next;
|
||||
}
|
||||
@@ -624,11 +641,13 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
|
||||
(*fieldp)->name = strdup(str);
|
||||
if ((*fieldp)->name == NULL)
|
||||
return -ENOMEM;
|
||||
if (*str != '[')
|
||||
goodname = (*fieldp)->name;
|
||||
pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
|
||||
|
||||
/* If no name is specified, set the last field name */
|
||||
/* If no name is specified, set the last field name (not array index)*/
|
||||
if (!arg->name) {
|
||||
arg->name = strdup((*fieldp)->name);
|
||||
arg->name = strdup(goodname);
|
||||
if (arg->name == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -776,8 +795,11 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
|
||||
len -= ret;
|
||||
|
||||
while (field) {
|
||||
ret = e_snprintf(tmp, len, "%s%s", field->ref ? "->" : ".",
|
||||
field->name);
|
||||
if (field->name[0] == '[')
|
||||
ret = e_snprintf(tmp, len, "%s", field->name);
|
||||
else
|
||||
ret = e_snprintf(tmp, len, "%s%s",
|
||||
field->ref ? "->" : ".", field->name);
|
||||
if (ret <= 0)
|
||||
goto error;
|
||||
tmp += ret;
|
||||
|
Reference in New Issue
Block a user