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>
This commit is contained in:
parent
3a46817f67
commit
8a398897ff
|
@ -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 *
|
||||||
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,
|
||||||
|
|
||||||
|
|
||||||
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,
|
||||||
* 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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue