aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung.kim@lge.com>2013-04-01 07:35:17 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-05-28 09:23:52 -0400
commit26353a61b977e57b58dd3555bc0422fea46c5ad6 (patch)
treec6fe9a8d16effc5284ff44c1be0879e7adb8ad41 /tools
parent6956664a5c4c32d5aa48fe96d5e2421a3e3f72d5 (diff)
perf hists: Fix an invalid memory free on he->branch_info
The branch info was allocated for the whole stack and passed matching hist entry for each level during processing samples. Thus when a hist entry tries to free its branch info like in hists__collapse_insert_entry it'll face following error. *** glibc detected *** perf: munmap_chunk(): invalid pointer: 0x00000000014e9d20 *** ======= Backtrace: ========= /lib64/libc.so.6[0x387d47ae16] perf[0x4923bd] perf(cmd_report+0xd68)[0x432a08] perf[0x41a663] perf(main+0x58f)[0x419eaf] /lib64/libc.so.6(__libc_start_main+0xf5)[0x387d421735] perf[0x419f95] Fix it by allocating and copying branch info for each new hist entry. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Andi Kleen <andi@firstfloor.org> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1364816125-12212-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-report.c9
-rw-r--r--tools/perf/util/hist.c14
2 files changed, 20 insertions, 3 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index bd0ca81eeaca..d9f2de3e81fe 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -187,6 +187,9 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
187 for (i = 0; i < sample->branch_stack->nr; i++) { 187 for (i = 0; i < sample->branch_stack->nr; i++) {
188 if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym)) 188 if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym))
189 continue; 189 continue;
190
191 err = -ENOMEM;
192
190 /* 193 /*
191 * The report shows the percentage of total branches captured 194 * The report shows the percentage of total branches captured
192 * and not events sampled. Thus we use a pseudo period of 1. 195 * and not events sampled. Thus we use a pseudo period of 1.
@@ -195,7 +198,6 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
195 &bi[i], 1, 1); 198 &bi[i], 1, 1);
196 if (he) { 199 if (he) {
197 struct annotation *notes; 200 struct annotation *notes;
198 err = -ENOMEM;
199 bx = he->branch_info; 201 bx = he->branch_info;
200 if (bx->from.sym && use_browser == 1 && sort__has_sym) { 202 if (bx->from.sym && use_browser == 1 && sort__has_sym) {
201 notes = symbol__annotation(bx->from.sym); 203 notes = symbol__annotation(bx->from.sym);
@@ -226,11 +228,12 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
226 } 228 }
227 evsel->hists.stats.total_period += 1; 229 evsel->hists.stats.total_period += 1;
228 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 230 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
229 err = 0;
230 } else 231 } else
231 return -ENOMEM; 232 goto out;
232 } 233 }
234 err = 0;
233out: 235out:
236 free(bi);
234 return err; 237 return err;
235} 238}
236 239
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6b32721f829a..9438d576459d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -292,6 +292,20 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
292 he->ms.map->referenced = true; 292 he->ms.map->referenced = true;
293 293
294 if (he->branch_info) { 294 if (he->branch_info) {
295 /*
296 * This branch info is (a part of) allocated from
297 * machine__resolve_bstack() and will be freed after
298 * adding new entries. So we need to save a copy.
299 */
300 he->branch_info = malloc(sizeof(*he->branch_info));
301 if (he->branch_info == NULL) {
302 free(he);
303 return NULL;
304 }
305
306 memcpy(he->branch_info, template->branch_info,
307 sizeof(*he->branch_info));
308
295 if (he->branch_info->from.map) 309 if (he->branch_info->from.map)
296 he->branch_info->from.map->referenced = true; 310 he->branch_info->from.map->referenced = true;
297 if (he->branch_info->to.map) 311 if (he->branch_info->to.map)