aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2017-10-30 22:06:54 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-11-01 10:44:38 -0400
commit7285cf3325b4a1dfb336d31eebc27dfbc30fb9aa (patch)
treeece6aeb203be9207ae16eb2ffb985fddc42db46d /tools/perf
parentb7b75a60b291cc699ca9bb2a8517a1b3b08bbeb1 (diff)
perf srcline: Show correct function name for srcline of callchains
When libbfd is not used, it doesn't show proper function name and reuse the original symbol of the sample. That's because it passes the original sym to inline_list__append(). As `addr2line -f` returns function names as well, use that to create an inline_sym and pass it to inline_list__append(). For example, following data shows that inlined entries of main have same name (main). Before: $ perf report -g srcline -q | head 45.22% inlining libm-2.26.so [.] __hypot_finite | ---__hypot_finite ??:0 | |--44.15%--hypot ??:0 | main complex:589 | main complex:597 | main complex:654 | main complex:664 | main inlining.cpp:14 After: $ perf report -g srcline -q | head 45.22% inlining libm-2.26.so [.] __hypot_finite | ---__hypot_finite | |--44.15%--hypot | std::__complex_abs complex:589 (inlined) | std::abs<double> complex:597 (inlined) | std::_Norm_helper<true>::_S_do_it<double> complex:654 (inlined) | std::norm<double> complex:664 (inlined) | main inlining.cpp:14 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Reviewed-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Milian Wolff <milian.wolff@kdab.com> Cc: Jin Yao <yao.jin@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20171031020654.31163-2-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/srcline.c95
1 files changed, 55 insertions, 40 deletions
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 51dc49c65476..ad1b46f1f2cf 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -10,7 +10,7 @@
10#include "util/debug.h" 10#include "util/debug.h"
11#include "util/callchain.h" 11#include "util/callchain.h"
12#include "srcline.h" 12#include "srcline.h"
13 13#include "string2.h"
14#include "symbol.h" 14#include "symbol.h"
15 15
16bool srcline_full_filename; 16bool srcline_full_filename;
@@ -77,6 +77,41 @@ static char *srcline_from_fileline(const char *file, unsigned int line)
77 return srcline; 77 return srcline;
78} 78}
79 79
80static struct symbol *new_inline_sym(struct dso *dso,
81 struct symbol *base_sym,
82 const char *funcname)
83{
84 struct symbol *inline_sym;
85 char *demangled = NULL;
86
87 if (dso) {
88 demangled = dso__demangle_sym(dso, 0, funcname);
89 if (demangled)
90 funcname = demangled;
91 }
92
93 if (base_sym && strcmp(funcname, base_sym->name) == 0) {
94 /* reuse the real, existing symbol */
95 inline_sym = base_sym;
96 /* ensure that we don't alias an inlined symbol, which could
97 * lead to double frees in inline_node__delete
98 */
99 assert(!base_sym->inlined);
100 } else {
101 /* create a fake symbol for the inline frame */
102 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
103 base_sym ? base_sym->end : 0,
104 base_sym ? base_sym->binding : 0,
105 funcname);
106 if (inline_sym)
107 inline_sym->inlined = 1;
108 }
109
110 free(demangled);
111
112 return inline_sym;
113}
114
80#ifdef HAVE_LIBBFD_SUPPORT 115#ifdef HAVE_LIBBFD_SUPPORT
81 116
82/* 117/*
@@ -219,41 +254,6 @@ static void addr2line_cleanup(struct a2l_data *a2l)
219 254
220#define MAX_INLINE_NEST 1024 255#define MAX_INLINE_NEST 1024
221 256
222static struct symbol *new_inline_sym(struct dso *dso,
223 struct symbol *base_sym,
224 const char *funcname)
225{
226 struct symbol *inline_sym;
227 char *demangled = NULL;
228
229 if (dso) {
230 demangled = dso__demangle_sym(dso, 0, funcname);
231 if (demangled)
232 funcname = demangled;
233 }
234
235 if (base_sym && strcmp(funcname, base_sym->name) == 0) {
236 /* reuse the real, existing symbol */
237 inline_sym = base_sym;
238 /* ensure that we don't alias an inlined symbol, which could
239 * lead to double frees in inline_node__delete
240 */
241 assert(!base_sym->inlined);
242 } else {
243 /* create a fake symbol for the inline frame */
244 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
245 base_sym ? base_sym->end : 0,
246 base_sym ? base_sym->binding : 0,
247 funcname);
248 if (inline_sym)
249 inline_sym->inlined = 1;
250 }
251
252 free(demangled);
253
254 return inline_sym;
255}
256
257static int inline_list__append_dso_a2l(struct dso *dso, 257static int inline_list__append_dso_a2l(struct dso *dso,
258 struct inline_node *node, 258 struct inline_node *node,
259 struct symbol *sym) 259 struct symbol *sym)
@@ -432,10 +432,11 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
432 char cmd[PATH_MAX]; 432 char cmd[PATH_MAX];
433 struct inline_node *node; 433 struct inline_node *node;
434 char *filename = NULL; 434 char *filename = NULL;
435 size_t len; 435 char *funcname = NULL;
436 size_t filelen, funclen;
436 unsigned int line_nr = 0; 437 unsigned int line_nr = 0;
437 438
438 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64, 439 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i -f %016"PRIx64,
439 dso_name, addr); 440 dso_name, addr);
440 441
441 fp = popen(cmd, "r"); 442 fp = popen(cmd, "r");
@@ -453,20 +454,34 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
453 INIT_LIST_HEAD(&node->val); 454 INIT_LIST_HEAD(&node->val);
454 node->addr = addr; 455 node->addr = addr;
455 456
456 while (getline(&filename, &len, fp) != -1) { 457 /* addr2line -f generates two lines for each inlined functions */
458 while (getline(&funcname, &funclen, fp) != -1) {
457 char *srcline; 459 char *srcline;
460 struct symbol *inline_sym;
461
462 rtrim(funcname);
463
464 if (getline(&filename, &filelen, fp) == -1)
465 goto out;
458 466
459 if (filename_split(filename, &line_nr) != 1) 467 if (filename_split(filename, &line_nr) != 1)
460 goto out; 468 goto out;
461 469
462 srcline = srcline_from_fileline(filename, line_nr); 470 srcline = srcline_from_fileline(filename, line_nr);
463 if (inline_list__append(sym, srcline, node) != 0) 471 inline_sym = new_inline_sym(dso, sym, funcname);
472
473 if (inline_list__append(inline_sym, srcline, node) != 0) {
474 free(srcline);
475 if (inline_sym && inline_sym->inlined)
476 symbol__delete(inline_sym);
464 goto out; 477 goto out;
478 }
465 } 479 }
466 480
467out: 481out:
468 pclose(fp); 482 pclose(fp);
469 free(filename); 483 free(filename);
484 free(funcname);
470 485
471 return node; 486 return node;
472} 487}