From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org, Jin Yao <yao.jin@linux.intel.com>,
Andi Kleen <ak@linux.intel.com>, Jiri Olsa <jolsa@kernel.org>,
Kan Liang <kan.liang@intel.com>,
Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 08/20] perf report: Find the inline stack for a given address
Date: Mon, 27 Mar 2017 22:39:03 -0300 [thread overview]
Message-ID: <20170328013915.15236-9-acme@kernel.org> (raw)
In-Reply-To: <20170328013915.15236-1-acme@kernel.org>
From: Jin Yao <yao.jin@linux.intel.com>
It would be useful for perf to support a mode to query the inline stack
for a given callgraph address. This would simplify finding the right
code in code that does a lot of inlining.
The srcline.c has contained the code which supports to translate the
address to filename:line_nr. This patch just extends the function to let
it support getting the inline stacks.
It introduces the inline_list which will store the inline function
result (filename:line_nr and funcname).
If BFD lib is not supported, the result is only filename:line_nr.
Signed-off-by: Yao Jin <yao.jin@linux.intel.com>
Tested-by: Milian Wolff <milian.wolff@kdab.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@intel.com>
Link: http://lkml.kernel.org/r/1490474069-15823-3-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/srcline.c | 167 +++++++++++++++++++++++++++++++++++++--
tools/perf/util/symbol-elf.c | 5 ++
tools/perf/util/symbol-minimal.c | 7 ++
tools/perf/util/symbol.h | 2 +
tools/perf/util/util.h | 16 ++++
5 files changed, 192 insertions(+), 5 deletions(-)
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 2953c9fecb30..3ce28f702b36 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -7,6 +7,7 @@
#include "util/dso.h"
#include "util/util.h"
#include "util/debug.h"
+#include "util/callchain.h"
#include "symbol.h"
@@ -30,6 +31,34 @@ static const char *dso__name(struct dso *dso)
return dso_name;
}
+static int inline_list__append(char *filename, char *funcname, int line_nr,
+ struct inline_node *node, struct dso *dso)
+{
+ struct inline_list *ilist;
+ char *demangled;
+
+ ilist = zalloc(sizeof(*ilist));
+ if (ilist == NULL)
+ return -1;
+
+ ilist->filename = filename;
+ ilist->line_nr = line_nr;
+
+ if (dso != NULL) {
+ demangled = dso__demangle_sym(dso, 0, funcname);
+ if (demangled == NULL) {
+ ilist->funcname = funcname;
+ } else {
+ ilist->funcname = demangled;
+ free(funcname);
+ }
+ }
+
+ list_add_tail(&ilist->list, &node->val);
+
+ return 0;
+}
+
#ifdef HAVE_LIBBFD_SUPPORT
/*
@@ -169,9 +198,17 @@ static void addr2line_cleanup(struct a2l_data *a2l)
#define MAX_INLINE_NEST 1024
+static void inline_list__reverse(struct inline_node *node)
+{
+ struct inline_list *ilist, *n;
+
+ list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
+ list_move_tail(&ilist->list, &node->val);
+}
+
static int addr2line(const char *dso_name, u64 addr,
char **file, unsigned int *line, struct dso *dso,
- bool unwind_inlines)
+ bool unwind_inlines, struct inline_node *node)
{
int ret = 0;
struct a2l_data *a2l = dso->a2l;
@@ -196,8 +233,21 @@ static int addr2line(const char *dso_name, u64 addr,
while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
&a2l->funcname, &a2l->line) &&
- cnt++ < MAX_INLINE_NEST)
- ;
+ cnt++ < MAX_INLINE_NEST) {
+
+ if (node != NULL) {
+ if (inline_list__append(strdup(a2l->filename),
+ strdup(a2l->funcname),
+ a2l->line, node,
+ dso) != 0)
+ return 0;
+ }
+ }
+
+ if ((node != NULL) &&
+ (callchain_param.order != ORDER_CALLEE)) {
+ inline_list__reverse(node);
+ }
}
if (a2l->found && a2l->filename) {
@@ -223,6 +273,35 @@ void dso__free_a2l(struct dso *dso)
dso->a2l = NULL;
}
+static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
+ struct dso *dso)
+{
+ char *file = NULL;
+ unsigned int line = 0;
+ struct inline_node *node;
+
+ node = zalloc(sizeof(*node));
+ if (node == NULL) {
+ perror("not enough memory for the inline node");
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&node->val);
+ node->addr = addr;
+
+ if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
+ goto out_free_inline_node;
+
+ if (list_empty(&node->val))
+ goto out_free_inline_node;
+
+ return node;
+
+out_free_inline_node:
+ inline_node__delete(node);
+ return NULL;
+}
+
#else /* HAVE_LIBBFD_SUPPORT */
static int filename_split(char *filename, unsigned int *line_nr)
@@ -249,7 +328,8 @@ static int filename_split(char *filename, unsigned int *line_nr)
static int addr2line(const char *dso_name, u64 addr,
char **file, unsigned int *line_nr,
struct dso *dso __maybe_unused,
- bool unwind_inlines __maybe_unused)
+ bool unwind_inlines __maybe_unused,
+ struct inline_node *node __maybe_unused)
{
FILE *fp;
char cmd[PATH_MAX];
@@ -288,6 +368,58 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
{
}
+static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
+ struct dso *dso __maybe_unused)
+{
+ FILE *fp;
+ char cmd[PATH_MAX];
+ struct inline_node *node;
+ char *filename = NULL;
+ size_t len;
+ unsigned int line_nr = 0;
+
+ scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
+ dso_name, addr);
+
+ fp = popen(cmd, "r");
+ if (fp == NULL) {
+ pr_err("popen failed for %s\n", dso_name);
+ return NULL;
+ }
+
+ node = zalloc(sizeof(*node));
+ if (node == NULL) {
+ perror("not enough memory for the inline node");
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&node->val);
+ node->addr = addr;
+
+ while (getline(&filename, &len, fp) != -1) {
+ if (filename_split(filename, &line_nr) != 1) {
+ free(filename);
+ goto out;
+ }
+
+ if (inline_list__append(filename, NULL, line_nr, node,
+ NULL) != 0)
+ goto out;
+
+ filename = NULL;
+ }
+
+out:
+ pclose(fp);
+
+ if (list_empty(&node->val)) {
+ inline_node__delete(node);
+ return NULL;
+ }
+
+ return node;
+}
+
#endif /* HAVE_LIBBFD_SUPPORT */
/*
@@ -311,7 +443,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
if (dso_name == NULL)
goto out;
- if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines))
+ if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL))
goto out;
if (asprintf(&srcline, "%s:%u",
@@ -351,3 +483,28 @@ char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
{
return __get_srcline(dso, addr, sym, show_sym, false);
}
+
+struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
+{
+ const char *dso_name;
+
+ dso_name = dso__name(dso);
+ if (dso_name == NULL)
+ return NULL;
+
+ return addr2inlines(dso_name, addr, dso);
+}
+
+void inline_node__delete(struct inline_node *node)
+{
+ struct inline_list *ilist, *tmp;
+
+ list_for_each_entry_safe(ilist, tmp, &node->val, list) {
+ list_del_init(&ilist->list);
+ zfree(&ilist->filename);
+ zfree(&ilist->funcname);
+ free(ilist);
+ }
+
+ free(node);
+}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 0e660dba58ad..d1a40bb642ff 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -390,6 +390,11 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
return 0;
}
+char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name)
+{
+ return demangle_sym(dso, kmodule, elf_name);
+}
+
/*
* Align offset to 4 bytes as needed for note name and descriptor data.
*/
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 11cdde980545..870ef0f0659c 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -373,3 +373,10 @@ int kcore_copy(const char *from_dir __maybe_unused,
void symbol__elf_init(void)
{
}
+
+char *dso__demangle_sym(struct dso *dso __maybe_unused,
+ int kmodule __maybe_unused,
+ char *elf_name __maybe_unused)
+{
+ return NULL;
+}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 9222c7e702f3..e36213ccfcf7 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -305,6 +305,8 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
struct map *map);
+char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name);
+
void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
void symbols__insert(struct rb_root *symbols, struct symbol *sym);
void symbols__fixup_duplicate(struct rb_root *symbols);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b2cfa47990dc..cc0700d6fef0 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -364,4 +364,20 @@ int is_printable_array(char *p, unsigned int len);
int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
int unit_number__scnprintf(char *buf, size_t size, u64 n);
+
+struct inline_list {
+ char *filename;
+ char *funcname;
+ unsigned int line_nr;
+ struct list_head list;
+};
+
+struct inline_node {
+ u64 addr;
+ struct list_head val;
+};
+
+struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr);
+void inline_node__delete(struct inline_node *node);
+
#endif /* GIT_COMPAT_UTIL_H */
--
2.9.3
next prev parent reply other threads:[~2017-03-28 1:39 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-28 1:38 [GIT PULL 00/20] perf/core improvements and fixes Arnaldo Carvalho de Melo
2017-03-28 1:38 ` [PATCH 01/20] perf trace: Check for vfs_getname.pathname length Arnaldo Carvalho de Melo
2017-03-28 1:38 ` [PATCH 02/20] perf trace: Fix up error path indentation Arnaldo Carvalho de Melo
2017-03-28 1:38 ` [PATCH 03/20] perf trace: Fixup thread refcounting Arnaldo Carvalho de Melo
2017-03-28 1:38 ` [PATCH 04/20] perf auxtrace: Fix no_size logic in addr_filter__resolve_kernel_syms() Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 05/20] perf list sdt: Show option in man page Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 06/20] perf tools: Remove unused 'prefix' from builtin functions Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 07/20] perf report: Refactor common code in srcline.c Arnaldo Carvalho de Melo
2017-03-28 1:39 ` Arnaldo Carvalho de Melo [this message]
2017-03-28 1:39 ` [PATCH 09/20] perf report: Introduce --inline option Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 10/20] perf report: Show inline stack for stdio mode Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 11/20] perf report: Show inline stack for browser mode Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 12/20] perf report: Enable sorting by srcline as key Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 13/20] perf annotate: Fix a bug following symbolic link of a build-id file Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 14/20] perf annotate: Fix a bug of division by zero when calculating percent Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 15/20] perf buildid: Do not update SDT cache with null filename Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 16/20] perf buildid: Do not assume that readlink() returns a null terminated string Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 17/20] perf tests: " Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 18/20] perf utils: use sizeof(buf) - 1 in readlink() call Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 19/20] perf utils: Null terminate buf in read_ftrace_printk() Arnaldo Carvalho de Melo
2017-03-28 1:39 ` [PATCH 20/20] perf utils: Readlink /proc/self/exe to find the perf binary Arnaldo Carvalho de Melo
2017-03-28 5:45 ` [GIT PULL 00/20] perf/core improvements and fixes Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170328013915.15236-9-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=ak@linux.intel.com \
--cc=jolsa@kernel.org \
--cc=kan.liang@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=yao.jin@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.