aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
authorChris Phlipot <cphlipot0@gmail.com>2016-04-19 22:32:11 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-04-25 11:49:17 -0400
commite557b674a9470dae99916be6105e6780b3a072ca (patch)
treed9d6aebb5812a33de9db375c6aeb0cd3ff2b6ccc /tools/perf/builtin-script.c
parent0c3a6ef4ea54a179328734a45b7f7698e44ad805 (diff)
perf script: Fix segfault when printing callchains
This fixes a bug caused by an unitialized callchain cursor. The crash frist appeared in: 6f736735e30f ("perf evsel: Require that callchains be resolved before calling fprintf_{sym,callchain}") The callchain cursor is a struct that contains pointers, that when uninitialized will cause unpredictable behavior (usually a crash) when trying to append to the callchain. The existing implementation has the following issues: 1. The callchain cursor used is not initialized, resulting in unpredictable behavior when used. 2. The cursor is declared on the stack. Even if it is properly initalized, the implmentation will leak memory when the function returns, since all the references to the callchain_nodes allocated by callchain_cursor_append will be lost when the cursor goes out of scope. 3. Storing the cursor on the stack is inefficient. Even if memory is properly freed when it goes out of scope, a performance penalty will be incurred due to reallocation of callchain nodes. callchain_cursor_append is designed to avoid these reallocations when an existing cursor is reused. This patch fixes the crash by replacing cursor_callchain with a reference to the global callchain_cursor which also resolves all 3 issues mentioned above. How to reproduce the crash: $ perf record --call-graph=dwarf stress -t 1 -c 1 $ perf script > /dev/null Segfault Signed-off-by: Chris Phlipot <cphlipot0@gmail.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Fixes: 6f736735e30f ("perf evsel: Require that callchains be resolved before calling fprintf_{sym,callchain}") Link: http://lkml.kernel.org/r/1461119531-2529-1-git-send-email-cphlipot0@gmail.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 5099740aa50b..f43b0c6f88f4 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -570,12 +570,12 @@ static void print_sample_bts(struct perf_sample *sample,
570 /* print branch_from information */ 570 /* print branch_from information */
571 if (PRINT_FIELD(IP)) { 571 if (PRINT_FIELD(IP)) {
572 unsigned int print_opts = output[attr->type].print_ip_opts; 572 unsigned int print_opts = output[attr->type].print_ip_opts;
573 struct callchain_cursor *cursor = NULL, cursor_callchain; 573 struct callchain_cursor *cursor = NULL;
574 574
575 if (symbol_conf.use_callchain && sample->callchain && 575 if (symbol_conf.use_callchain && sample->callchain &&
576 thread__resolve_callchain(al->thread, &cursor_callchain, evsel, 576 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
577 sample, NULL, NULL, scripting_max_stack) == 0) 577 sample, NULL, NULL, scripting_max_stack) == 0)
578 cursor = &cursor_callchain; 578 cursor = &callchain_cursor;
579 579
580 if (cursor == NULL) { 580 if (cursor == NULL) {
581 putchar(' '); 581 putchar(' ');
@@ -789,12 +789,12 @@ static void process_event(struct perf_script *script,
789 printf("%16" PRIu64, sample->weight); 789 printf("%16" PRIu64, sample->weight);
790 790
791 if (PRINT_FIELD(IP)) { 791 if (PRINT_FIELD(IP)) {
792 struct callchain_cursor *cursor = NULL, cursor_callchain; 792 struct callchain_cursor *cursor = NULL;
793 793
794 if (symbol_conf.use_callchain && sample->callchain && 794 if (symbol_conf.use_callchain && sample->callchain &&
795 thread__resolve_callchain(al->thread, &cursor_callchain, evsel, 795 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
796 sample, NULL, NULL, scripting_max_stack) == 0) 796 sample, NULL, NULL, scripting_max_stack) == 0)
797 cursor = &cursor_callchain; 797 cursor = &callchain_cursor;
798 798
799 putchar(cursor ? '\n' : ' '); 799 putchar(cursor ? '\n' : ' ');
800 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); 800 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);