diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-05-19 15:57:42 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-07-05 17:50:27 -0400 |
commit | b2a3c12b7442247c440f7083d48ef05716753ec1 (patch) | |
tree | c3a3d0bb442e285979b0dbeecfbf0c04a8b3743e /tools/perf/util/probe-event.c | |
parent | 73317b954041031249e8968d2e9023ff4e960d99 (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.c | 56 |
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 */ |
558 | static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) | 558 | static 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; |