diff options
Diffstat (limited to 'tools/perf/ui')
-rw-r--r-- | tools/perf/ui/browsers/annotate.c | 33 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 133 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.h | 1 | ||||
-rw-r--r-- | tools/perf/ui/browsers/map.c | 4 | ||||
-rw-r--r-- | tools/perf/ui/gtk/annotate.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/gtk/hists.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/helpline.c | 10 | ||||
-rw-r--r-- | tools/perf/ui/helpline.h | 1 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 21 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 117 |
10 files changed, 228 insertions, 96 deletions
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 2e2d10022355..ba36aac340bc 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -213,17 +213,17 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ui_browser__write_nstring(browser, bf, printed); if (change_color) ui_browser__set_color(browser, color); - if (dl->ins && dl->ins->ops->scnprintf) { - if (ins__is_jump(dl->ins)) { - bool fwd = dl->ops.target.offset > (u64)dl->offset; + if (dl->ins.ops && dl->ins.ops->scnprintf) { + if (ins__is_jump(&dl->ins)) { + bool fwd = dl->ops.target.offset > dl->offset; ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : SLSMG_UARROW_CHAR); SLsmg_write_char(' '); - } else if (ins__is_call(dl->ins)) { + } else if (ins__is_call(&dl->ins)) { ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); SLsmg_write_char(' '); - } else if (ins__is_ret(dl->ins)) { + } else if (ins__is_ret(&dl->ins)) { ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); SLsmg_write_char(' '); } else { @@ -243,9 +243,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) { - if (!dl || !dl->ins || !ins__is_jump(dl->ins) + if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) || !disasm_line__has_offset(dl) - || dl->ops.target.offset >= symbol__size(sym)) + || dl->ops.target.offset < 0 + || dl->ops.target.offset >= (s64)symbol__size(sym)) return false; return true; @@ -492,10 +493,10 @@ static bool annotate_browser__callq(struct annotate_browser *browser, }; char title[SYM_TITLE_MAX_SIZE]; - if (!ins__is_call(dl->ins)) + if (!ins__is_call(&dl->ins)) return false; - if (map_groups__find_ams(&target, NULL) || + if (map_groups__find_ams(&target) || map__rip_2objdump(target.map, target.map->map_ip(target.map, target.addr)) != dl->ops.target.addr) { @@ -543,14 +544,16 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows static bool annotate_browser__jump(struct annotate_browser *browser) { struct disasm_line *dl = browser->selection; + u64 offset; s64 idx; - if (!ins__is_jump(dl->ins)) + if (!ins__is_jump(&dl->ins)) return false; - dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx); + offset = dl->ops.target.offset; + dl = annotate_browser__find_offset(browser, offset, &idx); if (dl == NULL) { - ui_helpline__puts("Invalid jump offset"); + ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); return true; } @@ -841,9 +844,9 @@ show_help: ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); else if (browser->selection->offset == -1) ui_helpline__puts("Actions are only available for assembly lines."); - else if (!browser->selection->ins) + else if (!browser->selection->ins.ops) goto show_sup_ins; - else if (ins__is_ret(browser->selection->ins)) + else if (ins__is_ret(&browser->selection->ins)) goto out; else if (!(annotate_browser__jump(browser) || annotate_browser__callq(browser, evsel, hbt))) { @@ -1050,7 +1053,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, (nr_pcnt - 1); } - err = symbol__disassemble(sym, map, sizeof_bdl); + err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), sizeof_bdl); if (err) { char msg[BUFSIZ]; symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 13d414384739..641b40234a9d 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -30,7 +30,7 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd, static bool hist_browser__has_filter(struct hist_browser *hb) { - return hists__has_filter(hb->hists) || hb->min_pcnt || symbol_conf.has_filter; + return hists__has_filter(hb->hists) || hb->min_pcnt || symbol_conf.has_filter || hb->c2c_filter; } static int hist_browser__get_folding(struct hist_browser *browser) @@ -69,8 +69,11 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb) static void hist_browser__update_rows(struct hist_browser *hb) { struct ui_browser *browser = &hb->b; - u16 header_offset = hb->show_headers ? 1 : 0, index_row; + struct hists *hists = hb->hists; + struct perf_hpp_list *hpp_list = hists->hpp_list; + u16 header_offset, index_row; + header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0; browser->rows = browser->height - header_offset; /* * Verify if we were at the last line and that line isn't @@ -99,8 +102,11 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser) static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) { - u16 header_offset = browser->show_headers ? 1 : 0; + struct hists *hists = browser->hists; + struct perf_hpp_list *hpp_list = hists->hpp_list; + u16 header_offset; + header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0; ui_browser__gotorc(&browser->b, row + header_offset, column); } @@ -595,7 +601,8 @@ int hist_browser__run(struct hist_browser *browser, const char *help) u64 nr_entries; hbt->timer(hbt->arg); - if (hist_browser__has_filter(browser)) + if (hist_browser__has_filter(browser) || + symbol_conf.report_hierarchy) hist_browser__update_nr_entries(browser); nr_entries = hist_browser__nr_entries(browser); @@ -731,6 +738,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, struct callchain_print_arg *arg) { char bf[1024], *alloc_str; + char buf[64], *alloc_str2; const char *str; if (arg->row_offset != 0) { @@ -739,12 +747,26 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, } alloc_str = NULL; + alloc_str2 = NULL; + str = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso); - if (need_percent) { - char buf[64]; + if (symbol_conf.show_branchflag_count) { + if (need_percent) + callchain_list_counts__printf_value(node, chain, NULL, + buf, sizeof(buf)); + else + callchain_list_counts__printf_value(NULL, chain, NULL, + buf, sizeof(buf)); + if (asprintf(&alloc_str2, "%s%s", str, buf) < 0) + str = "Not enough memory!"; + else + str = alloc_str2; + } + + if (need_percent) { callchain_node__scnprintf_value(node, buf, sizeof(buf), total); @@ -757,6 +779,7 @@ 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; } @@ -1074,7 +1097,7 @@ struct hpp_arg { bool current_entry; }; -static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) +int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) { struct hpp_arg *arg = hpp->ptr; int ret, len; @@ -1091,7 +1114,6 @@ static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent); ui_browser__printf(arg->b, "%s", hpp->buf); - advance_hpp(hpp, ret); return ret; } @@ -1331,8 +1353,8 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, } if (first) { - ui_browser__printf(&browser->b, "%c", folded_sign); - width--; + ui_browser__printf(&browser->b, "%c ", folded_sign); + width -= 2; first = false; } else { ui_browser__printf(&browser->b, " "); @@ -1355,8 +1377,10 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, width -= hpp.buf - s; } - ui_browser__write_nstring(&browser->b, "", hierarchy_indent); - width -= hierarchy_indent; + if (!first) { + ui_browser__write_nstring(&browser->b, "", hierarchy_indent); + width -= hierarchy_indent; + } if (column >= browser->b.horiz_scroll) { char s[2048]; @@ -1375,7 +1399,13 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, } perf_hpp_list__for_each_format(entry->hpp_list, fmt) { - ui_browser__write_nstring(&browser->b, "", 2); + if (first) { + ui_browser__printf(&browser->b, "%c ", folded_sign); + first = false; + } else { + ui_browser__write_nstring(&browser->b, "", 2); + } + width -= 2; /* @@ -1496,7 +1526,9 @@ static int advance_hpp_check(struct perf_hpp *hpp, int inc) return hpp->size <= 0; } -static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, size_t size) +static int +hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, + size_t size, int line) { struct hists *hists = browser->hists; struct perf_hpp dummy_hpp = { @@ -1506,6 +1538,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * struct perf_hpp_fmt *fmt; size_t ret = 0; int column = 0; + int span = 0; if (symbol_conf.use_callchain) { ret = scnprintf(buf, size, " "); @@ -1517,10 +1550,13 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) continue; - ret = fmt->header(fmt, &dummy_hpp, hists); + ret = fmt->header(fmt, &dummy_hpp, hists, line, &span); if (advance_hpp_check(&dummy_hpp, ret)) break; + if (span) + continue; + ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " "); if (advance_hpp_check(&dummy_hpp, ret)) break; @@ -1543,10 +1579,11 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows int indent = hists->nr_hpp_node - 2; bool first_node, first_col; - ret = scnprintf(buf, size, " "); + ret = scnprintf(buf, size, " "); if (advance_hpp_check(&dummy_hpp, ret)) return ret; + first_node = true; /* the first hpp_list_node is for overhead columns */ fmt_node = list_first_entry(&hists->hpp_formats, struct perf_hpp_list_node, list); @@ -1554,19 +1591,23 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows if (column++ < browser->b.horiz_scroll) continue; - ret = fmt->header(fmt, &dummy_hpp, hists); + ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL); if (advance_hpp_check(&dummy_hpp, ret)) break; ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " "); if (advance_hpp_check(&dummy_hpp, ret)) break; + + first_node = false; } - ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "%*s", - indent * HIERARCHY_INDENT, ""); - if (advance_hpp_check(&dummy_hpp, ret)) - return ret; + if (!first_node) { + ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "%*s", + indent * HIERARCHY_INDENT, ""); + if (advance_hpp_check(&dummy_hpp, ret)) + return ret; + } first_node = true; list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) { @@ -1591,7 +1632,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows } first_col = false; - ret = fmt->header(fmt, &dummy_hpp, hists); + ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL); dummy_hpp.buf[ret] = '\0'; start = trim(dummy_hpp.buf); @@ -1622,14 +1663,21 @@ static void hists_browser__hierarchy_headers(struct hist_browser *browser) static void hists_browser__headers(struct hist_browser *browser) { - char headers[1024]; + struct hists *hists = browser->hists; + struct perf_hpp_list *hpp_list = hists->hpp_list; - hists_browser__scnprintf_headers(browser, headers, - sizeof(headers)); + int line; - ui_browser__gotorc(&browser->b, 0, 0); - ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); - ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); + for (line = 0; line < hpp_list->nr_header_lines; line++) { + char headers[1024]; + + hists_browser__scnprintf_headers(browser, headers, + sizeof(headers), line); + + ui_browser__gotorc(&browser->b, line, 0); + ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); + ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); + } } static void hist_browser__show_headers(struct hist_browser *browser) @@ -1656,10 +1704,13 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) u16 header_offset = 0; struct rb_node *nd; struct hist_browser *hb = container_of(browser, struct hist_browser, b); + struct hists *hists = hb->hists; if (hb->show_headers) { + struct perf_hpp_list *hpp_list = hists->hpp_list; + hist_browser__show_headers(hb); - header_offset = 1; + header_offset = hpp_list->nr_header_lines; } ui_browser__hists_init_top(browser); @@ -2054,10 +2105,23 @@ void hist_browser__init(struct hist_browser *browser, browser->b.use_navkeypressed = true; browser->show_headers = symbol_conf.show_hist_headers; - hists__for_each_format(hists, fmt) { - perf_hpp__reset_width(fmt, hists); + if (symbol_conf.report_hierarchy) { + struct perf_hpp_list_node *fmt_node; + + /* count overhead columns (in the first node) */ + fmt_node = list_first_entry(&hists->hpp_formats, + struct perf_hpp_list_node, list); + perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) + ++browser->b.columns; + + /* add a single column for whole hierarchy sort keys*/ ++browser->b.columns; + } else { + hists__for_each_format(hists, fmt) + ++browser->b.columns; } + + hists__reset_column_width(hists); } struct hist_browser *hist_browser__new(struct hists *hists) @@ -2418,8 +2482,6 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act) browser->hists->dso_filter = NULL; ui_helpline__pop(); } else { - if (map == NULL) - return 0; ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"", __map__is_kernel(map) ? "the Kernel" : map->dso->short_name); browser->hists->dso_filter = map->dso; @@ -2787,7 +2849,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, do_zoom_dso(browser, actions); continue; case 'V': - browser->show_dso = !browser->show_dso; + verbose = (verbose + 1) % 4; + browser->show_dso = verbose > 0; + ui_helpline__fpush("Verbosity level set to %d\n", + verbose); continue; case 't': actions->thread = thread; diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h index 39bd0f28f211..23d6acb84800 100644 --- a/tools/perf/ui/browsers/hists.h +++ b/tools/perf/ui/browsers/hists.h @@ -18,6 +18,7 @@ struct hist_browser { u64 nr_non_filtered_entries; u64 nr_hierarchy_entries; u64 nr_callchain_rows; + bool c2c_filter; /* Get title string. */ int (*title)(struct hist_browser *browser, diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c index 80912778bb6d..98a34664bb7e 100644 --- a/tools/perf/ui/browsers/map.c +++ b/tools/perf/ui/browsers/map.c @@ -52,9 +52,9 @@ static int map_browser__search(struct map_browser *browser) if (target[0] == '0' && tolower(target[1]) == 'x') { u64 addr = strtoull(target, NULL, 16); - sym = map__find_symbol(browser->map, addr, NULL); + sym = map__find_symbol(browser->map, addr); } else - sym = map__find_symbol_by_name(browser->map, target, NULL); + sym = map__find_symbol_by_name(browser->map, target); if (sym != NULL) { u32 *idx = symbol__browser_index(sym); diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 42d319927762..8c9308ac30b7 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -167,7 +167,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map, if (map->dso->annotate_warned) return -1; - err = symbol__disassemble(sym, map, 0); + err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0); if (err) { char msg[BUFSIZ]; symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index c5f3677f6679..a4f02de7c1b5 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -549,7 +549,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, strcat(buf, "+"); first_col = false; - fmt->header(fmt, &hpp, hists); + fmt->header(fmt, &hpp, hists, 0, NULL); strcat(buf, ltrim(rtrim(hpp.buf))); } } diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c index 5b74a7eba210..379039ab00d8 100644 --- a/tools/perf/ui/helpline.c +++ b/tools/perf/ui/helpline.c @@ -72,3 +72,13 @@ int ui_helpline__vshow(const char *fmt, va_list ap) { return helpline_fns->show(fmt, ap); } + +void ui_helpline__printf(const char *fmt, ...) +{ + va_list ap; + + ui_helpline__pop(); + va_start(ap, fmt); + ui_helpline__vpush(fmt, ap); + va_end(ap); +} diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h index 46181f4fc07e..d52d0a1a881b 100644 --- a/tools/perf/ui/helpline.h +++ b/tools/perf/ui/helpline.h @@ -21,6 +21,7 @@ void ui_helpline__push(const char *msg); void ui_helpline__vpush(const char *fmt, va_list ap); void ui_helpline__fpush(const char *fmt, ...); void ui_helpline__puts(const char *msg); +void ui_helpline__printf(const char *fmt, ...); int ui_helpline__vshow(const char *fmt, va_list ap); extern char ui_helpline__current[512]; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 4274969ddc89..37388397b5bc 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -230,13 +230,14 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt, } static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, - struct hists *hists) + struct hists *hists, int line __maybe_unused, + int *span __maybe_unused) { int len = hpp__width_fn(fmt, hpp, hists); return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); } -static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) +int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) { va_list args; ssize_t ssize = hpp->size; @@ -441,6 +442,7 @@ struct perf_hpp_fmt perf_hpp__format[] = { struct perf_hpp_list perf_hpp_list = { .fields = LIST_HEAD_INIT(perf_hpp_list.fields), .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts), + .nr_header_lines = 1, }; #undef HPP__COLOR_PRINT_FNS @@ -697,6 +699,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) } } +void hists__reset_column_width(struct hists *hists) +{ + struct perf_hpp_fmt *fmt; + struct perf_hpp_list_node *node; + + hists__for_each_format(hists, fmt) + perf_hpp__reset_width(fmt, hists); + + /* hierarchy entries have their own hpp list */ + list_for_each_entry(node, &hists->hpp_formats, list) { + perf_hpp_list__for_each_format(&node->hpp, fmt) + perf_hpp__reset_width(fmt, hists); + } +} + void perf_hpp__set_user_width(const char *width_list_str) { struct perf_hpp_fmt *fmt; diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index f04a63112079..668f4aecf2e6 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -41,7 +41,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node, { int i; size_t ret = 0; - char bf[1024]; + char bf[1024], *alloc_str = NULL; + char buf[64]; + const char *str; ret += callchain__fprintf_left_margin(fp, left_margin); for (i = 0; i < depth; i++) { @@ -56,8 +58,26 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node, } else ret += fprintf(fp, "%s", " "); } - fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp); + + str = callchain_list__sym_name(chain, bf, sizeof(bf), false); + + if (symbol_conf.show_branchflag_count) { + if (!period) + callchain_list_counts__printf_value(node, chain, NULL, + buf, sizeof(buf)); + else + callchain_list_counts__printf_value(NULL, chain, NULL, + buf, sizeof(buf)); + + if (asprintf(&alloc_str, "%s%s", str, buf) < 0) + str = "Not enough memory!"; + else + str = alloc_str; + } + + fputs(str, fp); fputc('\n', fp); + free(alloc_str); return ret; } @@ -219,8 +239,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, } else ret += callchain__fprintf_left_margin(fp, left_margin); - ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf), - false)); + ret += fprintf(fp, "%s", + callchain_list__sym_name(chain, bf, + sizeof(bf), + false)); + + if (symbol_conf.show_branchflag_count) + ret += callchain_list_counts__printf_value( + NULL, chain, fp, NULL, 0); + ret += fprintf(fp, "\n"); if (++entries_printed == callchain_param.print_limit) break; @@ -373,7 +400,8 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he, return 0; } -static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) +int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, + struct perf_hpp_list *hpp_list) { const char *sep = symbol_conf.field_sep; struct perf_hpp_fmt *fmt; @@ -384,7 +412,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) if (symbol_conf.exclude_other && !he->parent) return 0; - hists__for_each_format(he->hists, fmt) { + perf_hpp_list__for_each_format(hpp_list, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -410,6 +438,11 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) return hpp->buf - start; } +static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) +{ + return __hist_entry__snprintf(he, hpp, he->hists->hpp_list); +} + static int hist_entry__hierarchy_fprintf(struct hist_entry *he, struct perf_hpp *hpp, struct hists *hists, @@ -528,8 +561,8 @@ static int print_hierarchy_indent(const char *sep, int indent, return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line); } -static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, - const char *sep, FILE *fp) +static int hists__fprintf_hierarchy_headers(struct hists *hists, + struct perf_hpp *hpp, FILE *fp) { bool first_node, first_col; int indent; @@ -538,6 +571,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, unsigned header_width = 0; struct perf_hpp_fmt *fmt; struct perf_hpp_list_node *fmt_node; + const char *sep = symbol_conf.field_sep; indent = hists->nr_hpp_node; @@ -549,7 +583,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, struct perf_hpp_list_node, list); perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { - fmt->header(fmt, hpp, hists); + fmt->header(fmt, hpp, hists, 0, NULL); fprintf(fp, "%s%s", hpp->buf, sep ?: " "); } @@ -569,7 +603,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, header_width += fprintf(fp, "+"); first_col = false; - fmt->header(fmt, hpp, hists); + fmt->header(fmt, hpp, hists, 0, NULL); header_width += fprintf(fp, "%s", trim(hpp->buf)); } @@ -623,20 +657,28 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, return 2; } -static int -hists__fprintf_hierarchy_headers(struct hists *hists, - struct perf_hpp *hpp, - FILE *fp) +static void fprintf_line(struct hists *hists, struct perf_hpp *hpp, + int line, FILE *fp) { - struct perf_hpp_list_node *fmt_node; struct perf_hpp_fmt *fmt; + const char *sep = symbol_conf.field_sep; + bool first = true; + int span = 0; - list_for_each_entry(fmt_node, &hists->hpp_formats, list) { - perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) - perf_hpp__reset_width(fmt, hists); - } + hists__for_each_format(hists, fmt) { + if (perf_hpp__should_skip(fmt, hists)) + continue; + + if (!first && !span) + fprintf(fp, "%s", sep ?: " "); + else + first = false; + + fmt->header(fmt, hpp, hists, line, &span); - return print_hierarchy_header(hists, hpp, symbol_conf.field_sep, fp); + if (!span) + fprintf(fp, "%s", hpp->buf); + } } static int @@ -644,28 +686,23 @@ hists__fprintf_standard_headers(struct hists *hists, struct perf_hpp *hpp, FILE *fp) { + struct perf_hpp_list *hpp_list = hists->hpp_list; struct perf_hpp_fmt *fmt; unsigned int width; const char *sep = symbol_conf.field_sep; bool first = true; - - hists__for_each_format(hists, fmt) { - if (perf_hpp__should_skip(fmt, hists)) - continue; - - if (!first) - fprintf(fp, "%s", sep ?: " "); - else - first = false; - - fmt->header(fmt, hpp, hists); - fprintf(fp, "%s", hpp->buf); + int line; + + for (line = 0; line < hpp_list->nr_header_lines; line++) { + /* first # is displayed one level up */ + if (line) + fprintf(fp, "# "); + fprintf_line(hists, hpp, line, fp); + fprintf(fp, "\n"); } - fprintf(fp, "\n"); - if (sep) - return 1; + return hpp_list->nr_header_lines; first = true; @@ -689,12 +726,12 @@ hists__fprintf_standard_headers(struct hists *hists, fprintf(fp, "\n"); fprintf(fp, "#\n"); - return 3; + return hpp_list->nr_header_lines + 2; } -static int hists__fprintf_headers(struct hists *hists, FILE *fp) +int hists__fprintf_headers(struct hists *hists, FILE *fp) { - char bf[96]; + char bf[1024]; struct perf_hpp dummy_hpp = { .buf = bf, .size = sizeof(bf), @@ -713,7 +750,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, int max_cols, float min_pcnt, FILE *fp, bool use_callchain) { - struct perf_hpp_fmt *fmt; struct rb_node *nd; size_t ret = 0; const char *sep = symbol_conf.field_sep; @@ -724,8 +760,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, init_rem_hits(); - hists__for_each_format(hists, fmt) - perf_hpp__reset_width(fmt, hists); + hists__reset_column_width(hists); if (symbol_conf.col_width_list_str) perf_hpp__set_user_width(symbol_conf.col_width_list_str); |