diff options
| author | Ingo Molnar <mingo@kernel.org> | 2012-09-09 04:39:14 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2012-09-09 04:39:14 -0400 |
| commit | d5cb2aef4fda355fbafe8db4f425b73ea94d2019 (patch) | |
| tree | f6812e5248557bd16803f787e0cbc9d57ab60133 /tools | |
| parent | ef34eb4da3eb62a1511592adf7c76d74faca0b14 (diff) | |
| parent | 6c7f631261064762a8ba1ee34fc2b76d117ef3fa (diff) | |
Merge tag 'perf-core-for-mingo' 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:
* Don't pass const char pointers to basename, so that we can unconditionally
use libgen.h and thus avoid ifdef BIONIC lines, from David Ahern
* Fix assert/BUG_ON when NDEBUG is defined, from Irina Tirdea.
* Refactor hist formatting so that it can be reused with the GTK browser,
From Namhyung Kim
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/Makefile | 2 | ||||
| -rw-r--r-- | tools/perf/bench/sched-pipe.c | 6 | ||||
| -rw-r--r-- | tools/perf/builtin-diff.c | 1 | ||||
| -rw-r--r-- | tools/perf/ui/browsers/hists.c | 96 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/browser.c | 101 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/gtk.h | 1 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/setup.c | 1 | ||||
| -rw-r--r-- | tools/perf/ui/hist.c | 389 | ||||
| -rw-r--r-- | tools/perf/ui/setup.c | 8 | ||||
| -rw-r--r-- | tools/perf/ui/stdio/hist.c | 239 | ||||
| -rw-r--r-- | tools/perf/ui/tui/setup.c | 4 | ||||
| -rw-r--r-- | tools/perf/util/annotate.c | 9 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 33 | ||||
| -rw-r--r-- | tools/perf/util/hist.h | 37 | ||||
| -rw-r--r-- | tools/perf/util/include/linux/kernel.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 2 |
17 files changed, 665 insertions, 280 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3eda49215730..e4b2e8f2606c 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
| @@ -403,7 +403,9 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o | |||
| 403 | LIB_OBJS += $(OUTPUT)util/target.o | 403 | LIB_OBJS += $(OUTPUT)util/target.o |
| 404 | LIB_OBJS += $(OUTPUT)util/rblist.o | 404 | LIB_OBJS += $(OUTPUT)util/rblist.o |
| 405 | LIB_OBJS += $(OUTPUT)util/intlist.o | 405 | LIB_OBJS += $(OUTPUT)util/intlist.o |
| 406 | |||
| 406 | LIB_OBJS += $(OUTPUT)ui/helpline.o | 407 | LIB_OBJS += $(OUTPUT)ui/helpline.o |
| 408 | LIB_OBJS += $(OUTPUT)ui/hist.o | ||
| 407 | LIB_OBJS += $(OUTPUT)ui/stdio/hist.o | 409 | LIB_OBJS += $(OUTPUT)ui/stdio/hist.o |
| 408 | 410 | ||
| 409 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o | 411 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o |
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 0c7454f8b8a9..15911e9c587a 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c | |||
| @@ -56,13 +56,13 @@ int bench_sched_pipe(int argc, const char **argv, | |||
| 56 | * causes error in building environment for perf | 56 | * causes error in building environment for perf |
| 57 | */ | 57 | */ |
| 58 | int __used ret, wait_stat; | 58 | int __used ret, wait_stat; |
| 59 | pid_t pid, retpid; | 59 | pid_t pid, retpid __used; |
| 60 | 60 | ||
| 61 | argc = parse_options(argc, argv, options, | 61 | argc = parse_options(argc, argv, options, |
| 62 | bench_sched_pipe_usage, 0); | 62 | bench_sched_pipe_usage, 0); |
| 63 | 63 | ||
| 64 | assert(!pipe(pipe_1)); | 64 | BUG_ON(pipe(pipe_1)); |
| 65 | assert(!pipe(pipe_2)); | 65 | BUG_ON(pipe(pipe_2)); |
| 66 | 66 | ||
| 67 | pid = fork(); | 67 | pid = fork(); |
| 68 | assert(pid >= 0); | 68 | assert(pid >= 0); |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index e9933fdd256e..c4c6d76b70ea 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
| @@ -264,6 +264,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used) | |||
| 264 | if (symbol__init() < 0) | 264 | if (symbol__init() < 0) |
| 265 | return -1; | 265 | return -1; |
| 266 | 266 | ||
| 267 | perf_hpp__init(true, show_displacement); | ||
| 267 | setup_sorting(diff_usage, options); | 268 | setup_sorting(diff_usage, options); |
| 268 | setup_pager(); | 269 | setup_pager(); |
| 269 | 270 | ||
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 81bd8c2af730..5a5739bbe6ac 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
| @@ -28,6 +28,8 @@ struct hist_browser { | |||
| 28 | bool has_symbols; | 28 | bool has_symbols; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | extern void hist_browser__init_hpp(void); | ||
| 32 | |||
| 31 | static int hists__browser_title(struct hists *hists, char *bf, size_t size, | 33 | static int hists__browser_title(struct hists *hists, char *bf, size_t size, |
| 32 | const char *ev_name); | 34 | const char *ev_name); |
| 33 | 35 | ||
| @@ -563,14 +565,47 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
| 563 | return row - first_row; | 565 | return row - first_row; |
| 564 | } | 566 | } |
| 565 | 567 | ||
| 568 | #define HPP__COLOR_FN(_name, _field) \ | ||
| 569 | static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ | ||
| 570 | struct hist_entry *he) \ | ||
| 571 | { \ | ||
| 572 | double percent = 100.0 * he->_field / hpp->total_period; \ | ||
| 573 | *(double *)hpp->ptr = percent; \ | ||
| 574 | return scnprintf(hpp->buf, hpp->size, "%5.2f%%", percent); \ | ||
| 575 | } | ||
| 576 | |||
| 577 | HPP__COLOR_FN(overhead, period) | ||
| 578 | HPP__COLOR_FN(overhead_sys, period_sys) | ||
| 579 | HPP__COLOR_FN(overhead_us, period_us) | ||
| 580 | HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) | ||
| 581 | HPP__COLOR_FN(overhead_guest_us, period_guest_us) | ||
| 582 | |||
| 583 | #undef HPP__COLOR_FN | ||
| 584 | |||
| 585 | void hist_browser__init_hpp(void) | ||
| 586 | { | ||
| 587 | perf_hpp__init(false, false); | ||
| 588 | |||
| 589 | perf_hpp__format[PERF_HPP__OVERHEAD].color = | ||
| 590 | hist_browser__hpp_color_overhead; | ||
| 591 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = | ||
| 592 | hist_browser__hpp_color_overhead_sys; | ||
| 593 | perf_hpp__format[PERF_HPP__OVERHEAD_US].color = | ||
| 594 | hist_browser__hpp_color_overhead_us; | ||
| 595 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = | ||
| 596 | hist_browser__hpp_color_overhead_guest_sys; | ||
| 597 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = | ||
| 598 | hist_browser__hpp_color_overhead_guest_us; | ||
| 599 | } | ||
| 600 | |||
| 566 | static int hist_browser__show_entry(struct hist_browser *browser, | 601 | static int hist_browser__show_entry(struct hist_browser *browser, |
| 567 | struct hist_entry *entry, | 602 | struct hist_entry *entry, |
| 568 | unsigned short row) | 603 | unsigned short row) |
| 569 | { | 604 | { |
| 570 | char s[256]; | 605 | char s[256]; |
| 571 | double percent; | 606 | double percent; |
| 572 | int printed = 0; | 607 | int i, printed = 0; |
| 573 | int width = browser->b.width - 6; /* The percentage */ | 608 | int width = browser->b.width - 1; |
| 574 | char folded_sign = ' '; | 609 | char folded_sign = ' '; |
| 575 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); | 610 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); |
| 576 | off_t row_offset = entry->row_offset; | 611 | off_t row_offset = entry->row_offset; |
| @@ -586,35 +621,50 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
| 586 | } | 621 | } |
| 587 | 622 | ||
| 588 | if (row_offset == 0) { | 623 | if (row_offset == 0) { |
| 589 | hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists); | 624 | struct perf_hpp hpp = { |
| 590 | percent = (entry->period * 100.0) / browser->hists->stats.total_period; | 625 | .buf = s, |
| 626 | .size = sizeof(s), | ||
| 627 | .total_period = browser->hists->stats.total_period, | ||
| 628 | }; | ||
| 591 | 629 | ||
| 592 | ui_browser__set_percent_color(&browser->b, percent, current_entry); | 630 | ui_browser__gotorc(&browser->b, row, 1); |
| 593 | ui_browser__gotorc(&browser->b, row, 0); | ||
| 594 | if (symbol_conf.use_callchain) { | ||
| 595 | slsmg_printf("%c ", folded_sign); | ||
| 596 | width -= 2; | ||
| 597 | } | ||
| 598 | 631 | ||
| 599 | slsmg_printf(" %5.2f%%", percent); | 632 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
| 633 | if (!perf_hpp__format[i].cond) | ||
| 634 | continue; | ||
| 600 | 635 | ||
| 601 | /* The scroll bar isn't being used */ | 636 | if (i) { |
| 602 | if (!browser->b.navkeypressed) | 637 | slsmg_printf(" "); |
| 603 | width += 1; | 638 | width -= 2; |
| 639 | } | ||
| 604 | 640 | ||
| 605 | if (!current_entry || !browser->b.navkeypressed) | 641 | if (perf_hpp__format[i].color) { |
| 606 | ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); | 642 | hpp.ptr = &percent; |
| 643 | /* It will set percent for us. See HPP__COLOR_FN above. */ | ||
| 644 | width -= perf_hpp__format[i].color(&hpp, entry); | ||
| 607 | 645 | ||
| 608 | if (symbol_conf.show_nr_samples) { | 646 | ui_browser__set_percent_color(&browser->b, percent, current_entry); |
| 609 | slsmg_printf(" %11u", entry->nr_events); | 647 | |
| 610 | width -= 12; | 648 | if (i == 0 && symbol_conf.use_callchain) { |
| 611 | } | 649 | slsmg_printf("%c ", folded_sign); |
| 650 | width -= 2; | ||
| 651 | } | ||
| 652 | |||
| 653 | slsmg_printf("%s", s); | ||
| 612 | 654 | ||
| 613 | if (symbol_conf.show_total_period) { | 655 | if (!current_entry || !browser->b.navkeypressed) |
| 614 | slsmg_printf(" %12" PRIu64, entry->period); | 656 | ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); |
| 615 | width -= 13; | 657 | } else { |
| 658 | width -= perf_hpp__format[i].entry(&hpp, entry); | ||
| 659 | slsmg_printf("%s", s); | ||
| 660 | } | ||
| 616 | } | 661 | } |
| 617 | 662 | ||
| 663 | /* The scroll bar isn't being used */ | ||
| 664 | if (!browser->b.navkeypressed) | ||
| 665 | width += 1; | ||
| 666 | |||
| 667 | hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists); | ||
| 618 | slsmg_write_nstring(s, width); | 668 | slsmg_write_nstring(s, width); |
| 619 | ++row; | 669 | ++row; |
| 620 | ++printed; | 670 | ++printed; |
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 26b5b652a8cd..3c16ab50e0f8 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c | |||
| @@ -36,6 +36,57 @@ static void perf_gtk__resize_window(GtkWidget *window) | |||
| 36 | gtk_window_resize(GTK_WINDOW(window), width, height); | 36 | gtk_window_resize(GTK_WINDOW(window), width, height); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static const char *perf_gtk__get_percent_color(double percent) | ||
| 40 | { | ||
| 41 | if (percent >= MIN_RED) | ||
| 42 | return "<span fgcolor='red'>"; | ||
| 43 | if (percent >= MIN_GREEN) | ||
| 44 | return "<span fgcolor='dark green'>"; | ||
| 45 | return NULL; | ||
| 46 | } | ||
| 47 | |||
| 48 | #define HPP__COLOR_FN(_name, _field) \ | ||
| 49 | static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ | ||
| 50 | struct hist_entry *he) \ | ||
| 51 | { \ | ||
| 52 | double percent = 100.0 * he->_field / hpp->total_period; \ | ||
| 53 | const char *markup; \ | ||
| 54 | int ret = 0; \ | ||
| 55 | \ | ||
| 56 | markup = perf_gtk__get_percent_color(percent); \ | ||
| 57 | if (markup) \ | ||
| 58 | ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ | ||
| 59 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%5.2f%%", percent); \ | ||
| 60 | if (markup) \ | ||
| 61 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); \ | ||
| 62 | \ | ||
| 63 | return ret; \ | ||
| 64 | } | ||
| 65 | |||
| 66 | HPP__COLOR_FN(overhead, period) | ||
| 67 | HPP__COLOR_FN(overhead_sys, period_sys) | ||
| 68 | HPP__COLOR_FN(overhead_us, period_us) | ||
| 69 | HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) | ||
| 70 | HPP__COLOR_FN(overhead_guest_us, period_guest_us) | ||
| 71 | |||
| 72 | #undef HPP__COLOR_FN | ||
| 73 | |||
| 74 | void perf_gtk__init_hpp(void) | ||
| 75 | { | ||
| 76 | perf_hpp__init(false, false); | ||
| 77 | |||
| 78 | perf_hpp__format[PERF_HPP__OVERHEAD].color = | ||
| 79 | perf_gtk__hpp_color_overhead; | ||
| 80 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = | ||
| 81 | perf_gtk__hpp_color_overhead_sys; | ||
| 82 | perf_hpp__format[PERF_HPP__OVERHEAD_US].color = | ||
| 83 | perf_gtk__hpp_color_overhead_us; | ||
| 84 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = | ||
| 85 | perf_gtk__hpp_color_overhead_guest_sys; | ||
| 86 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = | ||
| 87 | perf_gtk__hpp_color_overhead_guest_us; | ||
| 88 | } | ||
| 89 | |||
| 39 | static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | 90 | static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) |
| 40 | { | 91 | { |
| 41 | GType col_types[MAX_COLUMNS]; | 92 | GType col_types[MAX_COLUMNS]; |
| @@ -43,15 +94,25 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
| 43 | struct sort_entry *se; | 94 | struct sort_entry *se; |
| 44 | GtkListStore *store; | 95 | GtkListStore *store; |
| 45 | struct rb_node *nd; | 96 | struct rb_node *nd; |
| 46 | u64 total_period; | ||
| 47 | GtkWidget *view; | 97 | GtkWidget *view; |
| 48 | int col_idx; | 98 | int i, col_idx; |
| 49 | int nr_cols; | 99 | int nr_cols; |
| 100 | char s[512]; | ||
| 101 | |||
| 102 | struct perf_hpp hpp = { | ||
| 103 | .buf = s, | ||
| 104 | .size = sizeof(s), | ||
| 105 | .total_period = hists->stats.total_period, | ||
| 106 | }; | ||
| 50 | 107 | ||
| 51 | nr_cols = 0; | 108 | nr_cols = 0; |
| 52 | 109 | ||
| 53 | /* The percentage column */ | 110 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
| 54 | col_types[nr_cols++] = G_TYPE_STRING; | 111 | if (!perf_hpp__format[i].cond) |
| 112 | continue; | ||
| 113 | |||
| 114 | col_types[nr_cols++] = G_TYPE_STRING; | ||
| 115 | } | ||
| 55 | 116 | ||
| 56 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 117 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 57 | if (se->elide) | 118 | if (se->elide) |
| @@ -68,11 +129,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
| 68 | 129 | ||
| 69 | col_idx = 0; | 130 | col_idx = 0; |
| 70 | 131 | ||
| 71 | /* The percentage column */ | 132 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
| 72 | gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), | 133 | if (!perf_hpp__format[i].cond) |
| 73 | -1, "Overhead (%)", | 134 | continue; |
| 74 | renderer, "text", | 135 | |
| 75 | col_idx++, NULL); | 136 | perf_hpp__format[i].header(&hpp); |
| 137 | |||
| 138 | gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), | ||
| 139 | -1, s, | ||
| 140 | renderer, "markup", | ||
| 141 | col_idx++, NULL); | ||
| 142 | } | ||
| 76 | 143 | ||
| 77 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 144 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 78 | if (se->elide) | 145 | if (se->elide) |
| @@ -88,13 +155,9 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
| 88 | 155 | ||
| 89 | g_object_unref(GTK_TREE_MODEL(store)); | 156 | g_object_unref(GTK_TREE_MODEL(store)); |
| 90 | 157 | ||
| 91 | total_period = hists->stats.total_period; | ||
| 92 | |||
| 93 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 158 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
| 94 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 159 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
| 95 | GtkTreeIter iter; | 160 | GtkTreeIter iter; |
| 96 | double percent; | ||
| 97 | char s[512]; | ||
| 98 | 161 | ||
| 99 | if (h->filtered) | 162 | if (h->filtered) |
| 100 | continue; | 163 | continue; |
| @@ -103,11 +166,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
| 103 | 166 | ||
| 104 | col_idx = 0; | 167 | col_idx = 0; |
| 105 | 168 | ||
| 106 | percent = (h->period * 100.0) / total_period; | 169 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
| 170 | if (!perf_hpp__format[i].cond) | ||
| 171 | continue; | ||
| 107 | 172 | ||
| 108 | snprintf(s, ARRAY_SIZE(s), "%.2f", percent); | 173 | if (perf_hpp__format[i].color) |
| 174 | perf_hpp__format[i].color(&hpp, h); | ||
| 175 | else | ||
| 176 | perf_hpp__format[i].entry(&hpp, h); | ||
| 109 | 177 | ||
| 110 | gtk_list_store_set(store, &iter, col_idx++, s, -1); | 178 | gtk_list_store_set(store, &iter, col_idx++, s, -1); |
| 179 | } | ||
| 111 | 180 | ||
| 112 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 181 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 113 | if (se->elide) | 182 | if (se->elide) |
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index 793cb6116ddf..687af0bba187 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h | |||
| @@ -30,6 +30,7 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window); | |||
| 30 | int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); | 30 | int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); |
| 31 | 31 | ||
| 32 | void perf_gtk__init_helpline(void); | 32 | void perf_gtk__init_helpline(void); |
| 33 | void perf_gtk__init_hpp(void); | ||
| 33 | 34 | ||
| 34 | #ifndef HAVE_GTK_INFO_BAR | 35 | #ifndef HAVE_GTK_INFO_BAR |
| 35 | static inline GtkWidget *perf_gtk__setup_info_bar(void) | 36 | static inline GtkWidget *perf_gtk__setup_info_bar(void) |
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index ec1ee26b485a..26429437e19e 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c | |||
| @@ -8,6 +8,7 @@ int perf_gtk__init(void) | |||
| 8 | { | 8 | { |
| 9 | perf_error__register(&perf_gtk_eops); | 9 | perf_error__register(&perf_gtk_eops); |
| 10 | perf_gtk__init_helpline(); | 10 | perf_gtk__init_helpline(); |
| 11 | perf_gtk__init_hpp(); | ||
| 11 | return gtk_init_check(NULL, NULL) ? 0 : -1; | 12 | return gtk_init_check(NULL, NULL) ? 0 : -1; |
| 12 | } | 13 | } |
| 13 | 14 | ||
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c new file mode 100644 index 000000000000..031b349a3f84 --- /dev/null +++ b/tools/perf/ui/hist.c | |||
| @@ -0,0 +1,389 @@ | |||
| 1 | #include <math.h> | ||
| 2 | |||
| 3 | #include "../util/hist.h" | ||
| 4 | #include "../util/util.h" | ||
| 5 | #include "../util/sort.h" | ||
| 6 | |||
| 7 | |||
| 8 | /* hist period print (hpp) functions */ | ||
| 9 | static int hpp__header_overhead(struct perf_hpp *hpp) | ||
| 10 | { | ||
| 11 | const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; | ||
| 12 | |||
| 13 | return scnprintf(hpp->buf, hpp->size, fmt); | ||
| 14 | } | ||
| 15 | |||
| 16 | static int hpp__width_overhead(struct perf_hpp *hpp __used) | ||
| 17 | { | ||
| 18 | return 8; | ||
| 19 | } | ||
| 20 | |||
| 21 | static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 22 | { | ||
| 23 | double percent = 100.0 * he->period / hpp->total_period; | ||
| 24 | |||
| 25 | if (hpp->ptr) { | ||
| 26 | struct hists *old_hists = hpp->ptr; | ||
| 27 | u64 total_period = old_hists->stats.total_period; | ||
| 28 | u64 base_period = he->pair ? he->pair->period : 0; | ||
| 29 | |||
| 30 | if (total_period) | ||
| 31 | percent = 100.0 * base_period / total_period; | ||
| 32 | else | ||
| 33 | percent = 0.0; | ||
| 34 | } | ||
| 35 | |||
| 36 | return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%%", percent); | ||
| 37 | } | ||
| 38 | |||
| 39 | static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 40 | { | ||
| 41 | double percent = 100.0 * he->period / hpp->total_period; | ||
| 42 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%%"; | ||
| 43 | |||
| 44 | if (hpp->ptr) { | ||
| 45 | struct hists *old_hists = hpp->ptr; | ||
| 46 | u64 total_period = old_hists->stats.total_period; | ||
| 47 | u64 base_period = he->pair ? he->pair->period : 0; | ||
| 48 | |||
| 49 | if (total_period) | ||
| 50 | percent = 100.0 * base_period / total_period; | ||
| 51 | else | ||
| 52 | percent = 0.0; | ||
| 53 | } | ||
| 54 | |||
| 55 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
| 56 | } | ||
| 57 | |||
| 58 | static int hpp__header_overhead_sys(struct perf_hpp *hpp) | ||
| 59 | { | ||
| 60 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6s"; | ||
| 61 | |||
| 62 | return scnprintf(hpp->buf, hpp->size, fmt, "sys"); | ||
| 63 | } | ||
| 64 | |||
| 65 | static int hpp__width_overhead_sys(struct perf_hpp *hpp __used) | ||
| 66 | { | ||
| 67 | return 6; | ||
| 68 | } | ||
| 69 | |||
| 70 | static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 71 | { | ||
| 72 | double percent = 100.0 * he->period_sys / hpp->total_period; | ||
| 73 | return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent); | ||
| 74 | } | ||
| 75 | |||
| 76 | static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 77 | { | ||
| 78 | double percent = 100.0 * he->period_sys / hpp->total_period; | ||
| 79 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%5.2f%%"; | ||
| 80 | |||
| 81 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
| 82 | } | ||
| 83 | |||
| 84 | static int hpp__header_overhead_us(struct perf_hpp *hpp) | ||
| 85 | { | ||
| 86 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6s"; | ||
| 87 | |||
| 88 | return scnprintf(hpp->buf, hpp->size, fmt, "user"); | ||
| 89 | } | ||
| 90 | |||
| 91 | static int hpp__width_overhead_us(struct perf_hpp *hpp __used) | ||
| 92 | { | ||
| 93 | return 6; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 97 | { | ||
| 98 | double percent = 100.0 * he->period_us / hpp->total_period; | ||
| 99 | return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent); | ||
| 100 | } | ||
| 101 | |||
| 102 | static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 103 | { | ||
| 104 | double percent = 100.0 * he->period_us / hpp->total_period; | ||
| 105 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%5.2f%%"; | ||
| 106 | |||
| 107 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
| 108 | } | ||
| 109 | |||
| 110 | static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp) | ||
| 111 | { | ||
| 112 | return scnprintf(hpp->buf, hpp->size, "guest sys"); | ||
| 113 | } | ||
| 114 | |||
| 115 | static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __used) | ||
| 116 | { | ||
| 117 | return 9; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, | ||
| 121 | struct hist_entry *he) | ||
| 122 | { | ||
| 123 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; | ||
| 124 | return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent); | ||
| 125 | } | ||
| 126 | |||
| 127 | static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, | ||
| 128 | struct hist_entry *he) | ||
| 129 | { | ||
| 130 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; | ||
| 131 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%% "; | ||
| 132 | |||
| 133 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
| 134 | } | ||
| 135 | |||
| 136 | static int hpp__header_overhead_guest_us(struct perf_hpp *hpp) | ||
| 137 | { | ||
| 138 | return scnprintf(hpp->buf, hpp->size, "guest usr"); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __used) | ||
| 142 | { | ||
| 143 | return 9; | ||
| 144 | } | ||
| 145 | |||
| 146 | static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, | ||
| 147 | struct hist_entry *he) | ||
| 148 | { | ||
| 149 | double percent = 100.0 * he->period_guest_us / hpp->total_period; | ||
| 150 | return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent); | ||
| 151 | } | ||
| 152 | |||
| 153 | static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, | ||
| 154 | struct hist_entry *he) | ||
| 155 | { | ||
| 156 | double percent = 100.0 * he->period_guest_us / hpp->total_period; | ||
| 157 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%% "; | ||
| 158 | |||
| 159 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
| 160 | } | ||
| 161 | |||
| 162 | static int hpp__header_samples(struct perf_hpp *hpp) | ||
| 163 | { | ||
| 164 | const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; | ||
| 165 | |||
| 166 | return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); | ||
| 167 | } | ||
| 168 | |||
| 169 | static int hpp__width_samples(struct perf_hpp *hpp __used) | ||
| 170 | { | ||
| 171 | return 11; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 175 | { | ||
| 176 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; | ||
| 177 | |||
| 178 | return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); | ||
| 179 | } | ||
| 180 | |||
| 181 | static int hpp__header_period(struct perf_hpp *hpp) | ||
| 182 | { | ||
| 183 | const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; | ||
| 184 | |||
| 185 | return scnprintf(hpp->buf, hpp->size, fmt, "Period"); | ||
| 186 | } | ||
| 187 | |||
| 188 | static int hpp__width_period(struct perf_hpp *hpp __used) | ||
| 189 | { | ||
| 190 | return 12; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 194 | { | ||
| 195 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; | ||
| 196 | |||
| 197 | return scnprintf(hpp->buf, hpp->size, fmt, he->period); | ||
| 198 | } | ||
| 199 | |||
| 200 | static int hpp__header_delta(struct perf_hpp *hpp) | ||
| 201 | { | ||
| 202 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; | ||
| 203 | |||
| 204 | return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); | ||
| 205 | } | ||
| 206 | |||
| 207 | static int hpp__width_delta(struct perf_hpp *hpp __used) | ||
| 208 | { | ||
| 209 | return 7; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) | ||
| 213 | { | ||
| 214 | struct hists *pair_hists = hpp->ptr; | ||
| 215 | u64 old_total, new_total; | ||
| 216 | double old_percent = 0, new_percent = 0; | ||
| 217 | double diff; | ||
| 218 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; | ||
| 219 | char buf[32] = " "; | ||
| 220 | |||
| 221 | old_total = pair_hists->stats.total_period; | ||
| 222 | if (old_total > 0 && he->pair) | ||
| 223 | old_percent = 100.0 * he->pair->period / old_total; | ||
| 224 | |||
| 225 | new_total = hpp->total_period; | ||
| 226 | if (new_total > 0) | ||
| 227 | new_percent = 100.0 * he->period / new_total; | ||
| 228 | |||
| 229 | diff = new_percent - old_percent; | ||
| 230 | if (fabs(diff) >= 0.01) | ||
| 231 | scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); | ||
| 232 | |||
| 233 | return scnprintf(hpp->buf, hpp->size, fmt, buf); | ||
| 234 | } | ||
| 235 | |||
| 236 | static int hpp__header_displ(struct perf_hpp *hpp) | ||
| 237 | { | ||
| 238 | return scnprintf(hpp->buf, hpp->size, "Displ."); | ||
| 239 | } | ||
| 240 | |||
| 241 | static int hpp__width_displ(struct perf_hpp *hpp __used) | ||
| 242 | { | ||
| 243 | return 6; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int hpp__entry_displ(struct perf_hpp *hpp, struct hist_entry *he __used) | ||
| 247 | { | ||
| 248 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; | ||
| 249 | char buf[32] = " "; | ||
| 250 | |||
| 251 | if (hpp->displacement) | ||
| 252 | scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); | ||
| 253 | |||
| 254 | return scnprintf(hpp->buf, hpp->size, fmt, buf); | ||
| 255 | } | ||
| 256 | |||
| 257 | #define HPP__COLOR_PRINT_FNS(_name) \ | ||
| 258 | .header = hpp__header_ ## _name, \ | ||
| 259 | .width = hpp__width_ ## _name, \ | ||
| 260 | .color = hpp__color_ ## _name, \ | ||
| 261 | .entry = hpp__entry_ ## _name | ||
| 262 | |||
| 263 | #define HPP__PRINT_FNS(_name) \ | ||
| 264 | .header = hpp__header_ ## _name, \ | ||
| 265 | .width = hpp__width_ ## _name, \ | ||
| 266 | .entry = hpp__entry_ ## _name | ||
| 267 | |||
| 268 | struct perf_hpp_fmt perf_hpp__format[] = { | ||
| 269 | { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, | ||
| 270 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, | ||
| 271 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, | ||
| 272 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) }, | ||
| 273 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) }, | ||
| 274 | { .cond = false, HPP__PRINT_FNS(samples) }, | ||
| 275 | { .cond = false, HPP__PRINT_FNS(period) }, | ||
| 276 | { .cond = false, HPP__PRINT_FNS(delta) }, | ||
| 277 | { .cond = false, HPP__PRINT_FNS(displ) } | ||
| 278 | }; | ||
| 279 | |||
| 280 | #undef HPP__COLOR_PRINT_FNS | ||
| 281 | #undef HPP__PRINT_FNS | ||
| 282 | |||
| 283 | void perf_hpp__init(bool need_pair, bool show_displacement) | ||
| 284 | { | ||
| 285 | if (symbol_conf.show_cpu_utilization) { | ||
| 286 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; | ||
| 287 | perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true; | ||
| 288 | |||
| 289 | if (perf_guest) { | ||
| 290 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true; | ||
| 291 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | if (symbol_conf.show_nr_samples) | ||
| 296 | perf_hpp__format[PERF_HPP__SAMPLES].cond = true; | ||
| 297 | |||
| 298 | if (symbol_conf.show_total_period) | ||
| 299 | perf_hpp__format[PERF_HPP__PERIOD].cond = true; | ||
| 300 | |||
| 301 | if (need_pair) { | ||
| 302 | perf_hpp__format[PERF_HPP__DELTA].cond = true; | ||
| 303 | |||
| 304 | if (show_displacement) | ||
| 305 | perf_hpp__format[PERF_HPP__DISPL].cond = true; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | static inline void advance_hpp(struct perf_hpp *hpp, int inc) | ||
| 310 | { | ||
| 311 | hpp->buf += inc; | ||
| 312 | hpp->size -= inc; | ||
| 313 | } | ||
| 314 | |||
| 315 | int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | ||
| 316 | bool color) | ||
| 317 | { | ||
| 318 | const char *sep = symbol_conf.field_sep; | ||
| 319 | char *start = hpp->buf; | ||
| 320 | int i, ret; | ||
| 321 | |||
| 322 | if (symbol_conf.exclude_other && !he->parent) | ||
| 323 | return 0; | ||
| 324 | |||
| 325 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { | ||
| 326 | if (!perf_hpp__format[i].cond) | ||
| 327 | continue; | ||
| 328 | |||
| 329 | if (!sep || i > 0) { | ||
| 330 | ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); | ||
| 331 | advance_hpp(hpp, ret); | ||
| 332 | } | ||
| 333 | |||
| 334 | if (color && perf_hpp__format[i].color) | ||
| 335 | ret = perf_hpp__format[i].color(hpp, he); | ||
| 336 | else | ||
| 337 | ret = perf_hpp__format[i].entry(hpp, he); | ||
| 338 | |||
| 339 | advance_hpp(hpp, ret); | ||
| 340 | } | ||
| 341 | |||
| 342 | return hpp->buf - start; | ||
| 343 | } | ||
| 344 | |||
| 345 | int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, | ||
| 346 | struct hists *hists) | ||
| 347 | { | ||
| 348 | const char *sep = symbol_conf.field_sep; | ||
| 349 | struct sort_entry *se; | ||
| 350 | int ret = 0; | ||
| 351 | |||
| 352 | list_for_each_entry(se, &hist_entry__sort_list, list) { | ||
| 353 | if (se->elide) | ||
| 354 | continue; | ||
| 355 | |||
| 356 | ret += scnprintf(s + ret, size - ret, "%s", sep ?: " "); | ||
| 357 | ret += se->se_snprintf(he, s + ret, size - ret, | ||
| 358 | hists__col_len(hists, se->se_width_idx)); | ||
| 359 | } | ||
| 360 | |||
| 361 | return ret; | ||
| 362 | } | ||
| 363 | |||
| 364 | /* | ||
| 365 | * See hists__fprintf to match the column widths | ||
| 366 | */ | ||
| 367 | unsigned int hists__sort_list_width(struct hists *hists) | ||
| 368 | { | ||
| 369 | struct sort_entry *se; | ||
| 370 | int i, ret = 0; | ||
| 371 | |||
| 372 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { | ||
| 373 | if (!perf_hpp__format[i].cond) | ||
| 374 | continue; | ||
| 375 | if (i) | ||
| 376 | ret += 2; | ||
| 377 | |||
| 378 | ret += perf_hpp__format[i].width(NULL); | ||
| 379 | } | ||
| 380 | |||
| 381 | list_for_each_entry(se, &hist_entry__sort_list, list) | ||
| 382 | if (!se->elide) | ||
| 383 | ret += 2 + hists__col_len(hists, se->se_width_idx); | ||
| 384 | |||
| 385 | if (verbose) /* Addr + origin */ | ||
| 386 | ret += 3 + BITS_PER_LONG / 4; | ||
| 387 | |||
| 388 | return ret; | ||
| 389 | } | ||
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index c7820e569660..bd7d460f844c 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | #include <pthread.h> | 1 | #include <pthread.h> |
| 2 | 2 | ||
| 3 | #include "../cache.h" | 3 | #include "../util/cache.h" |
| 4 | #include "../debug.h" | 4 | #include "../util/debug.h" |
| 5 | 5 | #include "../util/hist.h" | |
| 6 | 6 | ||
| 7 | pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; | 7 | pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; |
| 8 | 8 | ||
| @@ -29,6 +29,8 @@ void setup_browser(bool fallback_to_pager) | |||
| 29 | use_browser = 0; | 29 | use_browser = 0; |
| 30 | if (fallback_to_pager) | 30 | if (fallback_to_pager) |
| 31 | setup_pager(); | 31 | setup_pager(); |
| 32 | |||
| 33 | perf_hpp__init(false, false); | ||
| 32 | break; | 34 | break; |
| 33 | } | 35 | } |
| 34 | } | 36 | } |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 9bf7e9e5a72e..882461a42830 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | #include <stdio.h> | 1 | #include <stdio.h> |
| 2 | #include <math.h> | ||
| 3 | 2 | ||
| 4 | #include "../../util/util.h" | 3 | #include "../../util/util.h" |
| 5 | #include "../../util/hist.h" | 4 | #include "../../util/hist.h" |
| @@ -291,138 +290,6 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he, | |||
| 291 | return 0; | 290 | return 0; |
| 292 | } | 291 | } |
| 293 | 292 | ||
| 294 | static int hist_entry__period_snprintf(struct hist_entry *he, char *s, | ||
| 295 | size_t size, struct hists *pair_hists, | ||
| 296 | bool show_displacement, long displacement, | ||
| 297 | bool color, u64 total_period) | ||
| 298 | { | ||
| 299 | u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; | ||
| 300 | u64 nr_events; | ||
| 301 | const char *sep = symbol_conf.field_sep; | ||
| 302 | int ret; | ||
| 303 | |||
| 304 | if (symbol_conf.exclude_other && !he->parent) | ||
| 305 | return 0; | ||
| 306 | |||
| 307 | if (pair_hists) { | ||
| 308 | period = he->pair ? he->pair->period : 0; | ||
| 309 | nr_events = he->pair ? he->pair->nr_events : 0; | ||
| 310 | total = pair_hists->stats.total_period; | ||
| 311 | period_sys = he->pair ? he->pair->period_sys : 0; | ||
| 312 | period_us = he->pair ? he->pair->period_us : 0; | ||
| 313 | period_guest_sys = he->pair ? he->pair->period_guest_sys : 0; | ||
| 314 | period_guest_us = he->pair ? he->pair->period_guest_us : 0; | ||
| 315 | } else { | ||
| 316 | period = he->period; | ||
| 317 | nr_events = he->nr_events; | ||
| 318 | total = total_period; | ||
| 319 | period_sys = he->period_sys; | ||
| 320 | period_us = he->period_us; | ||
| 321 | period_guest_sys = he->period_guest_sys; | ||
| 322 | period_guest_us = he->period_guest_us; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (total) { | ||
| 326 | if (color) | ||
| 327 | ret = percent_color_snprintf(s, size, | ||
| 328 | sep ? "%.2f" : " %6.2f%%", | ||
| 329 | (period * 100.0) / total); | ||
| 330 | else | ||
| 331 | ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%", | ||
| 332 | (period * 100.0) / total); | ||
| 333 | if (symbol_conf.show_cpu_utilization) { | ||
| 334 | ret += percent_color_snprintf(s + ret, size - ret, | ||
| 335 | sep ? "%.2f" : " %6.2f%%", | ||
| 336 | (period_sys * 100.0) / total); | ||
| 337 | ret += percent_color_snprintf(s + ret, size - ret, | ||
| 338 | sep ? "%.2f" : " %6.2f%%", | ||
| 339 | (period_us * 100.0) / total); | ||
| 340 | if (perf_guest) { | ||
| 341 | ret += percent_color_snprintf(s + ret, | ||
| 342 | size - ret, | ||
| 343 | sep ? "%.2f" : " %6.2f%%", | ||
| 344 | (period_guest_sys * 100.0) / | ||
| 345 | total); | ||
| 346 | ret += percent_color_snprintf(s + ret, | ||
| 347 | size - ret, | ||
| 348 | sep ? "%.2f" : " %6.2f%%", | ||
| 349 | (period_guest_us * 100.0) / | ||
| 350 | total); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | } else | ||
| 354 | ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period); | ||
| 355 | |||
| 356 | if (symbol_conf.show_nr_samples) { | ||
| 357 | if (sep) | ||
| 358 | ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events); | ||
| 359 | else | ||
| 360 | ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events); | ||
| 361 | } | ||
| 362 | |||
| 363 | if (symbol_conf.show_total_period) { | ||
| 364 | if (sep) | ||
| 365 | ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); | ||
| 366 | else | ||
| 367 | ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period); | ||
| 368 | } | ||
| 369 | |||
| 370 | if (pair_hists) { | ||
| 371 | char bf[32]; | ||
| 372 | double old_percent = 0, new_percent = 0, diff; | ||
| 373 | |||
| 374 | if (total > 0) | ||
| 375 | old_percent = (period * 100.0) / total; | ||
| 376 | if (total_period > 0) | ||
| 377 | new_percent = (he->period * 100.0) / total_period; | ||
| 378 | |||
| 379 | diff = new_percent - old_percent; | ||
| 380 | |||
| 381 | if (fabs(diff) >= 0.01) | ||
| 382 | scnprintf(bf, sizeof(bf), "%+4.2F%%", diff); | ||
| 383 | else | ||
| 384 | scnprintf(bf, sizeof(bf), " "); | ||
| 385 | |||
| 386 | if (sep) | ||
| 387 | ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf); | ||
| 388 | else | ||
| 389 | ret += scnprintf(s + ret, size - ret, "%11.11s", bf); | ||
| 390 | |||
| 391 | if (show_displacement) { | ||
| 392 | if (displacement) | ||
| 393 | scnprintf(bf, sizeof(bf), "%+4ld", displacement); | ||
| 394 | else | ||
| 395 | scnprintf(bf, sizeof(bf), " "); | ||
| 396 | |||
| 397 | if (sep) | ||
| 398 | ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf); | ||
| 399 | else | ||
| 400 | ret += scnprintf(s + ret, size - ret, "%6.6s", bf); | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | return ret; | ||
| 405 | } | ||
| 406 | |||
| 407 | int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, | ||
| 408 | struct hists *hists) | ||
| 409 | { | ||
| 410 | const char *sep = symbol_conf.field_sep; | ||
| 411 | struct sort_entry *se; | ||
| 412 | int ret = 0; | ||
| 413 | |||
| 414 | list_for_each_entry(se, &hist_entry__sort_list, list) { | ||
| 415 | if (se->elide) | ||
| 416 | continue; | ||
| 417 | |||
| 418 | ret += scnprintf(s + ret, size - ret, "%s", sep ?: " "); | ||
| 419 | ret += se->se_snprintf(he, s + ret, size - ret, | ||
| 420 | hists__col_len(hists, se->se_width_idx)); | ||
| 421 | } | ||
| 422 | |||
| 423 | return ret; | ||
| 424 | } | ||
| 425 | |||
| 426 | static size_t hist_entry__callchain_fprintf(struct hist_entry *he, | 293 | static size_t hist_entry__callchain_fprintf(struct hist_entry *he, |
| 427 | struct hists *hists, | 294 | struct hists *hists, |
| 428 | u64 total_period, FILE *fp) | 295 | u64 total_period, FILE *fp) |
| @@ -441,18 +308,23 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he, | |||
| 441 | 308 | ||
| 442 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, | 309 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, |
| 443 | struct hists *hists, struct hists *pair_hists, | 310 | struct hists *hists, struct hists *pair_hists, |
| 444 | bool show_displacement, long displacement, | 311 | long displacement, u64 total_period, FILE *fp) |
| 445 | u64 total_period, FILE *fp) | ||
| 446 | { | 312 | { |
| 447 | char bf[512]; | 313 | char bf[512]; |
| 448 | int ret; | 314 | int ret; |
| 315 | struct perf_hpp hpp = { | ||
| 316 | .buf = bf, | ||
| 317 | .size = size, | ||
| 318 | .total_period = total_period, | ||
| 319 | .displacement = displacement, | ||
| 320 | .ptr = pair_hists, | ||
| 321 | }; | ||
| 322 | bool color = !symbol_conf.field_sep; | ||
| 449 | 323 | ||
| 450 | if (size == 0 || size > sizeof(bf)) | 324 | if (size == 0 || size > sizeof(bf)) |
| 451 | size = sizeof(bf); | 325 | size = hpp.size = sizeof(bf); |
| 452 | 326 | ||
| 453 | ret = hist_entry__period_snprintf(he, bf, size, pair_hists, | 327 | ret = hist_entry__period_snprintf(&hpp, he, color); |
| 454 | show_displacement, displacement, | ||
| 455 | true, total_period); | ||
| 456 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); | 328 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); |
| 457 | 329 | ||
| 458 | ret = fprintf(fp, "%s\n", bf); | 330 | ret = fprintf(fp, "%s\n", bf); |
| @@ -477,59 +349,29 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, | |||
| 477 | unsigned int width; | 349 | unsigned int width; |
| 478 | const char *sep = symbol_conf.field_sep; | 350 | const char *sep = symbol_conf.field_sep; |
| 479 | const char *col_width = symbol_conf.col_width_list_str; | 351 | const char *col_width = symbol_conf.col_width_list_str; |
| 480 | int nr_rows = 0; | 352 | int idx, nr_rows = 0; |
| 353 | char bf[64]; | ||
| 354 | struct perf_hpp dummy_hpp = { | ||
| 355 | .buf = bf, | ||
| 356 | .size = sizeof(bf), | ||
| 357 | .ptr = pair, | ||
| 358 | }; | ||
| 481 | 359 | ||
| 482 | init_rem_hits(); | 360 | init_rem_hits(); |
| 483 | 361 | ||
| 484 | if (!show_header) | 362 | if (!show_header) |
| 485 | goto print_entries; | 363 | goto print_entries; |
| 486 | 364 | ||
| 487 | fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); | 365 | fprintf(fp, "# "); |
| 488 | 366 | for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { | |
| 489 | if (symbol_conf.show_cpu_utilization) { | 367 | if (!perf_hpp__format[idx].cond) |
| 490 | if (sep) { | 368 | continue; |
| 491 | ret += fprintf(fp, "%csys", *sep); | ||
| 492 | ret += fprintf(fp, "%cus", *sep); | ||
| 493 | if (perf_guest) { | ||
| 494 | ret += fprintf(fp, "%cguest sys", *sep); | ||
| 495 | ret += fprintf(fp, "%cguest us", *sep); | ||
| 496 | } | ||
| 497 | } else { | ||
| 498 | ret += fprintf(fp, " sys "); | ||
| 499 | ret += fprintf(fp, " us "); | ||
| 500 | if (perf_guest) { | ||
| 501 | ret += fprintf(fp, " guest sys "); | ||
| 502 | ret += fprintf(fp, " guest us "); | ||
| 503 | } | ||
| 504 | } | ||
| 505 | } | ||
| 506 | |||
| 507 | if (symbol_conf.show_nr_samples) { | ||
| 508 | if (sep) | ||
| 509 | fprintf(fp, "%cSamples", *sep); | ||
| 510 | else | ||
| 511 | fputs(" Samples ", fp); | ||
| 512 | } | ||
| 513 | |||
| 514 | if (symbol_conf.show_total_period) { | ||
| 515 | if (sep) | ||
| 516 | ret += fprintf(fp, "%cPeriod", *sep); | ||
| 517 | else | ||
| 518 | ret += fprintf(fp, " Period "); | ||
| 519 | } | ||
| 520 | 369 | ||
| 521 | if (pair) { | 370 | if (idx) |
| 522 | if (sep) | 371 | fprintf(fp, "%s", sep ?: " "); |
| 523 | ret += fprintf(fp, "%cDelta", *sep); | ||
| 524 | else | ||
| 525 | ret += fprintf(fp, " Delta "); | ||
| 526 | 372 | ||
| 527 | if (show_displacement) { | 373 | perf_hpp__format[idx].header(&dummy_hpp); |
| 528 | if (sep) | 374 | fprintf(fp, "%s", bf); |
| 529 | ret += fprintf(fp, "%cDisplacement", *sep); | ||
| 530 | else | ||
| 531 | ret += fprintf(fp, " Displ"); | ||
| 532 | } | ||
| 533 | } | 375 | } |
| 534 | 376 | ||
| 535 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 377 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| @@ -561,18 +403,21 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, | |||
| 561 | if (sep) | 403 | if (sep) |
| 562 | goto print_entries; | 404 | goto print_entries; |
| 563 | 405 | ||
| 564 | fprintf(fp, "# ........"); | 406 | fprintf(fp, "# "); |
| 565 | if (symbol_conf.show_cpu_utilization) | 407 | for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { |
| 566 | fprintf(fp, " ....... ......."); | 408 | unsigned int i; |
| 567 | if (symbol_conf.show_nr_samples) | 409 | |
| 568 | fprintf(fp, " .........."); | 410 | if (!perf_hpp__format[idx].cond) |
| 569 | if (symbol_conf.show_total_period) | 411 | continue; |
| 570 | fprintf(fp, " ............"); | 412 | |
| 571 | if (pair) { | 413 | if (idx) |
| 572 | fprintf(fp, " .........."); | 414 | fprintf(fp, "%s", sep ?: " "); |
| 573 | if (show_displacement) | 415 | |
| 574 | fprintf(fp, " ....."); | 416 | width = perf_hpp__format[idx].width(&dummy_hpp); |
| 417 | for (i = 0; i < width; i++) | ||
| 418 | fprintf(fp, "."); | ||
| 575 | } | 419 | } |
| 420 | |||
| 576 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 421 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 577 | unsigned int i; | 422 | unsigned int i; |
| 578 | 423 | ||
| @@ -612,8 +457,8 @@ print_entries: | |||
| 612 | displacement = 0; | 457 | displacement = 0; |
| 613 | ++position; | 458 | ++position; |
| 614 | } | 459 | } |
| 615 | ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, | 460 | ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement, |
| 616 | displacement, total_period, fp); | 461 | total_period, fp); |
| 617 | 462 | ||
| 618 | if (max_rows && ++nr_rows >= max_rows) | 463 | if (max_rows && ++nr_rows >= max_rows) |
| 619 | goto out; | 464 | goto out; |
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 4c936e09931c..4dc0887c04f1 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c | |||
| @@ -15,6 +15,8 @@ static volatile int ui__need_resize; | |||
| 15 | 15 | ||
| 16 | extern struct perf_error_ops perf_tui_eops; | 16 | extern struct perf_error_ops perf_tui_eops; |
| 17 | 17 | ||
| 18 | extern void hist_browser__init_hpp(void); | ||
| 19 | |||
| 18 | void ui__refresh_dimensions(bool force) | 20 | void ui__refresh_dimensions(bool force) |
| 19 | { | 21 | { |
| 20 | if (force || ui__need_resize) { | 22 | if (force || ui__need_resize) { |
| @@ -124,6 +126,8 @@ int ui__init(void) | |||
| 124 | signal(SIGTERM, ui__signal); | 126 | signal(SIGTERM, ui__signal); |
| 125 | 127 | ||
| 126 | perf_error__register(&perf_tui_eops); | 128 | perf_error__register(&perf_tui_eops); |
| 129 | |||
| 130 | hist_browser__init_hpp(); | ||
| 127 | out: | 131 | out: |
| 128 | return err; | 132 | return err; |
| 129 | } | 133 | } |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 51ef69c9841d..04eafd3939df 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
| @@ -984,7 +984,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
| 984 | int context) | 984 | int context) |
| 985 | { | 985 | { |
| 986 | struct dso *dso = map->dso; | 986 | struct dso *dso = map->dso; |
| 987 | const char *filename = dso->long_name, *d_filename; | 987 | char *filename; |
| 988 | const char *d_filename; | ||
| 988 | struct annotation *notes = symbol__annotation(sym); | 989 | struct annotation *notes = symbol__annotation(sym); |
| 989 | struct disasm_line *pos, *queue = NULL; | 990 | struct disasm_line *pos, *queue = NULL; |
| 990 | u64 start = map__rip_2objdump(map, sym->start); | 991 | u64 start = map__rip_2objdump(map, sym->start); |
| @@ -992,6 +993,10 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
| 992 | int more = 0; | 993 | int more = 0; |
| 993 | u64 len; | 994 | u64 len; |
| 994 | 995 | ||
| 996 | filename = strdup(dso->long_name); | ||
| 997 | if (!filename) | ||
| 998 | return -ENOMEM; | ||
| 999 | |||
| 995 | if (full_paths) | 1000 | if (full_paths) |
| 996 | d_filename = filename; | 1001 | d_filename = filename; |
| 997 | else | 1002 | else |
| @@ -1042,6 +1047,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
| 1042 | } | 1047 | } |
| 1043 | } | 1048 | } |
| 1044 | 1049 | ||
| 1050 | free(filename); | ||
| 1051 | |||
| 1045 | return more; | 1052 | return more; |
| 1046 | } | 1053 | } |
| 1047 | 1054 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b1817f15bb87..0ba65ad07cd1 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -563,39 +563,6 @@ void hists__output_resort_threaded(struct hists *hists) | |||
| 563 | return __hists__output_resort(hists, true); | 563 | return __hists__output_resort(hists, true); |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | /* | ||
| 567 | * See hists__fprintf to match the column widths | ||
| 568 | */ | ||
| 569 | unsigned int hists__sort_list_width(struct hists *hists) | ||
| 570 | { | ||
| 571 | struct sort_entry *se; | ||
| 572 | int ret = 9; /* total % */ | ||
| 573 | |||
| 574 | if (symbol_conf.show_cpu_utilization) { | ||
| 575 | ret += 7; /* count_sys % */ | ||
| 576 | ret += 6; /* count_us % */ | ||
| 577 | if (perf_guest) { | ||
| 578 | ret += 13; /* count_guest_sys % */ | ||
| 579 | ret += 12; /* count_guest_us % */ | ||
| 580 | } | ||
| 581 | } | ||
| 582 | |||
| 583 | if (symbol_conf.show_nr_samples) | ||
| 584 | ret += 11; | ||
| 585 | |||
| 586 | if (symbol_conf.show_total_period) | ||
| 587 | ret += 13; | ||
| 588 | |||
| 589 | list_for_each_entry(se, &hist_entry__sort_list, list) | ||
| 590 | if (!se->elide) | ||
| 591 | ret += 2 + hists__col_len(hists, se->se_width_idx); | ||
| 592 | |||
| 593 | if (verbose) /* Addr + origin */ | ||
| 594 | ret += 3 + BITS_PER_LONG / 4; | ||
| 595 | |||
| 596 | return ret; | ||
| 597 | } | ||
| 598 | |||
| 599 | static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, | 566 | static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, |
| 600 | enum hist_filter filter) | 567 | enum hist_filter filter) |
| 601 | { | 568 | { |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 2e650ffb7d23..4146f51124f0 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -115,6 +115,43 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); | |||
| 115 | void hists__reset_col_len(struct hists *hists); | 115 | void hists__reset_col_len(struct hists *hists); |
| 116 | void hists__calc_col_len(struct hists *hists, struct hist_entry *he); | 116 | void hists__calc_col_len(struct hists *hists, struct hist_entry *he); |
| 117 | 117 | ||
| 118 | struct perf_hpp { | ||
| 119 | char *buf; | ||
| 120 | size_t size; | ||
| 121 | u64 total_period; | ||
| 122 | const char *sep; | ||
| 123 | long displacement; | ||
| 124 | void *ptr; | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct perf_hpp_fmt { | ||
| 128 | bool cond; | ||
| 129 | int (*header)(struct perf_hpp *hpp); | ||
| 130 | int (*width)(struct perf_hpp *hpp); | ||
| 131 | int (*color)(struct perf_hpp *hpp, struct hist_entry *he); | ||
| 132 | int (*entry)(struct perf_hpp *hpp, struct hist_entry *he); | ||
| 133 | }; | ||
| 134 | |||
| 135 | extern struct perf_hpp_fmt perf_hpp__format[]; | ||
| 136 | |||
| 137 | enum { | ||
| 138 | PERF_HPP__OVERHEAD, | ||
| 139 | PERF_HPP__OVERHEAD_SYS, | ||
| 140 | PERF_HPP__OVERHEAD_US, | ||
| 141 | PERF_HPP__OVERHEAD_GUEST_SYS, | ||
| 142 | PERF_HPP__OVERHEAD_GUEST_US, | ||
| 143 | PERF_HPP__SAMPLES, | ||
| 144 | PERF_HPP__PERIOD, | ||
| 145 | PERF_HPP__DELTA, | ||
| 146 | PERF_HPP__DISPL, | ||
| 147 | |||
| 148 | PERF_HPP__MAX_INDEX | ||
| 149 | }; | ||
| 150 | |||
| 151 | void perf_hpp__init(bool need_pair, bool show_displacement); | ||
| 152 | int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | ||
| 153 | bool color); | ||
| 154 | |||
| 118 | struct perf_evlist; | 155 | struct perf_evlist; |
| 119 | 156 | ||
| 120 | #ifdef NO_NEWT_SUPPORT | 157 | #ifdef NO_NEWT_SUPPORT |
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index b6842c1d02a8..4af9a10cc2d2 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h | |||
| @@ -47,8 +47,12 @@ | |||
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
| 49 | #ifndef BUG_ON | 49 | #ifndef BUG_ON |
| 50 | #ifdef NDEBUG | ||
| 51 | #define BUG_ON(cond) do { if (cond) {} } while (0) | ||
| 52 | #else | ||
| 50 | #define BUG_ON(cond) assert(!(cond)) | 53 | #define BUG_ON(cond) assert(!(cond)) |
| 51 | #endif | 54 | #endif |
| 55 | #endif | ||
| 52 | 56 | ||
| 53 | /* | 57 | /* |
| 54 | * Both need more care to handle endianness | 58 | * Both need more care to handle endianness |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 0dda25d82d06..e8c72de0f70c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -2307,10 +2307,17 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
| 2307 | function = NULL; | 2307 | function = NULL; |
| 2308 | } | 2308 | } |
| 2309 | if (!pev->group) { | 2309 | if (!pev->group) { |
| 2310 | char *ptr1, *ptr2; | 2310 | char *ptr1, *ptr2, *exec_copy; |
| 2311 | 2311 | ||
| 2312 | pev->group = zalloc(sizeof(char *) * 64); | 2312 | pev->group = zalloc(sizeof(char *) * 64); |
| 2313 | ptr1 = strdup(basename(exec)); | 2313 | exec_copy = strdup(exec); |
| 2314 | if (!exec_copy) { | ||
| 2315 | ret = -ENOMEM; | ||
| 2316 | pr_warning("Failed to copy exec string.\n"); | ||
| 2317 | goto out; | ||
| 2318 | } | ||
| 2319 | |||
| 2320 | ptr1 = strdup(basename(exec_copy)); | ||
| 2314 | if (ptr1) { | 2321 | if (ptr1) { |
| 2315 | ptr2 = strpbrk(ptr1, "-._"); | 2322 | ptr2 = strpbrk(ptr1, "-._"); |
| 2316 | if (ptr2) | 2323 | if (ptr2) |
| @@ -2319,6 +2326,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
| 2319 | ptr1); | 2326 | ptr1); |
| 2320 | free(ptr1); | 2327 | free(ptr1); |
| 2321 | } | 2328 | } |
| 2329 | free(exec_copy); | ||
| 2322 | } | 2330 | } |
| 2323 | free(pp->function); | 2331 | free(pp->function); |
| 2324 | pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); | 2332 | pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index d3b330cbc3e0..41a15dac4120 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -10,9 +10,7 @@ | |||
| 10 | #include <linux/rbtree.h> | 10 | #include <linux/rbtree.h> |
| 11 | #include <stdio.h> | 11 | #include <stdio.h> |
| 12 | #include <byteswap.h> | 12 | #include <byteswap.h> |
| 13 | #if defined(__BIONIC__) | ||
| 14 | #include <libgen.h> | 13 | #include <libgen.h> |
| 15 | #endif | ||
| 16 | 14 | ||
| 17 | #ifndef NO_LIBELF_SUPPORT | 15 | #ifndef NO_LIBELF_SUPPORT |
| 18 | #include <libelf.h> | 16 | #include <libelf.h> |
