aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/ui/stdio/hist.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2017-03-28 07:44:43 +0200
committerIngo Molnar <mingo@kernel.org>2017-03-28 07:44:43 +0200
commit3906a13a6b4e78fbc0def03a808f091f0dff1b44 (patch)
treec37c8d9fbc1454e0482e60dddb4a4a4af29dfa72 /tools/perf/ui/stdio/hist.c
parentd652f4bbca35100358bad83c29ec0e40a1f8e5cc (diff)
parent55f77128e7652e537d6c226d5b56821cdb5c22de (diff)
Merge tag 'perf-core-for-mingo-4.12-20170327' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: - Handle inline functions in callchains (Jin Yao) - Enable sorting by srcline as key (Milian Wolff) Fixes: - Fix no_size logic in addr_filter__resolve_kernel_syms() in the auxtrace code (Adrian Hunter) - Fix some thread refcount leaks in 'perf trace' (Arnaldo Carvalho de Melo) - Fix divide by zero when calculating percent for an event in a group in the annotate by source line code (Taeung Song) - build-id files now aren't anymore symlinks, their parent directories are, so readlink the later (Taeung Song) - Assorted fixes for null termination problems, mostly related to readlink, detected by valgrind (Tommi Rantala) Infrastructure changes: - Make vfs_getname probe point logic in 'perf trace' more robust wrt length of pathname (Arnaldo Carvalho de Melo) - Remove unused 'prefix' parameter from builtins main functions (Arnaldo Carvalho de Melo) - Show 'perf list sdt' option in man page (Ravi Bangoria) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/ui/stdio/hist.c')
-rw-r--r--tools/perf/ui/stdio/hist.c86
1 files changed, 85 insertions, 1 deletions
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 668f4aecf2e6..d52d5f64ea89 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -17,6 +17,67 @@ static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
return ret;
}
+static size_t inline__fprintf(struct map *map, u64 ip, int left_margin,
+ int depth, int depth_mask, FILE *fp)
+{
+ struct dso *dso;
+ struct inline_node *node;
+ struct inline_list *ilist;
+ int ret = 0, i;
+
+ if (map == NULL)
+ return 0;
+
+ dso = map->dso;
+ if (dso == NULL)
+ return 0;
+
+ if (dso->kernel != DSO_TYPE_USER)
+ return 0;
+
+ node = dso__parse_addr_inlines(dso,
+ map__rip_2objdump(map, ip));
+ if (node == NULL)
+ return 0;
+
+ list_for_each_entry(ilist, &node->val, list) {
+ if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
+ ret += callchain__fprintf_left_margin(fp, left_margin);
+
+ for (i = 0; i < depth; i++) {
+ if (depth_mask & (1 << i))
+ ret += fprintf(fp, "|");
+ else
+ ret += fprintf(fp, " ");
+ ret += fprintf(fp, " ");
+ }
+
+ if (callchain_param.key == CCKEY_ADDRESS ||
+ callchain_param.key == CCKEY_SRCLINE) {
+ if (ilist->filename != NULL)
+ ret += fprintf(fp, "%s:%d (inline)",
+ ilist->filename,
+ ilist->line_nr);
+ else
+ ret += fprintf(fp, "??");
+ } else if (ilist->funcname != NULL)
+ ret += fprintf(fp, "%s (inline)",
+ ilist->funcname);
+ else if (ilist->filename != NULL)
+ ret += fprintf(fp, "%s:%d (inline)",
+ ilist->filename,
+ ilist->line_nr);
+ else
+ ret += fprintf(fp, "??");
+
+ ret += fprintf(fp, "\n");
+ }
+ }
+
+ inline_node__delete(node);
+ return ret;
+}
+
static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
int left_margin)
{
@@ -78,6 +139,10 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
fputs(str, fp);
fputc('\n', fp);
free(alloc_str);
+
+ if (symbol_conf.inline_name)
+ ret += inline__fprintf(chain->ms.map, chain->ip,
+ left_margin, depth, depth_mask, fp);
return ret;
}
@@ -229,6 +294,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
if (!i++ && field_order == NULL &&
sort_order && !prefixcmp(sort_order, "sym"))
continue;
+
if (!printed) {
ret += callchain__fprintf_left_margin(fp, left_margin);
ret += fprintf(fp, "|\n");
@@ -251,6 +317,13 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
if (++entries_printed == callchain_param.print_limit)
break;
+
+ if (symbol_conf.inline_name)
+ ret += inline__fprintf(chain->ms.map,
+ chain->ip,
+ left_margin,
+ 0, 0,
+ fp);
}
root = &cnode->rb_root;
}
@@ -529,6 +602,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
bool use_callchain)
{
int ret;
+ int callchain_ret = 0;
+ int inline_ret = 0;
struct perf_hpp hpp = {
.buf = bf,
.size = size,
@@ -547,7 +622,16 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
ret = fprintf(fp, "%s\n", bf);
if (use_callchain)
- ret += hist_entry_callchain__fprintf(he, total_period, 0, fp);
+ callchain_ret = hist_entry_callchain__fprintf(he, total_period,
+ 0, fp);
+
+ if (callchain_ret == 0 && symbol_conf.inline_name) {
+ inline_ret = inline__fprintf(he->ms.map, he->ip, 0, 0, 0, fp);
+ ret += inline_ret;
+ if (inline_ret > 0)
+ ret += fprintf(fp, "\n");
+ } else
+ ret += callchain_ret;
return ret;
}