diff options
Diffstat (limited to 'tools/perf/ui')
-rw-r--r-- | tools/perf/ui/browser.c | 4 | ||||
-rw-r--r-- | tools/perf/ui/browsers/annotate.c | 3 | ||||
-rw-r--r-- | tools/perf/ui/browsers/header.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 193 | ||||
-rw-r--r-- | tools/perf/ui/browsers/map.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/gtk/annotate.c | 3 | ||||
-rw-r--r-- | tools/perf/ui/gtk/hists.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 1 | ||||
-rw-r--r-- | tools/perf/ui/setup.c | 1 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 91 | ||||
-rw-r--r-- | tools/perf/ui/tui/setup.c | 1 |
11 files changed, 290 insertions, 13 deletions
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 3eb3edb307a4..a4d3762cd825 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -1,4 +1,5 @@ #include "../util.h" +#include "../string2.h" #include "../config.h" #include "../../perf.h" #include "libslang.h" @@ -13,6 +14,7 @@ #include "helpline.h" #include "keysyms.h" #include "../color.h" +#include "sane_ctype.h" static int ui_browser__percent_color(struct ui_browser *browser, double percent, bool current) @@ -579,7 +581,7 @@ static int ui_browser__color_config(const char *var, const char *value, break; *bg = '\0'; - while (isspace(*++bg)); + bg = ltrim(++bg); ui_browser__colorsets[i].bg = bg; ui_browser__colorsets[i].fg = fg; return 0; diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index ba36aac340bc..d990ad08a3c6 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -9,7 +9,10 @@ #include "../../util/symbol.h" #include "../../util/evsel.h" #include "../../util/config.h" +#include <inttypes.h> #include <pthread.h> +#include <linux/kernel.h> +#include <sys/ttydefaults.h> struct disasm_line_samples { double percent; diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c index edbeaaf31ace..e2c9390ff4c5 100644 --- a/tools/perf/ui/browsers/header.c +++ b/tools/perf/ui/browsers/header.c @@ -8,6 +8,8 @@ #include "util/header.h" #include "util/session.h" +#include <sys/ttydefaults.h> + static void ui_browser__argv_write(struct ui_browser *browser, void *entry, int row) { diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index fc4fb669ceee..69f4570bd4f9 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1,7 +1,11 @@ +#include <dirent.h> +#include <errno.h> +#include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <linux/rbtree.h> +#include <sys/ttydefaults.h> #include "../../util/evsel.h" #include "../../util/evlist.h" @@ -10,6 +14,7 @@ #include "../../util/sort.h" #include "../../util/util.h" #include "../../util/top.h" +#include "../../util/thread.h" #include "../../arch/common.h" #include "../browsers/hists.h" @@ -18,6 +23,11 @@ #include "../ui.h" #include "map.h" #include "annotate.h" +#include "srcline.h" +#include "string2.h" +#include "units.h" + +#include "sane_ctype.h" extern void hist_browser__init_hpp(void); @@ -144,9 +154,60 @@ static void callchain_list__set_folding(struct callchain_list *cl, bool unfold) cl->unfolded = unfold ? cl->has_children : false; } +static struct inline_node *inline_node__create(struct map *map, u64 ip) +{ + struct dso *dso; + struct inline_node *node; + + if (map == NULL) + return NULL; + + dso = map->dso; + if (dso == NULL) + return NULL; + + if (dso->kernel != DSO_TYPE_USER) + return NULL; + + node = dso__parse_addr_inlines(dso, + map__rip_2objdump(map, ip)); + + return node; +} + +static int inline__count_rows(struct inline_node *node) +{ + struct inline_list *ilist; + int i = 0; + + if (node == NULL) + return 0; + + list_for_each_entry(ilist, &node->val, list) { + if ((ilist->filename != NULL) || (ilist->funcname != NULL)) + i++; + } + + return i; +} + +static int callchain_list__inline_rows(struct callchain_list *chain) +{ + struct inline_node *node; + int rows; + + node = inline_node__create(chain->ms.map, chain->ip); + if (node == NULL) + return 0; + + rows = inline__count_rows(node); + inline_node__delete(node); + return rows; +} + static int callchain_node__count_rows_rb_tree(struct callchain_node *node) { - int n = 0; + int n = 0, inline_rows; struct rb_node *nd; for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) { @@ -156,6 +217,13 @@ static int callchain_node__count_rows_rb_tree(struct callchain_node *node) list_for_each_entry(chain, &child->val, list) { ++n; + + if (symbol_conf.inline_name) { + inline_rows = + callchain_list__inline_rows(chain); + n += inline_rows; + } + /* We need this because we may not have children */ folded_sign = callchain_list__folded(chain); if (folded_sign == '+') @@ -207,7 +275,7 @@ static int callchain_node__count_rows(struct callchain_node *node) { struct callchain_list *chain; bool unfolded = false; - int n = 0; + int n = 0, inline_rows; if (callchain_param.mode == CHAIN_FLAT) return callchain_node__count_flat_rows(node); @@ -216,6 +284,11 @@ static int callchain_node__count_rows(struct callchain_node *node) list_for_each_entry(chain, &node->val, list) { ++n; + if (symbol_conf.inline_name) { + inline_rows = callchain_list__inline_rows(chain); + n += inline_rows; + } + unfolded = chain->unfolded; } @@ -362,6 +435,19 @@ static void hist_entry__init_have_children(struct hist_entry *he) he->init_have_children = true; } +static void hist_entry_init_inline_node(struct hist_entry *he) +{ + if (he->inline_node) + return; + + he->inline_node = inline_node__create(he->ms.map, he->ip); + + if (he->inline_node == NULL) + return; + + he->has_children = true; +} + static bool hist_browser__toggle_fold(struct hist_browser *browser) { struct hist_entry *he = browser->he_selection; @@ -393,7 +479,12 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser) if (he->unfolded) { if (he->leaf) - he->nr_rows = callchain__count_rows(&he->sorted_chain); + if (he->inline_node) + he->nr_rows = inline__count_rows( + he->inline_node); + else + he->nr_rows = callchain__count_rows( + &he->sorted_chain); else he->nr_rows = hierarchy_count_rows(browser, he, false); @@ -753,6 +844,71 @@ static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_u #define LEVEL_OFFSET_STEP 3 +static int hist_browser__show_inline(struct hist_browser *browser, + struct inline_node *node, + unsigned short row, + int offset) +{ + struct inline_list *ilist; + char buf[1024]; + int color, width, first_row; + + first_row = row; + width = browser->b.width - (LEVEL_OFFSET_STEP + 2); + list_for_each_entry(ilist, &node->val, list) { + if ((ilist->filename != NULL) || (ilist->funcname != NULL)) { + color = HE_COLORSET_NORMAL; + if (ui_browser__is_current_entry(&browser->b, row)) + color = HE_COLORSET_SELECTED; + + if (callchain_param.key == CCKEY_ADDRESS || + callchain_param.key == CCKEY_SRCLINE) { + if (ilist->filename != NULL) + scnprintf(buf, sizeof(buf), + "%s:%d (inline)", + ilist->filename, + ilist->line_nr); + else + scnprintf(buf, sizeof(buf), "??"); + } else if (ilist->funcname != NULL) + scnprintf(buf, sizeof(buf), "%s (inline)", + ilist->funcname); + else if (ilist->filename != NULL) + scnprintf(buf, sizeof(buf), + "%s:%d (inline)", + ilist->filename, + ilist->line_nr); + else + scnprintf(buf, sizeof(buf), "??"); + + ui_browser__set_color(&browser->b, color); + hist_browser__gotorc(browser, row, 0); + ui_browser__write_nstring(&browser->b, " ", + LEVEL_OFFSET_STEP + offset); + ui_browser__write_nstring(&browser->b, buf, width); + row++; + } + } + + return row - first_row; +} + +static size_t show_inline_list(struct hist_browser *browser, struct map *map, + u64 ip, int row, int offset) +{ + struct inline_node *node; + int ret; + + node = inline_node__create(map, ip); + if (node == NULL) + return 0; + + ret = hist_browser__show_inline(browser, node, row, offset); + + inline_node__delete(node); + return ret; +} + static int hist_browser__show_callchain_list(struct hist_browser *browser, struct callchain_node *node, struct callchain_list *chain, @@ -764,6 +920,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, char bf[1024], *alloc_str; char buf[64], *alloc_str2; const char *str; + int inline_rows = 0, ret = 1; if (arg->row_offset != 0) { arg->row_offset--; @@ -801,10 +958,15 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, } print(browser, chain, str, offset, row, arg); - free(alloc_str); free(alloc_str2); - return 1; + + if (symbol_conf.inline_name) { + inline_rows = show_inline_list(browser, chain->ms.map, + chain->ip, row + 1, offset); + } + + return ret + inline_rows; } static bool check_percent_display(struct rb_node *node, u64 parent_total) @@ -1228,6 +1390,12 @@ static int hist_browser__show_entry(struct hist_browser *browser, folded_sign = hist_entry__folded(entry); } + if (symbol_conf.inline_name && + (!entry->has_children)) { + hist_entry_init_inline_node(entry); + folded_sign = hist_entry__folded(entry); + } + if (row_offset == 0) { struct hpp_arg arg = { .b = &browser->b, @@ -1259,7 +1427,8 @@ static int hist_browser__show_entry(struct hist_browser *browser, } if (first) { - if (symbol_conf.use_callchain) { + if (symbol_conf.use_callchain || + symbol_conf.inline_name) { ui_browser__printf(&browser->b, "%c ", folded_sign); width -= 2; } @@ -1301,8 +1470,14 @@ static int hist_browser__show_entry(struct hist_browser *browser, .is_current_entry = current_entry, }; - printed += hist_browser__show_callchain(browser, entry, 1, row, - hist_browser__show_callchain_entry, &arg, + if (entry->inline_node) + printed += hist_browser__show_inline(browser, + entry->inline_node, row, 0); + else + printed += hist_browser__show_callchain(browser, + entry, 1, row, + hist_browser__show_callchain_entry, + &arg, hist_browser__check_output_full); } @@ -2308,7 +2483,7 @@ static int switch_data_file(void) return ret; memset(options, 0, sizeof(options)); - memset(options, 0, sizeof(abs_path)); + memset(abs_path, 0, sizeof(abs_path)); while ((dent = readdir(pwd_dir))) { char path[PATH_MAX]; diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c index 9ce142de536d..ffa5addf631d 100644 --- a/tools/perf/ui/browsers/map.c +++ b/tools/perf/ui/browsers/map.c @@ -11,6 +11,8 @@ #include "../keysyms.h" #include "map.h" +#include "sane_ctype.h" + struct map_browser { struct ui_browser b; struct map *map; diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 8c9308ac30b7..e99ba86158d2 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -3,7 +3,8 @@ #include "util/annotate.h" #include "util/evsel.h" #include "ui/helpline.h" - +#include <inttypes.h> +#include <signal.h> enum { ANN_COL__PERCENT, diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index a4f02de7c1b5..e24f83957705 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -4,7 +4,9 @@ #include "../sort.h" #include "../hist.h" #include "../helpline.h" +#include "../string2.h" #include "gtk.h" +#include <signal.h> #define MAX_COLUMNS 32 diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 5d632dca672a..59addd52d9cd 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -1,3 +1,4 @@ +#include <inttypes.h> #include <math.h> #include <linux/compiler.h> diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index 50d13e58210f..5ea0b40c4fc2 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c @@ -4,6 +4,7 @@ #include "../util/cache.h" #include "../util/debug.h" #include "../util/hist.h" +#include "../util/util.h" pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; void *perf_gtk_handle; diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 668f4aecf2e6..42e432bd2eb4 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -4,7 +4,10 @@ #include "../../util/hist.h" #include "../../util/sort.h" #include "../../util/evsel.h" - +#include "../../util/srcline.h" +#include "../../util/string2.h" +#include "../../util/thread.h" +#include "../../util/sane_ctype.h" static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) { @@ -17,6 +20,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 +142,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 +297,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 +320,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 +605,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 +625,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; } diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 4ea2ba861fc2..d9350a1da48b 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c @@ -1,6 +1,7 @@ #include <errno.h> #include <signal.h> #include <stdbool.h> +#include <linux/kernel.h> #ifdef HAVE_BACKTRACE_SUPPORT #include <execinfo.h> #endif |