diff options
author | Stephane Eranian <eranian@google.com> | 2014-01-17 10:34:05 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-01-20 14:19:08 -0500 |
commit | 8a398897ff21f73cb8b15a19514660f032926882 (patch) | |
tree | bb08e1fcfe48e09b30ec21f67b7b7fbb5fb7f176 /tools | |
parent | 3a46817f674389d5fb2f4dce19fbc73ebd1976bb (diff) |
perf stat: fix NULL pointer reference bug with event unit
This patch fixes a problem with the handling of the newly introduced
optional event unit. The following cmdline caused a segfault:
$ perf stat -e cpu/event-0x3c/ ls
This patch fixes the problem with the default setting for alias->unit
which was eventually causing the segfault.
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1389972846-6566-2-git-send-email-eranian@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/parse-events.c | 2 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 24 | ||||
-rw-r--r-- | tools/perf/util/pmu.h | 2 |
3 files changed, 22 insertions, 6 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a7f1b6a91fdd..d248fca6d7ed 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -635,7 +635,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
635 | struct perf_event_attr attr; | 635 | struct perf_event_attr attr; |
636 | struct perf_pmu *pmu; | 636 | struct perf_pmu *pmu; |
637 | struct perf_evsel *evsel; | 637 | struct perf_evsel *evsel; |
638 | char *unit; | 638 | const char *unit; |
639 | double scale; | 639 | double scale; |
640 | 640 | ||
641 | pmu = perf_pmu__find(name); | 641 | pmu = perf_pmu__find(name); |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d9cab4d27192..b752ecb40d86 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -105,7 +105,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * | |||
105 | char scale[128]; | 105 | char scale[128]; |
106 | int fd, ret = -1; | 106 | int fd, ret = -1; |
107 | char path[PATH_MAX]; | 107 | char path[PATH_MAX]; |
108 | char *lc; | 108 | const char *lc; |
109 | 109 | ||
110 | snprintf(path, PATH_MAX, "%s/%s.scale", dir, name); | 110 | snprintf(path, PATH_MAX, "%s/%s.scale", dir, name); |
111 | 111 | ||
@@ -609,7 +609,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, | |||
609 | 609 | ||
610 | 610 | ||
611 | static int check_unit_scale(struct perf_pmu_alias *alias, | 611 | static int check_unit_scale(struct perf_pmu_alias *alias, |
612 | char **unit, double *scale) | 612 | const char **unit, double *scale) |
613 | { | 613 | { |
614 | /* | 614 | /* |
615 | * Only one term in event definition can | 615 | * Only one term in event definition can |
@@ -634,14 +634,18 @@ static int check_unit_scale(struct perf_pmu_alias *alias, | |||
634 | * defined for the alias | 634 | * defined for the alias |
635 | */ | 635 | */ |
636 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, | 636 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
637 | char **unit, double *scale) | 637 | const char **unit, double *scale) |
638 | { | 638 | { |
639 | struct parse_events_term *term, *h; | 639 | struct parse_events_term *term, *h; |
640 | struct perf_pmu_alias *alias; | 640 | struct perf_pmu_alias *alias; |
641 | int ret; | 641 | int ret; |
642 | 642 | ||
643 | /* | ||
644 | * Mark unit and scale as not set | ||
645 | * (different from default values, see below) | ||
646 | */ | ||
643 | *unit = NULL; | 647 | *unit = NULL; |
644 | *scale = 0; | 648 | *scale = 0.0; |
645 | 649 | ||
646 | list_for_each_entry_safe(term, h, head_terms, list) { | 650 | list_for_each_entry_safe(term, h, head_terms, list) { |
647 | alias = pmu_find_alias(pmu, term); | 651 | alias = pmu_find_alias(pmu, term); |
@@ -658,6 +662,18 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, | |||
658 | list_del(&term->list); | 662 | list_del(&term->list); |
659 | free(term); | 663 | free(term); |
660 | } | 664 | } |
665 | |||
666 | /* | ||
667 | * if no unit or scale foundin aliases, then | ||
668 | * set defaults as for evsel | ||
669 | * unit cannot left to NULL | ||
670 | */ | ||
671 | if (*unit == NULL) | ||
672 | *unit = ""; | ||
673 | |||
674 | if (*scale == 0.0) | ||
675 | *scale = 1.0; | ||
676 | |||
661 | return 0; | 677 | return 0; |
662 | } | 678 | } |
663 | 679 | ||
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 9183380e2038..8b64125a9281 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h | |||
@@ -29,7 +29,7 @@ int perf_pmu__config_terms(struct list_head *formats, | |||
29 | struct perf_event_attr *attr, | 29 | struct perf_event_attr *attr, |
30 | struct list_head *head_terms); | 30 | struct list_head *head_terms); |
31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, | 31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
32 | char **unit, double *scale); | 32 | const char **unit, double *scale); |
33 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, | 33 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, |
34 | struct list_head *head_terms); | 34 | struct list_head *head_terms); |
35 | int perf_pmu_wrap(void); | 35 | int perf_pmu_wrap(void); |