aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-05-19 15:57:42 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-07-05 17:50:27 -0400
commitb2a3c12b7442247c440f7083d48ef05716753ec1 (patch)
treec3a3d0bb442e285979b0dbeecfbf0c04a8b3743e /tools/perf/util/probe-event.c
parent73317b954041031249e8968d2e9023ff4e960d99 (diff)
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>
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 914c67095d96..351baa9a3695 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -557,7 +557,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
557/* Parse perf-probe event argument */ 557/* Parse perf-probe event argument */
558static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 558static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
559{ 559{
560 char *tmp; 560 char *tmp, *goodname;
561 struct perf_probe_arg_field **fieldp; 561 struct perf_probe_arg_field **fieldp;
562 562
563 pr_debug("parsing arg: %s into ", str); 563 pr_debug("parsing arg: %s into ", str);
@@ -580,7 +580,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
580 pr_debug("type:%s ", arg->type); 580 pr_debug("type:%s ", arg->type);
581 } 581 }
582 582
583 tmp = strpbrk(str, "-."); 583 tmp = strpbrk(str, "-.[");
584 if (!is_c_varname(str) || !tmp) { 584 if (!is_c_varname(str) || !tmp) {
585 /* A variable, register, symbol or special value */ 585 /* A variable, register, symbol or special value */
586 arg->var = strdup(str); 586 arg->var = strdup(str);
@@ -590,10 +590,11 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
590 return 0; 590 return 0;
591 } 591 }
592 592
593 /* Structure fields */ 593 /* Structure fields or array element */
594 arg->var = strndup(str, tmp - str); 594 arg->var = strndup(str, tmp - str);
595 if (arg->var == NULL) 595 if (arg->var == NULL)
596 return -ENOMEM; 596 return -ENOMEM;
597 goodname = arg->var;
597 pr_debug("%s, ", arg->var); 598 pr_debug("%s, ", arg->var);
598 fieldp = &arg->field; 599 fieldp = &arg->field;
599 600
@@ -601,22 +602,38 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
601 *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 602 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
602 if (*fieldp == NULL) 603 if (*fieldp == NULL)
603 return -ENOMEM; 604 return -ENOMEM;
604 if (*tmp == '.') { 605 if (*tmp == '[') { /* Array */
605 str = tmp + 1; 606 str = tmp;
606 (*fieldp)->ref = false; 607 (*fieldp)->index = strtol(str + 1, &tmp, 0);
607 } else if (tmp[1] == '>') {
608 str = tmp + 2;
609 (*fieldp)->ref = true; 608 (*fieldp)->ref = true;
610 } else { 609 if (*tmp != ']' || tmp == str + 1) {
611 semantic_error("Argument parse error: %s\n", str); 610 semantic_error("Array index must be a"
612 return -EINVAL; 611 " number.\n");
612 return -EINVAL;
613 }
614 tmp++;
615 if (*tmp == '\0')
616 tmp = NULL;
617 } else { /* Structure */
618 if (*tmp == '.') {
619 str = tmp + 1;
620 (*fieldp)->ref = false;
621 } else if (tmp[1] == '>') {
622 str = tmp + 2;
623 (*fieldp)->ref = true;
624 } else {
625 semantic_error("Argument parse error: %s\n",
626 str);
627 return -EINVAL;
628 }
629 tmp = strpbrk(str, "-.[");
613 } 630 }
614
615 tmp = strpbrk(str, "-.");
616 if (tmp) { 631 if (tmp) {
617 (*fieldp)->name = strndup(str, tmp - str); 632 (*fieldp)->name = strndup(str, tmp - str);
618 if ((*fieldp)->name == NULL) 633 if ((*fieldp)->name == NULL)
619 return -ENOMEM; 634 return -ENOMEM;
635 if (*str != '[')
636 goodname = (*fieldp)->name;
620 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 637 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
621 fieldp = &(*fieldp)->next; 638 fieldp = &(*fieldp)->next;
622 } 639 }
@@ -624,11 +641,13 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
624 (*fieldp)->name = strdup(str); 641 (*fieldp)->name = strdup(str);
625 if ((*fieldp)->name == NULL) 642 if ((*fieldp)->name == NULL)
626 return -ENOMEM; 643 return -ENOMEM;
644 if (*str != '[')
645 goodname = (*fieldp)->name;
627 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 646 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
628 647
629 /* If no name is specified, set the last field name */ 648 /* If no name is specified, set the last field name (not array index)*/
630 if (!arg->name) { 649 if (!arg->name) {
631 arg->name = strdup((*fieldp)->name); 650 arg->name = strdup(goodname);
632 if (arg->name == NULL) 651 if (arg->name == NULL)
633 return -ENOMEM; 652 return -ENOMEM;
634 } 653 }
@@ -776,8 +795,11 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
776 len -= ret; 795 len -= ret;
777 796
778 while (field) { 797 while (field) {
779 ret = e_snprintf(tmp, len, "%s%s", field->ref ? "->" : ".", 798 if (field->name[0] == '[')
780 field->name); 799 ret = e_snprintf(tmp, len, "%s", field->name);
800 else
801 ret = e_snprintf(tmp, len, "%s%s",
802 field->ref ? "->" : ".", field->name);
781 if (ret <= 0) 803 if (ret <= 0)
782 goto error; 804 goto error;
783 tmp += ret; 805 tmp += ret;