diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-08-06 03:00:32 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-08-06 03:00:32 -0400 |
commit | e66b688c6456e6a607a1636e228fe0395d6c7214 (patch) | |
tree | bcdd5a9d23d78d91419b3b61de76a5b9fb955008 /tools | |
parent | a7c55cbee0c1bae9bf5a15a08300e91d88706e45 (diff) | |
parent | 71e7cf3a37ba6189fa7215555e8e760b400fc23b (diff) |
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-report.c | 31 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 19 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 3 | ||||
-rw-r--r-- | tools/perf/util/newt.c | 242 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 1 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 6 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 30 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
9 files changed, 297 insertions, 40 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 2f4b92925b26..55fc1f46892a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -348,7 +348,18 @@ static int __cmd_report(void) | |||
348 | hists__tty_browse_tree(&session->hists_tree, help); | 348 | hists__tty_browse_tree(&session->hists_tree, help); |
349 | 349 | ||
350 | out_delete: | 350 | out_delete: |
351 | perf_session__delete(session); | 351 | /* |
352 | * Speed up the exit process, for large files this can | ||
353 | * take quite a while. | ||
354 | * | ||
355 | * XXX Enable this when using valgrind or if we ever | ||
356 | * librarize this command. | ||
357 | * | ||
358 | * Also experiment with obstacks to see how much speed | ||
359 | * up we'll get here. | ||
360 | * | ||
361 | * perf_session__delete(session); | ||
362 | */ | ||
352 | return ret; | 363 | return ret; |
353 | } | 364 | } |
354 | 365 | ||
@@ -478,8 +489,24 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
478 | * so don't allocate extra space that won't be used in the stdio | 489 | * so don't allocate extra space that won't be used in the stdio |
479 | * implementation. | 490 | * implementation. |
480 | */ | 491 | */ |
481 | if (use_browser > 0) | 492 | if (use_browser > 0) { |
482 | symbol_conf.priv_size = sizeof(struct sym_priv); | 493 | symbol_conf.priv_size = sizeof(struct sym_priv); |
494 | /* | ||
495 | * For searching by name on the "Browse map details". | ||
496 | * providing it only in verbose mode not to bloat too | ||
497 | * much struct symbol. | ||
498 | */ | ||
499 | if (verbose) { | ||
500 | /* | ||
501 | * XXX: Need to provide a less kludgy way to ask for | ||
502 | * more space per symbol, the u32 is for the index on | ||
503 | * the ui browser. | ||
504 | * See symbol__browser_index. | ||
505 | */ | ||
506 | symbol_conf.priv_size += sizeof(u32); | ||
507 | symbol_conf.sort_by_name = true; | ||
508 | } | ||
509 | } | ||
483 | 510 | ||
484 | if (symbol__init() < 0) | 511 | if (symbol__init() < 0) |
485 | return -1; | 512 | return -1; |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 5161619d4714..9bcc38f0b706 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -455,8 +455,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) | |||
455 | if (p->current->state != TYPE_NONE) | 455 | if (p->current->state != TYPE_NONE) |
456 | pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp); | 456 | pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp); |
457 | 457 | ||
458 | p->current->state_since = timestamp; | 458 | p->current->state_since = timestamp; |
459 | p->current->state = TYPE_RUNNING; | 459 | p->current->state = TYPE_RUNNING; |
460 | } | 460 | } |
461 | 461 | ||
462 | if (prev_p->current) { | 462 | if (prev_p->current) { |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 294da725a57d..40a6a2992d15 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -1,13 +1,16 @@ | |||
1 | #include "builtin.h" | 1 | #include "builtin.h" |
2 | 2 | ||
3 | #include "util/util.h" | 3 | #include "perf.h" |
4 | #include "util/cache.h" | 4 | #include "util/cache.h" |
5 | #include "util/debug.h" | ||
6 | #include "util/exec_cmd.h" | ||
7 | #include "util/header.h" | ||
8 | #include "util/parse-options.h" | ||
9 | #include "util/session.h" | ||
5 | #include "util/symbol.h" | 10 | #include "util/symbol.h" |
6 | #include "util/thread.h" | 11 | #include "util/thread.h" |
7 | #include "util/header.h" | ||
8 | #include "util/exec_cmd.h" | ||
9 | #include "util/trace-event.h" | 12 | #include "util/trace-event.h" |
10 | #include "util/session.h" | 13 | #include "util/util.h" |
11 | 14 | ||
12 | static char const *script_name; | 15 | static char const *script_name; |
13 | static char const *generate_script_lang; | 16 | static char const *generate_script_lang; |
@@ -59,14 +62,6 @@ static int cleanup_scripting(void) | |||
59 | return scripting_ops->stop_script(); | 62 | return scripting_ops->stop_script(); |
60 | } | 63 | } |
61 | 64 | ||
62 | #include "util/parse-options.h" | ||
63 | |||
64 | #include "perf.h" | ||
65 | #include "util/debug.h" | ||
66 | |||
67 | #include "util/trace-event.h" | ||
68 | #include "util/exec_cmd.h" | ||
69 | |||
70 | static char const *input_name = "perf.data"; | 65 | static char const *input_name = "perf.data"; |
71 | 66 | ||
72 | static int process_sample_event(event_t *event, struct perf_session *session) | 67 | static int process_sample_event(event_t *event, struct perf_session *session) |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index e7263d49bcf0..62ec9b0e4b9a 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -876,6 +876,9 @@ unsigned int hists__sort_list_width(struct hists *self) | |||
876 | if (!se->elide) | 876 | if (!se->elide) |
877 | ret += 2 + hists__col_len(self, se->se_width_idx); | 877 | ret += 2 + hists__col_len(self, se->se_width_idx); |
878 | 878 | ||
879 | if (verbose) /* Addr + origin */ | ||
880 | ret += 3 + BITS_PER_LONG / 4; | ||
881 | |||
879 | return ret; | 882 | return ret; |
880 | } | 883 | } |
881 | 884 | ||
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 91de99b58445..e2deae0704d7 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <slang.h> | 13 | #include <slang.h> |
14 | #include <signal.h> | 14 | #include <signal.h> |
15 | #include <stdlib.h> | 15 | #include <stdlib.h> |
16 | #include <elf.h> | ||
16 | #include <newt.h> | 17 | #include <newt.h> |
17 | #include <sys/ttydefaults.h> | 18 | #include <sys/ttydefaults.h> |
18 | 19 | ||
@@ -127,6 +128,39 @@ static void ui_helpline__puts(const char *msg) | |||
127 | ui_helpline__push(msg); | 128 | ui_helpline__push(msg); |
128 | } | 129 | } |
129 | 130 | ||
131 | static int ui_entry__read(const char *title, char *bf, size_t size, int width) | ||
132 | { | ||
133 | struct newtExitStruct es; | ||
134 | newtComponent form, entry; | ||
135 | const char *result; | ||
136 | int err = -1; | ||
137 | |||
138 | newtCenteredWindow(width, 1, title); | ||
139 | form = newtForm(NULL, NULL, 0); | ||
140 | if (form == NULL) | ||
141 | return -1; | ||
142 | |||
143 | entry = newtEntry(0, 0, "0x", width, &result, NEWT_FLAG_SCROLL); | ||
144 | if (entry == NULL) | ||
145 | goto out_free_form; | ||
146 | |||
147 | newtFormAddComponent(form, entry); | ||
148 | newtFormAddHotKey(form, NEWT_KEY_ENTER); | ||
149 | newtFormAddHotKey(form, NEWT_KEY_ESCAPE); | ||
150 | newtFormAddHotKey(form, NEWT_KEY_LEFT); | ||
151 | newtFormAddHotKey(form, CTRL('c')); | ||
152 | newtFormRun(form, &es); | ||
153 | |||
154 | if (result != NULL) { | ||
155 | strncpy(bf, result, size); | ||
156 | err = 0; | ||
157 | } | ||
158 | out_free_form: | ||
159 | newtPopWindow(); | ||
160 | newtFormDestroy(form); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
130 | static char browser__last_msg[1024]; | 164 | static char browser__last_msg[1024]; |
131 | 165 | ||
132 | int browser__show_help(const char *format, va_list ap) | 166 | int browser__show_help(const char *format, va_list ap) |
@@ -279,7 +313,8 @@ struct ui_browser { | |||
279 | void *first_visible_entry, *entries; | 313 | void *first_visible_entry, *entries; |
280 | u16 top, left, width, height; | 314 | u16 top, left, width, height; |
281 | void *priv; | 315 | void *priv; |
282 | unsigned int (*refresh_entries)(struct ui_browser *self); | 316 | unsigned int (*refresh)(struct ui_browser *self); |
317 | void (*write)(struct ui_browser *self, void *entry, int row); | ||
283 | void (*seek)(struct ui_browser *self, | 318 | void (*seek)(struct ui_browser *self, |
284 | off_t offset, int whence); | 319 | off_t offset, int whence); |
285 | u32 nr_entries; | 320 | u32 nr_entries; |
@@ -316,6 +351,58 @@ static void ui_browser__list_head_seek(struct ui_browser *self, | |||
316 | self->first_visible_entry = pos; | 351 | self->first_visible_entry = pos; |
317 | } | 352 | } |
318 | 353 | ||
354 | static void ui_browser__rb_tree_seek(struct ui_browser *self, | ||
355 | off_t offset, int whence) | ||
356 | { | ||
357 | struct rb_root *root = self->entries; | ||
358 | struct rb_node *nd; | ||
359 | |||
360 | switch (whence) { | ||
361 | case SEEK_SET: | ||
362 | nd = rb_first(root); | ||
363 | break; | ||
364 | case SEEK_CUR: | ||
365 | nd = self->first_visible_entry; | ||
366 | break; | ||
367 | case SEEK_END: | ||
368 | nd = rb_last(root); | ||
369 | break; | ||
370 | default: | ||
371 | return; | ||
372 | } | ||
373 | |||
374 | if (offset > 0) { | ||
375 | while (offset-- != 0) | ||
376 | nd = rb_next(nd); | ||
377 | } else { | ||
378 | while (offset++ != 0) | ||
379 | nd = rb_prev(nd); | ||
380 | } | ||
381 | |||
382 | self->first_visible_entry = nd; | ||
383 | } | ||
384 | |||
385 | static unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self) | ||
386 | { | ||
387 | struct rb_node *nd; | ||
388 | int row = 0; | ||
389 | |||
390 | if (self->first_visible_entry == NULL) | ||
391 | self->first_visible_entry = rb_first(self->entries); | ||
392 | |||
393 | nd = self->first_visible_entry; | ||
394 | |||
395 | while (nd != NULL) { | ||
396 | SLsmg_gotorc(self->top + row, self->left); | ||
397 | self->write(self, nd, row); | ||
398 | if (++row == self->height) | ||
399 | break; | ||
400 | nd = rb_next(nd); | ||
401 | } | ||
402 | |||
403 | return row; | ||
404 | } | ||
405 | |||
319 | static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row) | 406 | static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row) |
320 | { | 407 | { |
321 | return (self->first_visible_entry_idx + row) == self->index; | 408 | return (self->first_visible_entry_idx + row) == self->index; |
@@ -418,12 +505,12 @@ static int objdump_line__show(struct objdump_line *self, struct list_head *head, | |||
418 | return 0; | 505 | return 0; |
419 | } | 506 | } |
420 | 507 | ||
421 | static int ui_browser__refresh_entries(struct ui_browser *self) | 508 | static int ui_browser__refresh(struct ui_browser *self) |
422 | { | 509 | { |
423 | int row; | 510 | int row; |
424 | 511 | ||
425 | newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); | 512 | newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); |
426 | row = self->refresh_entries(self); | 513 | row = self->refresh(self); |
427 | SLsmg_set_color(HE_COLORSET_NORMAL); | 514 | SLsmg_set_color(HE_COLORSET_NORMAL); |
428 | SLsmg_fill_region(self->top + row, self->left, | 515 | SLsmg_fill_region(self->top + row, self->left, |
429 | self->height - row, self->width, ' '); | 516 | self->height - row, self->width, ' '); |
@@ -433,7 +520,7 @@ static int ui_browser__refresh_entries(struct ui_browser *self) | |||
433 | 520 | ||
434 | static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es) | 521 | static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es) |
435 | { | 522 | { |
436 | if (ui_browser__refresh_entries(self) < 0) | 523 | if (ui_browser__refresh(self) < 0) |
437 | return -1; | 524 | return -1; |
438 | 525 | ||
439 | while (1) { | 526 | while (1) { |
@@ -504,7 +591,7 @@ static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es) | |||
504 | default: | 591 | default: |
505 | return es->u.key; | 592 | return es->u.key; |
506 | } | 593 | } |
507 | if (ui_browser__refresh_entries(self) < 0) | 594 | if (ui_browser__refresh(self) < 0) |
508 | return -1; | 595 | return -1; |
509 | } | 596 | } |
510 | return 0; | 597 | return 0; |
@@ -567,9 +654,9 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
567 | ui_helpline__push("Press <- or ESC to exit"); | 654 | ui_helpline__push("Press <- or ESC to exit"); |
568 | 655 | ||
569 | memset(&browser, 0, sizeof(browser)); | 656 | memset(&browser, 0, sizeof(browser)); |
570 | browser.entries = &head; | 657 | browser.entries = &head; |
571 | browser.refresh_entries = hist_entry__annotate_browser_refresh; | 658 | browser.refresh = hist_entry__annotate_browser_refresh; |
572 | browser.seek = ui_browser__list_head_seek; | 659 | browser.seek = ui_browser__list_head_seek; |
573 | browser.priv = self; | 660 | browser.priv = self; |
574 | list_for_each_entry(pos, &head, node) { | 661 | list_for_each_entry(pos, &head, node) { |
575 | size_t line_len = strlen(pos->line); | 662 | size_t line_len = strlen(pos->line); |
@@ -592,6 +679,128 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
592 | return ret; | 679 | return ret; |
593 | } | 680 | } |
594 | 681 | ||
682 | /* -------------------------------------------------------------------- */ | ||
683 | |||
684 | struct map_browser { | ||
685 | struct ui_browser b; | ||
686 | struct map *map; | ||
687 | u16 namelen; | ||
688 | u8 addrlen; | ||
689 | }; | ||
690 | |||
691 | static void map_browser__write(struct ui_browser *self, void *nd, int row) | ||
692 | { | ||
693 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | ||
694 | struct map_browser *mb = container_of(self, struct map_browser, b); | ||
695 | bool current_entry = ui_browser__is_current_entry(self, row); | ||
696 | int color = ui_browser__percent_color(0, current_entry); | ||
697 | |||
698 | SLsmg_set_color(color); | ||
699 | slsmg_printf("%*llx %*llx %c ", | ||
700 | mb->addrlen, sym->start, mb->addrlen, sym->end, | ||
701 | sym->binding == STB_GLOBAL ? 'g' : | ||
702 | sym->binding == STB_LOCAL ? 'l' : 'w'); | ||
703 | slsmg_write_nstring(sym->name, mb->namelen); | ||
704 | } | ||
705 | |||
706 | /* FIXME uber-kludgy, see comment on cmd_report... */ | ||
707 | static u32 *symbol__browser_index(struct symbol *self) | ||
708 | { | ||
709 | return ((void *)self) - sizeof(struct rb_node) - sizeof(u32); | ||
710 | } | ||
711 | |||
712 | static int map_browser__search(struct map_browser *self) | ||
713 | { | ||
714 | char target[512]; | ||
715 | struct symbol *sym; | ||
716 | int err = ui_entry__read("Search by name/addr", target, sizeof(target), 40); | ||
717 | |||
718 | if (err) | ||
719 | return err; | ||
720 | |||
721 | if (target[0] == '0' && tolower(target[1]) == 'x') { | ||
722 | u64 addr = strtoull(target, NULL, 16); | ||
723 | sym = map__find_symbol(self->map, addr, NULL); | ||
724 | } else | ||
725 | sym = map__find_symbol_by_name(self->map, target, NULL); | ||
726 | |||
727 | if (sym != NULL) { | ||
728 | u32 *idx = symbol__browser_index(sym); | ||
729 | |||
730 | self->b.first_visible_entry = &sym->rb_node; | ||
731 | self->b.index = self->b.first_visible_entry_idx = *idx; | ||
732 | } else | ||
733 | ui_helpline__fpush("%s not found!", target); | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int map_browser__run(struct map_browser *self, struct newtExitStruct *es) | ||
739 | { | ||
740 | if (ui_browser__show(&self->b, self->map->dso->long_name) < 0) | ||
741 | return -1; | ||
742 | |||
743 | ui_helpline__fpush("Press <- or ESC to exit, %s / to search", | ||
744 | verbose ? "" : "restart with -v to use"); | ||
745 | newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT); | ||
746 | newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER); | ||
747 | if (verbose) | ||
748 | newtFormAddHotKey(self->b.form, '/'); | ||
749 | |||
750 | while (1) { | ||
751 | ui_browser__run(&self->b, es); | ||
752 | |||
753 | if (es->reason != NEWT_EXIT_HOTKEY) | ||
754 | break; | ||
755 | if (verbose && es->u.key == '/') | ||
756 | map_browser__search(self); | ||
757 | else | ||
758 | break; | ||
759 | } | ||
760 | |||
761 | newtFormDestroy(self->b.form); | ||
762 | newtPopWindow(); | ||
763 | ui_helpline__pop(); | ||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | static int map__browse(struct map *self) | ||
768 | { | ||
769 | struct map_browser mb = { | ||
770 | .b = { | ||
771 | .entries = &self->dso->symbols[self->type], | ||
772 | .refresh = ui_browser__rb_tree_refresh, | ||
773 | .seek = ui_browser__rb_tree_seek, | ||
774 | .write = map_browser__write, | ||
775 | }, | ||
776 | .map = self, | ||
777 | }; | ||
778 | struct newtExitStruct es; | ||
779 | struct rb_node *nd; | ||
780 | char tmp[BITS_PER_LONG / 4]; | ||
781 | u64 maxaddr = 0; | ||
782 | |||
783 | for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) { | ||
784 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); | ||
785 | |||
786 | if (mb.namelen < pos->namelen) | ||
787 | mb.namelen = pos->namelen; | ||
788 | if (maxaddr < pos->end) | ||
789 | maxaddr = pos->end; | ||
790 | if (verbose) { | ||
791 | u32 *idx = symbol__browser_index(pos); | ||
792 | *idx = mb.b.nr_entries; | ||
793 | } | ||
794 | ++mb.b.nr_entries; | ||
795 | } | ||
796 | |||
797 | mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr); | ||
798 | mb.b.width += mb.addrlen * 2 + 4 + mb.namelen; | ||
799 | return map_browser__run(&mb, &es); | ||
800 | } | ||
801 | |||
802 | /* -------------------------------------------------------------------- */ | ||
803 | |||
595 | struct hist_browser { | 804 | struct hist_browser { |
596 | struct ui_browser b; | 805 | struct ui_browser b; |
597 | struct hists *hists; | 806 | struct hists *hists; |
@@ -602,7 +811,7 @@ struct hist_browser { | |||
602 | static void hist_browser__reset(struct hist_browser *self); | 811 | static void hist_browser__reset(struct hist_browser *self); |
603 | static int hist_browser__run(struct hist_browser *self, const char *title, | 812 | static int hist_browser__run(struct hist_browser *self, const char *title, |
604 | struct newtExitStruct *es); | 813 | struct newtExitStruct *es); |
605 | static unsigned int hist_browser__refresh_entries(struct ui_browser *self); | 814 | static unsigned int hist_browser__refresh(struct ui_browser *self); |
606 | static void ui_browser__hists_seek(struct ui_browser *self, | 815 | static void ui_browser__hists_seek(struct ui_browser *self, |
607 | off_t offset, int whence); | 816 | off_t offset, int whence); |
608 | 817 | ||
@@ -612,7 +821,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists) | |||
612 | 821 | ||
613 | if (self) { | 822 | if (self) { |
614 | self->hists = hists; | 823 | self->hists = hists; |
615 | self->b.refresh_entries = hist_browser__refresh_entries; | 824 | self->b.refresh = hist_browser__refresh; |
616 | self->b.seek = ui_browser__hists_seek; | 825 | self->b.seek = ui_browser__hists_seek; |
617 | } | 826 | } |
618 | 827 | ||
@@ -680,7 +889,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name) | |||
680 | const struct dso *dso; | 889 | const struct dso *dso; |
681 | char *options[16]; | 890 | char *options[16]; |
682 | int nr_options = 0, choice = 0, i, | 891 | int nr_options = 0, choice = 0, i, |
683 | annotate = -2, zoom_dso = -2, zoom_thread = -2; | 892 | annotate = -2, zoom_dso = -2, zoom_thread = -2, |
893 | browse_map = -2; | ||
684 | 894 | ||
685 | if (hist_browser__run(browser, msg, &es)) | 895 | if (hist_browser__run(browser, msg, &es)) |
686 | break; | 896 | break; |
@@ -771,6 +981,10 @@ do_help: | |||
771 | (dso->kernel ? "the Kernel" : dso->short_name)) > 0) | 981 | (dso->kernel ? "the Kernel" : dso->short_name)) > 0) |
772 | zoom_dso = nr_options++; | 982 | zoom_dso = nr_options++; |
773 | 983 | ||
984 | if (browser->selection->map != NULL && | ||
985 | asprintf(&options[nr_options], "Browse map details") > 0) | ||
986 | browse_map = nr_options++; | ||
987 | |||
774 | options[nr_options++] = (char *)"Exit"; | 988 | options[nr_options++] = (char *)"Exit"; |
775 | 989 | ||
776 | choice = popup_menu(nr_options, options); | 990 | choice = popup_menu(nr_options, options); |
@@ -800,7 +1014,9 @@ do_annotate: | |||
800 | continue; | 1014 | continue; |
801 | 1015 | ||
802 | hist_entry__tui_annotate(he); | 1016 | hist_entry__tui_annotate(he); |
803 | } else if (choice == zoom_dso) { | 1017 | } else if (choice == browse_map) |
1018 | map__browse(browser->selection->map); | ||
1019 | else if (choice == zoom_dso) { | ||
804 | zoom_dso: | 1020 | zoom_dso: |
805 | if (dso_filter) { | 1021 | if (dso_filter) { |
806 | pstack__remove(fstack, &dso_filter); | 1022 | pstack__remove(fstack, &dso_filter); |
@@ -1213,7 +1429,7 @@ static int hist_browser__show_entry(struct hist_browser *self, | |||
1213 | return printed; | 1429 | return printed; |
1214 | } | 1430 | } |
1215 | 1431 | ||
1216 | static unsigned int hist_browser__refresh_entries(struct ui_browser *self) | 1432 | static unsigned int hist_browser__refresh(struct ui_browser *self) |
1217 | { | 1433 | { |
1218 | unsigned row = 0; | 1434 | unsigned row = 0; |
1219 | struct rb_node *nd; | 1435 | struct rb_node *nd; |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 840f1aabbb74..6c7750da43d7 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <ctype.h> | 33 | #include <ctype.h> |
34 | #include <dwarf-regs.h> | 34 | #include <dwarf-regs.h> |
35 | 35 | ||
36 | #include "string.h" | ||
37 | #include "event.h" | 36 | #include "event.h" |
38 | #include "debug.h" | 37 | #include "debug.h" |
39 | #include "util.h" | 38 | #include "util.h" |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1c61a4f4aa8a..b62a553cc67d 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -196,7 +196,8 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, | |||
196 | 196 | ||
197 | if (verbose) { | 197 | if (verbose) { |
198 | char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; | 198 | char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; |
199 | ret += repsep_snprintf(bf, size, "%#018llx %c ", self->ip, o); | 199 | ret += repsep_snprintf(bf, size, "%*Lx %c ", |
200 | BITS_PER_LONG / 4, self->ip, o); | ||
200 | } | 201 | } |
201 | 202 | ||
202 | ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level); | 203 | ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level); |
@@ -204,7 +205,8 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, | |||
204 | ret += repsep_snprintf(bf + ret, size - ret, "%s", | 205 | ret += repsep_snprintf(bf + ret, size - ret, "%s", |
205 | self->ms.sym->name); | 206 | self->ms.sym->name); |
206 | else | 207 | else |
207 | ret += repsep_snprintf(bf + ret, size - ret, "%#016llx", self->ip); | 208 | ret += repsep_snprintf(bf + ret, size - ret, "%*Lx", |
209 | BITS_PER_LONG / 4, self->ip); | ||
208 | 210 | ||
209 | return ret; | 211 | return ret; |
210 | } | 212 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 6f0dd90c36ce..b6f5970f9106 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -131,7 +131,8 @@ static void map_groups__fixup_end(struct map_groups *self) | |||
131 | __map_groups__fixup_end(self, i); | 131 | __map_groups__fixup_end(self, i); |
132 | } | 132 | } |
133 | 133 | ||
134 | static struct symbol *symbol__new(u64 start, u64 len, const char *name) | 134 | static struct symbol *symbol__new(u64 start, u64 len, u8 binding, |
135 | const char *name) | ||
135 | { | 136 | { |
136 | size_t namelen = strlen(name) + 1; | 137 | size_t namelen = strlen(name) + 1; |
137 | struct symbol *self = calloc(1, (symbol_conf.priv_size + | 138 | struct symbol *self = calloc(1, (symbol_conf.priv_size + |
@@ -144,6 +145,7 @@ static struct symbol *symbol__new(u64 start, u64 len, const char *name) | |||
144 | 145 | ||
145 | self->start = start; | 146 | self->start = start; |
146 | self->end = len ? start + len - 1 : start; | 147 | self->end = len ? start + len - 1 : start; |
148 | self->binding = binding; | ||
147 | self->namelen = namelen - 1; | 149 | self->namelen = namelen - 1; |
148 | 150 | ||
149 | pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); | 151 | pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); |
@@ -160,8 +162,11 @@ void symbol__delete(struct symbol *self) | |||
160 | 162 | ||
161 | static size_t symbol__fprintf(struct symbol *self, FILE *fp) | 163 | static size_t symbol__fprintf(struct symbol *self, FILE *fp) |
162 | { | 164 | { |
163 | return fprintf(fp, " %llx-%llx %s\n", | 165 | return fprintf(fp, " %llx-%llx %c %s\n", |
164 | self->start, self->end, self->name); | 166 | self->start, self->end, |
167 | self->binding == STB_GLOBAL ? 'g' : | ||
168 | self->binding == STB_LOCAL ? 'l' : 'w', | ||
169 | self->name); | ||
165 | } | 170 | } |
166 | 171 | ||
167 | void dso__set_long_name(struct dso *self, char *name) | 172 | void dso__set_long_name(struct dso *self, char *name) |
@@ -453,6 +458,14 @@ struct process_kallsyms_args { | |||
453 | struct dso *dso; | 458 | struct dso *dso; |
454 | }; | 459 | }; |
455 | 460 | ||
461 | static u8 kallsyms2elf_type(char type) | ||
462 | { | ||
463 | if (type == 'W') | ||
464 | return STB_WEAK; | ||
465 | |||
466 | return isupper(type) ? STB_GLOBAL : STB_LOCAL; | ||
467 | } | ||
468 | |||
456 | static int map__process_kallsym_symbol(void *arg, const char *name, | 469 | static int map__process_kallsym_symbol(void *arg, const char *name, |
457 | char type, u64 start) | 470 | char type, u64 start) |
458 | { | 471 | { |
@@ -466,7 +479,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name, | |||
466 | /* | 479 | /* |
467 | * Will fix up the end later, when we have all symbols sorted. | 480 | * Will fix up the end later, when we have all symbols sorted. |
468 | */ | 481 | */ |
469 | sym = symbol__new(start, 0, name); | 482 | sym = symbol__new(start, 0, kallsyms2elf_type(type), name); |
470 | 483 | ||
471 | if (sym == NULL) | 484 | if (sym == NULL) |
472 | return -ENOMEM; | 485 | return -ENOMEM; |
@@ -661,7 +674,7 @@ static int dso__load_perf_map(struct dso *self, struct map *map, | |||
661 | if (len + 2 >= line_len) | 674 | if (len + 2 >= line_len) |
662 | continue; | 675 | continue; |
663 | 676 | ||
664 | sym = symbol__new(start, size, line + len); | 677 | sym = symbol__new(start, size, STB_GLOBAL, line + len); |
665 | 678 | ||
666 | if (sym == NULL) | 679 | if (sym == NULL) |
667 | goto out_delete_line; | 680 | goto out_delete_line; |
@@ -873,7 +886,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, | |||
873 | "%s@plt", elf_sym__name(&sym, symstrs)); | 886 | "%s@plt", elf_sym__name(&sym, symstrs)); |
874 | 887 | ||
875 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 888 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
876 | sympltname); | 889 | STB_GLOBAL, sympltname); |
877 | if (!f) | 890 | if (!f) |
878 | goto out_elf_end; | 891 | goto out_elf_end; |
879 | 892 | ||
@@ -895,7 +908,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, | |||
895 | "%s@plt", elf_sym__name(&sym, symstrs)); | 908 | "%s@plt", elf_sym__name(&sym, symstrs)); |
896 | 909 | ||
897 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 910 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
898 | sympltname); | 911 | STB_GLOBAL, sympltname); |
899 | if (!f) | 912 | if (!f) |
900 | goto out_elf_end; | 913 | goto out_elf_end; |
901 | 914 | ||
@@ -1146,7 +1159,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1146 | if (demangled != NULL) | 1159 | if (demangled != NULL) |
1147 | elf_name = demangled; | 1160 | elf_name = demangled; |
1148 | new_symbol: | 1161 | new_symbol: |
1149 | f = symbol__new(sym.st_value, sym.st_size, elf_name); | 1162 | f = symbol__new(sym.st_value, sym.st_size, |
1163 | GELF_ST_BIND(sym.st_info), elf_name); | ||
1150 | free(demangled); | 1164 | free(demangled); |
1151 | if (!f) | 1165 | if (!f) |
1152 | goto out_elf_end; | 1166 | goto out_elf_end; |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 906be20011d9..b7a8da4af5a0 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -53,6 +53,7 @@ struct symbol { | |||
53 | u64 start; | 53 | u64 start; |
54 | u64 end; | 54 | u64 end; |
55 | u16 namelen; | 55 | u16 namelen; |
56 | u8 binding; | ||
56 | char name[0]; | 57 | char name[0]; |
57 | }; | 58 | }; |
58 | 59 | ||