Commit 8a398897 authored by Stephane Eranian's avatar Stephane Eranian Committed by Arnaldo Carvalho de Melo

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: default avatarStephane 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 3a46817f
...@@ -635,7 +635,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx, ...@@ -635,7 +635,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
struct perf_event_attr attr; struct perf_event_attr attr;
struct perf_pmu *pmu; struct perf_pmu *pmu;
struct perf_evsel *evsel; struct perf_evsel *evsel;
char *unit; const char *unit;
double scale; double scale;
pmu = perf_pmu__find(name); pmu = perf_pmu__find(name);
......
...@@ -105,7 +105,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * ...@@ -105,7 +105,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
char scale[128]; char scale[128];
int fd, ret = -1; int fd, ret = -1;
char path[PATH_MAX]; char path[PATH_MAX];
char *lc; const char *lc;
snprintf(path, PATH_MAX, "%s/%s.scale", dir, name); snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
...@@ -609,7 +609,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, ...@@ -609,7 +609,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
static int check_unit_scale(struct perf_pmu_alias *alias, static int check_unit_scale(struct perf_pmu_alias *alias,
char **unit, double *scale) const char **unit, double *scale)
{ {
/* /*
* Only one term in event definition can * Only one term in event definition can
...@@ -634,14 +634,18 @@ static int check_unit_scale(struct perf_pmu_alias *alias, ...@@ -634,14 +634,18 @@ static int check_unit_scale(struct perf_pmu_alias *alias,
* defined for the alias * defined for the alias
*/ */
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
char **unit, double *scale) const char **unit, double *scale)
{ {
struct parse_events_term *term, *h; struct parse_events_term *term, *h;
struct perf_pmu_alias *alias; struct perf_pmu_alias *alias;
int ret; int ret;
/*
* Mark unit and scale as not set
* (different from default values, see below)
*/
*unit = NULL; *unit = NULL;
*scale = 0; *scale = 0.0;
list_for_each_entry_safe(term, h, head_terms, list) { list_for_each_entry_safe(term, h, head_terms, list) {
alias = pmu_find_alias(pmu, term); 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,6 +662,18 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
list_del(&term->list); list_del(&term->list);
free(term); free(term);
} }
/*
* if no unit or scale foundin aliases, then
* set defaults as for evsel
* unit cannot left to NULL
*/
if (*unit == NULL)
*unit = "";
if (*scale == 0.0)
*scale = 1.0;
return 0; return 0;
} }
......
...@@ -29,7 +29,7 @@ int perf_pmu__config_terms(struct list_head *formats, ...@@ -29,7 +29,7 @@ int perf_pmu__config_terms(struct list_head *formats,
struct perf_event_attr *attr, struct perf_event_attr *attr,
struct list_head *head_terms); struct list_head *head_terms);
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
char **unit, double *scale); const char **unit, double *scale);
struct list_head *perf_pmu__alias(struct perf_pmu *pmu, struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
struct list_head *head_terms); struct list_head *head_terms);
int perf_pmu_wrap(void); int perf_pmu_wrap(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment