diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-11-20 02:32:01 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-11-20 02:32:01 -0500 |
commit | 4e6e311e596eadba30d4f56f64eae7d45611a01c (patch) | |
tree | 681fb4c9ae7320ab1192f92e1c153ab35c90bf8e | |
parent | 2565711fb7d7c28e0cd93c8971b520d1b10b857c (diff) | |
parent | a84808083688d82d7f1e5786ccf5df0ff7d448cb (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:
User visible fixes:
- Fallback to kallsyms when using the minimal 'ELF' loader (Arnaldo Carvalho de Melo)
- Fix annotation with kcore (Adrian Hunter)
- Fix up srcline histogram key formatting (Arnaldo Carvalho de Melo)
- Add missing handler for PERF_RECORD_MMAP2 events in 'perf diff' (Kan Liang)
User visible changes/new features:
- Only print base source file for srcline histogram sort key (Andi Kleen)
- Support source line numbers in annotate using a hotkey (Andi Kleen)
Infrastructure changes and fixes:
- Do not poll events that use the system_wide flag (Adrian Hunter)
- Add perf-read-vdso32 and perf-read-vdsox32 to .gitignore (Adrian Hunter)
- Only override the default :tid comm entry (Adrian Hunter)
- Factor out adding new call chain entries (Andi Kleen)
- Use al.addr to set up call chain (Andi Kleen)
- Use a common function to resolve symbol or name (Andi Kleen)
- Fix ftrace:function event recording (Jiri Olsa)
- Move disable_buildid_cache() to util/build-id.c (Namhyung Kim)
- Clean up libelf feature support code (Namhyung Kim)
- Fix typo in python 'perf test' (WANG Chao)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/.gitignore | 2 | ||||
-rw-r--r-- | tools/perf/Makefile.perf | 2 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 1 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 5 | ||||
-rw-r--r-- | tools/perf/tests/builtin-test.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/browsers/annotate.c | 13 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 17 | ||||
-rw-r--r-- | tools/perf/ui/gtk/hists.c | 11 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 23 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 32 | ||||
-rw-r--r-- | tools/perf/util/annotate.h | 1 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 11 | ||||
-rw-r--r-- | tools/perf/util/build-id.h | 1 | ||||
-rw-r--r-- | tools/perf/util/callchain.c | 19 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 3 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 10 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 8 | ||||
-rw-r--r-- | tools/perf/util/header.c | 10 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 51 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 2 | ||||
-rw-r--r-- | tools/perf/util/srcline.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 1 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 5 | ||||
-rw-r--r-- | tools/perf/util/util.h | 1 |
24 files changed, 145 insertions, 88 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 717221e98450..40399c3d97d6 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore | |||
@@ -2,6 +2,8 @@ PERF-CFLAGS | |||
2 | PERF-GUI-VARS | 2 | PERF-GUI-VARS |
3 | PERF-VERSION-FILE | 3 | PERF-VERSION-FILE |
4 | perf | 4 | perf |
5 | perf-read-vdso32 | ||
6 | perf-read-vdsox32 | ||
5 | perf-help | 7 | perf-help |
6 | perf-record | 8 | perf-record |
7 | perf-report | 9 | perf-report |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index aecf61dcd754..478efa9b2364 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -497,8 +497,6 @@ ifneq ($(OUTPUT),) | |||
497 | endif | 497 | endif |
498 | 498 | ||
499 | ifdef NO_LIBELF | 499 | ifdef NO_LIBELF |
500 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) | ||
501 | |||
502 | # Remove ELF/DWARF dependent codes | 500 | # Remove ELF/DWARF dependent codes |
503 | LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) | 501 | LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) |
504 | LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) | 502 | LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 25114c9a6801..1ce425d101a9 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -357,6 +357,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
357 | static struct perf_tool tool = { | 357 | static struct perf_tool tool = { |
358 | .sample = diff__process_sample_event, | 358 | .sample = diff__process_sample_event, |
359 | .mmap = perf_event__process_mmap, | 359 | .mmap = perf_event__process_mmap, |
360 | .mmap2 = perf_event__process_mmap2, | ||
360 | .comm = perf_event__process_comm, | 361 | .comm = perf_event__process_comm, |
361 | .exit = perf_event__process_exit, | 362 | .exit = perf_event__process_exit, |
362 | .fork = perf_event__process_fork, | 363 | .fork = perf_event__process_fork, |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 79f906c7124e..5d4b039fe1ed 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -150,7 +150,7 @@ CFLAGS += -std=gnu99 | |||
150 | # adding assembler files missing the .GNU-stack linker note. | 150 | # adding assembler files missing the .GNU-stack linker note. |
151 | LDFLAGS += -Wl,-z,noexecstack | 151 | LDFLAGS += -Wl,-z,noexecstack |
152 | 152 | ||
153 | EXTLIBS = -lelf -lpthread -lrt -lm -ldl | 153 | EXTLIBS = -lpthread -lrt -lm -ldl |
154 | 154 | ||
155 | ifneq ($(OUTPUT),) | 155 | ifneq ($(OUTPUT),) |
156 | OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ | 156 | OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ |
@@ -354,6 +354,7 @@ endif # NO_LIBELF | |||
354 | 354 | ||
355 | ifndef NO_LIBELF | 355 | ifndef NO_LIBELF |
356 | CFLAGS += -DHAVE_LIBELF_SUPPORT | 356 | CFLAGS += -DHAVE_LIBELF_SUPPORT |
357 | EXTLIBS += -lelf | ||
357 | 358 | ||
358 | ifeq ($(feature-libelf-mmap), 1) | 359 | ifeq ($(feature-libelf-mmap), 1) |
359 | CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT | 360 | CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT |
@@ -373,7 +374,7 @@ ifndef NO_LIBELF | |||
373 | else | 374 | else |
374 | CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) | 375 | CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) |
375 | LDFLAGS += $(LIBDW_LDFLAGS) | 376 | LDFLAGS += $(LIBDW_LDFLAGS) |
376 | EXTLIBS += -lelf -ldw | 377 | EXTLIBS += -ldw |
377 | endif # PERF_HAVE_DWARF_REGS | 378 | endif # PERF_HAVE_DWARF_REGS |
378 | endif # NO_DWARF | 379 | endif # NO_DWARF |
379 | endif # NO_LIBELF | 380 | endif # NO_LIBELF |
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 162c978f1491..4b7d9ab0f049 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -85,7 +85,7 @@ static struct test { | |||
85 | .func = test__hists_link, | 85 | .func = test__hists_link, |
86 | }, | 86 | }, |
87 | { | 87 | { |
88 | .desc = "Try 'use perf' in python, checking link problems", | 88 | .desc = "Try 'import perf' in python, checking link problems", |
89 | .func = test__python_use, | 89 | .func = test__python_use, |
90 | }, | 90 | }, |
91 | { | 91 | { |
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index f0697a3aede0..1e0a2fd80115 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -27,6 +27,7 @@ static struct annotate_browser_opt { | |||
27 | bool hide_src_code, | 27 | bool hide_src_code, |
28 | use_offset, | 28 | use_offset, |
29 | jump_arrows, | 29 | jump_arrows, |
30 | show_linenr, | ||
30 | show_nr_jumps; | 31 | show_nr_jumps; |
31 | } annotate_browser__opts = { | 32 | } annotate_browser__opts = { |
32 | .use_offset = true, | 33 | .use_offset = true, |
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int | |||
128 | if (!*dl->line) | 129 | if (!*dl->line) |
129 | slsmg_write_nstring(" ", width - pcnt_width); | 130 | slsmg_write_nstring(" ", width - pcnt_width); |
130 | else if (dl->offset == -1) { | 131 | else if (dl->offset == -1) { |
131 | printed = scnprintf(bf, sizeof(bf), "%*s ", | 132 | if (dl->line_nr && annotate_browser__opts.show_linenr) |
133 | printed = scnprintf(bf, sizeof(bf), "%-*d ", | ||
134 | ab->addr_width + 1, dl->line_nr); | ||
135 | else | ||
136 | printed = scnprintf(bf, sizeof(bf), "%*s ", | ||
132 | ab->addr_width, " "); | 137 | ab->addr_width, " "); |
133 | slsmg_write_nstring(bf, printed); | 138 | slsmg_write_nstring(bf, printed); |
134 | slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); | 139 | slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); |
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser, | |||
733 | "o Toggle disassembler output/simplified view\n" | 738 | "o Toggle disassembler output/simplified view\n" |
734 | "s Toggle source code view\n" | 739 | "s Toggle source code view\n" |
735 | "/ Search string\n" | 740 | "/ Search string\n" |
741 | "k Toggle line numbers\n" | ||
736 | "r Run available scripts\n" | 742 | "r Run available scripts\n" |
737 | "? Search string backwards\n"); | 743 | "? Search string backwards\n"); |
738 | continue; | 744 | continue; |
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser, | |||
741 | script_browse(NULL); | 747 | script_browse(NULL); |
742 | continue; | 748 | continue; |
743 | } | 749 | } |
750 | case 'k': | ||
751 | annotate_browser__opts.show_linenr = | ||
752 | !annotate_browser__opts.show_linenr; | ||
753 | break; | ||
744 | case 'H': | 754 | case 'H': |
745 | nd = browser->curr_hot; | 755 | nd = browser->curr_hot; |
746 | break; | 756 | break; |
@@ -984,6 +994,7 @@ static struct annotate_config { | |||
984 | } annotate__configs[] = { | 994 | } annotate__configs[] = { |
985 | ANNOTATE_CFG(hide_src_code), | 995 | ANNOTATE_CFG(hide_src_code), |
986 | ANNOTATE_CFG(jump_arrows), | 996 | ANNOTATE_CFG(jump_arrows), |
997 | ANNOTATE_CFG(show_linenr), | ||
987 | ANNOTATE_CFG(show_nr_jumps), | 998 | ANNOTATE_CFG(show_nr_jumps), |
988 | ANNOTATE_CFG(use_offset), | 999 | ANNOTATE_CFG(use_offset), |
989 | }; | 1000 | }; |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index cfb976b3de3a..12c17c5a3d68 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -463,23 +463,6 @@ out: | |||
463 | return key; | 463 | return key; |
464 | } | 464 | } |
465 | 465 | ||
466 | static char *callchain_list__sym_name(struct callchain_list *cl, | ||
467 | char *bf, size_t bfsize, bool show_dso) | ||
468 | { | ||
469 | int printed; | ||
470 | |||
471 | if (cl->ms.sym) | ||
472 | printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); | ||
473 | else | ||
474 | printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
475 | |||
476 | if (show_dso) | ||
477 | scnprintf(bf + printed, bfsize - printed, " %s", | ||
478 | cl->ms.map ? cl->ms.map->dso->short_name : "unknown"); | ||
479 | |||
480 | return bf; | ||
481 | } | ||
482 | |||
483 | struct callchain_print_arg { | 466 | struct callchain_print_arg { |
484 | /* for hists browser */ | 467 | /* for hists browser */ |
485 | off_t row_offset; | 468 | off_t row_offset; |
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index fc654fb77ace..4b3585eed1e8 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c | |||
@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void) | |||
89 | perf_gtk__hpp_color_overhead_acc; | 89 | perf_gtk__hpp_color_overhead_acc; |
90 | } | 90 | } |
91 | 91 | ||
92 | static void callchain_list__sym_name(struct callchain_list *cl, | ||
93 | char *bf, size_t bfsize) | ||
94 | { | ||
95 | if (cl->ms.sym) | ||
96 | scnprintf(bf, bfsize, "%s", cl->ms.sym->name); | ||
97 | else | ||
98 | scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
99 | } | ||
100 | |||
101 | static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, | 92 | static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, |
102 | GtkTreeIter *parent, int col, u64 total) | 93 | GtkTreeIter *parent, int col, u64 total) |
103 | { | 94 | { |
@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, | |||
128 | scnprintf(buf, sizeof(buf), "%5.2f%%", percent); | 119 | scnprintf(buf, sizeof(buf), "%5.2f%%", percent); |
129 | gtk_tree_store_set(store, &iter, 0, buf, -1); | 120 | gtk_tree_store_set(store, &iter, 0, buf, -1); |
130 | 121 | ||
131 | callchain_list__sym_name(chain, buf, sizeof(buf)); | 122 | callchain_list__sym_name(chain, buf, sizeof(buf), false); |
132 | gtk_tree_store_set(store, &iter, col, buf, -1); | 123 | gtk_tree_store_set(store, &iter, col, buf, -1); |
133 | 124 | ||
134 | if (need_new_parent) { | 125 | if (need_new_parent) { |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 15b451acbde6..dfcbc90146ef 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, | |||
41 | { | 41 | { |
42 | int i; | 42 | int i; |
43 | size_t ret = 0; | 43 | size_t ret = 0; |
44 | char bf[1024]; | ||
44 | 45 | ||
45 | ret += callchain__fprintf_left_margin(fp, left_margin); | 46 | ret += callchain__fprintf_left_margin(fp, left_margin); |
46 | for (i = 0; i < depth; i++) { | 47 | for (i = 0; i < depth; i++) { |
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, | |||
56 | } else | 57 | } else |
57 | ret += fprintf(fp, "%s", " "); | 58 | ret += fprintf(fp, "%s", " "); |
58 | } | 59 | } |
59 | if (chain->ms.sym) | 60 | fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp); |
60 | ret += fprintf(fp, "%s\n", chain->ms.sym->name); | 61 | fputc('\n', fp); |
61 | else | ||
62 | ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); | ||
63 | |||
64 | return ret; | 62 | return ret; |
65 | } | 63 | } |
66 | 64 | ||
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, | |||
168 | struct rb_node *node; | 166 | struct rb_node *node; |
169 | int i = 0; | 167 | int i = 0; |
170 | int ret = 0; | 168 | int ret = 0; |
169 | char bf[1024]; | ||
171 | 170 | ||
172 | /* | 171 | /* |
173 | * If have one single callchain root, don't bother printing | 172 | * If have one single callchain root, don't bother printing |
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, | |||
196 | } else | 195 | } else |
197 | ret += callchain__fprintf_left_margin(fp, left_margin); | 196 | ret += callchain__fprintf_left_margin(fp, left_margin); |
198 | 197 | ||
199 | if (chain->ms.sym) | 198 | ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf), |
200 | ret += fprintf(fp, " %s\n", chain->ms.sym->name); | 199 | false)); |
201 | else | ||
202 | ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); | ||
203 | 200 | ||
204 | if (++entries_printed == callchain_param.print_limit) | 201 | if (++entries_printed == callchain_param.print_limit) |
205 | break; | 202 | break; |
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, | |||
219 | { | 216 | { |
220 | struct callchain_list *chain; | 217 | struct callchain_list *chain; |
221 | size_t ret = 0; | 218 | size_t ret = 0; |
219 | char bf[1024]; | ||
222 | 220 | ||
223 | if (!node) | 221 | if (!node) |
224 | return 0; | 222 | return 0; |
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, | |||
229 | list_for_each_entry(chain, &node->val, list) { | 227 | list_for_each_entry(chain, &node->val, list) { |
230 | if (chain->ip >= PERF_CONTEXT_MAX) | 228 | if (chain->ip >= PERF_CONTEXT_MAX) |
231 | continue; | 229 | continue; |
232 | if (chain->ms.sym) | 230 | ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain, |
233 | ret += fprintf(fp, " %s\n", chain->ms.sym->name); | 231 | bf, sizeof(bf), false)); |
234 | else | ||
235 | ret += fprintf(fp, " %p\n", | ||
236 | (void *)(long)chain->ip); | ||
237 | } | 232 | } |
238 | 233 | ||
239 | return ret; | 234 | return ret; |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 7dabde14ea54..e5670f1af737 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -17,11 +17,13 @@ | |||
17 | #include "debug.h" | 17 | #include "debug.h" |
18 | #include "annotate.h" | 18 | #include "annotate.h" |
19 | #include "evsel.h" | 19 | #include "evsel.h" |
20 | #include <regex.h> | ||
20 | #include <pthread.h> | 21 | #include <pthread.h> |
21 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
22 | 23 | ||
23 | const char *disassembler_style; | 24 | const char *disassembler_style; |
24 | const char *objdump_path; | 25 | const char *objdump_path; |
26 | static regex_t file_lineno; | ||
25 | 27 | ||
26 | static struct ins *ins__find(const char *name); | 28 | static struct ins *ins__find(const char *name); |
27 | static int disasm_line__parse(char *line, char **namep, char **rawp); | 29 | static int disasm_line__parse(char *line, char **namep, char **rawp); |
@@ -570,13 +572,15 @@ out_free_name: | |||
570 | return -1; | 572 | return -1; |
571 | } | 573 | } |
572 | 574 | ||
573 | static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) | 575 | static struct disasm_line *disasm_line__new(s64 offset, char *line, |
576 | size_t privsize, int line_nr) | ||
574 | { | 577 | { |
575 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); | 578 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); |
576 | 579 | ||
577 | if (dl != NULL) { | 580 | if (dl != NULL) { |
578 | dl->offset = offset; | 581 | dl->offset = offset; |
579 | dl->line = strdup(line); | 582 | dl->line = strdup(line); |
583 | dl->line_nr = line_nr; | ||
580 | if (dl->line == NULL) | 584 | if (dl->line == NULL) |
581 | goto out_delete; | 585 | goto out_delete; |
582 | 586 | ||
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st | |||
788 | * The ops.raw part will be parsed further according to type of the instruction. | 792 | * The ops.raw part will be parsed further according to type of the instruction. |
789 | */ | 793 | */ |
790 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | 794 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, |
791 | FILE *file, size_t privsize) | 795 | FILE *file, size_t privsize, |
796 | int *line_nr) | ||
792 | { | 797 | { |
793 | struct annotation *notes = symbol__annotation(sym); | 798 | struct annotation *notes = symbol__annotation(sym); |
794 | struct disasm_line *dl; | 799 | struct disasm_line *dl; |
795 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; | 800 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; |
796 | size_t line_len; | 801 | size_t line_len; |
797 | s64 line_ip, offset = -1; | 802 | s64 line_ip, offset = -1; |
803 | regmatch_t match[2]; | ||
798 | 804 | ||
799 | if (getline(&line, &line_len, file) < 0) | 805 | if (getline(&line, &line_len, file) < 0) |
800 | return -1; | 806 | return -1; |
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
812 | line_ip = -1; | 818 | line_ip = -1; |
813 | parsed_line = line; | 819 | parsed_line = line; |
814 | 820 | ||
821 | /* /filename:linenr ? Save line number and ignore. */ | ||
822 | if (regexec(&file_lineno, line, 2, match, 0) == 0) { | ||
823 | *line_nr = atoi(line + match[1].rm_so); | ||
824 | return 0; | ||
825 | } | ||
826 | |||
815 | /* | 827 | /* |
816 | * Strip leading spaces: | 828 | * Strip leading spaces: |
817 | */ | 829 | */ |
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
842 | parsed_line = tmp2 + 1; | 854 | parsed_line = tmp2 + 1; |
843 | } | 855 | } |
844 | 856 | ||
845 | dl = disasm_line__new(offset, parsed_line, privsize); | 857 | dl = disasm_line__new(offset, parsed_line, privsize, *line_nr); |
846 | free(line); | 858 | free(line); |
859 | (*line_nr)++; | ||
847 | 860 | ||
848 | if (dl == NULL) | 861 | if (dl == NULL) |
849 | return -1; | 862 | return -1; |
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
869 | return 0; | 882 | return 0; |
870 | } | 883 | } |
871 | 884 | ||
885 | static __attribute__((constructor)) void symbol__init_regexpr(void) | ||
886 | { | ||
887 | regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED); | ||
888 | } | ||
889 | |||
872 | static void delete_last_nop(struct symbol *sym) | 890 | static void delete_last_nop(struct symbol *sym) |
873 | { | 891 | { |
874 | struct annotation *notes = symbol__annotation(sym); | 892 | struct annotation *notes = symbol__annotation(sym); |
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
904 | char symfs_filename[PATH_MAX]; | 922 | char symfs_filename[PATH_MAX]; |
905 | struct kcore_extract kce; | 923 | struct kcore_extract kce; |
906 | bool delete_extract = false; | 924 | bool delete_extract = false; |
925 | int lineno = 0; | ||
907 | 926 | ||
908 | if (filename) | 927 | if (filename) |
909 | symbol__join_symfs(symfs_filename, filename); | 928 | symbol__join_symfs(symfs_filename, filename); |
@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
915 | return -ENOMEM; | 934 | return -ENOMEM; |
916 | } | 935 | } |
917 | goto fallback; | 936 | goto fallback; |
937 | } else if (dso__is_kcore(dso)) { | ||
938 | goto fallback; | ||
918 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || | 939 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || |
919 | strstr(command, "[kernel.kallsyms]") || | 940 | strstr(command, "[kernel.kallsyms]") || |
920 | access(symfs_filename, R_OK)) { | 941 | access(symfs_filename, R_OK)) { |
@@ -982,7 +1003,7 @@ fallback: | |||
982 | snprintf(command, sizeof(command), | 1003 | snprintf(command, sizeof(command), |
983 | "%s %s%s --start-address=0x%016" PRIx64 | 1004 | "%s %s%s --start-address=0x%016" PRIx64 |
984 | " --stop-address=0x%016" PRIx64 | 1005 | " --stop-address=0x%016" PRIx64 |
985 | " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", | 1006 | " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand", |
986 | objdump_path ? objdump_path : "objdump", | 1007 | objdump_path ? objdump_path : "objdump", |
987 | disassembler_style ? "-M " : "", | 1008 | disassembler_style ? "-M " : "", |
988 | disassembler_style ? disassembler_style : "", | 1009 | disassembler_style ? disassembler_style : "", |
@@ -999,7 +1020,8 @@ fallback: | |||
999 | goto out_free_filename; | 1020 | goto out_free_filename; |
1000 | 1021 | ||
1001 | while (!feof(file)) | 1022 | while (!feof(file)) |
1002 | if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) | 1023 | if (symbol__parse_objdump_line(sym, map, file, privsize, |
1024 | &lineno) < 0) | ||
1003 | break; | 1025 | break; |
1004 | 1026 | ||
1005 | /* | 1027 | /* |
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 112d6e268150..0784a9420528 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -58,6 +58,7 @@ struct disasm_line { | |||
58 | char *line; | 58 | char *line; |
59 | char *name; | 59 | char *name; |
60 | struct ins *ins; | 60 | struct ins *ins; |
61 | int line_nr; | ||
61 | struct ins_operands ops; | 62 | struct ins_operands ops; |
62 | }; | 63 | }; |
63 | 64 | ||
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index dd2a3e52ada1..e8d79e5bfaf7 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -18,6 +18,9 @@ | |||
18 | #include "header.h" | 18 | #include "header.h" |
19 | #include "vdso.h" | 19 | #include "vdso.h" |
20 | 20 | ||
21 | |||
22 | static bool no_buildid_cache; | ||
23 | |||
21 | int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, | 24 | int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, |
22 | union perf_event *event, | 25 | union perf_event *event, |
23 | struct perf_sample *sample, | 26 | struct perf_sample *sample, |
@@ -251,6 +254,11 @@ int dsos__hit_all(struct perf_session *session) | |||
251 | return 0; | 254 | return 0; |
252 | } | 255 | } |
253 | 256 | ||
257 | void disable_buildid_cache(void) | ||
258 | { | ||
259 | no_buildid_cache = true; | ||
260 | } | ||
261 | |||
254 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | 262 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, |
255 | const char *name, bool is_kallsyms, bool is_vdso) | 263 | const char *name, bool is_kallsyms, bool is_vdso) |
256 | { | 264 | { |
@@ -404,6 +412,9 @@ int perf_session__cache_build_ids(struct perf_session *session) | |||
404 | int ret; | 412 | int ret; |
405 | char debugdir[PATH_MAX]; | 413 | char debugdir[PATH_MAX]; |
406 | 414 | ||
415 | if (no_buildid_cache) | ||
416 | return 0; | ||
417 | |||
407 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); | 418 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); |
408 | 419 | ||
409 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 420 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 666a3bd4f64e..8236319514d5 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h | |||
@@ -25,5 +25,6 @@ int perf_session__cache_build_ids(struct perf_session *session); | |||
25 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | 25 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, |
26 | const char *name, bool is_kallsyms, bool is_vdso); | 26 | const char *name, bool is_kallsyms, bool is_vdso); |
27 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); | 27 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); |
28 | void disable_buildid_cache(void); | ||
28 | 29 | ||
29 | #endif | 30 | #endif |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 00229809a904..38da69c8c1ff 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -808,3 +808,22 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * | |||
808 | out: | 808 | out: |
809 | return 1; | 809 | return 1; |
810 | } | 810 | } |
811 | |||
812 | char *callchain_list__sym_name(struct callchain_list *cl, | ||
813 | char *bf, size_t bfsize, bool show_dso) | ||
814 | { | ||
815 | int printed; | ||
816 | |||
817 | if (cl->ms.sym) { | ||
818 | printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); | ||
819 | } else | ||
820 | printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
821 | |||
822 | if (show_dso) | ||
823 | scnprintf(bf + printed, bfsize - printed, " %s", | ||
824 | cl->ms.map ? | ||
825 | cl->ms.map->dso->short_name : | ||
826 | "unknown"); | ||
827 | |||
828 | return bf; | ||
829 | } | ||
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 3caccc2c173c..3e1ed15d11f1 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -193,4 +193,7 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, | |||
193 | } | 193 | } |
194 | #endif | 194 | #endif |
195 | 195 | ||
196 | char *callchain_list__sym_name(struct callchain_list *cl, | ||
197 | char *bf, size_t bfsize, bool show_dso); | ||
198 | |||
196 | #endif /* __PERF_CALLCHAIN_H */ | 199 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7e23dae54f1d..cfbe2b99b9aa 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -816,7 +816,15 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
816 | perf_evlist__mmap_get(evlist, idx); | 816 | perf_evlist__mmap_get(evlist, idx); |
817 | } | 817 | } |
818 | 818 | ||
819 | if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) { | 819 | /* |
820 | * The system_wide flag causes a selected event to be opened | ||
821 | * always without a pid. Consequently it will never get a | ||
822 | * POLLHUP, but it is used for tracking in combination with | ||
823 | * other events, so it should not need to be polled anyway. | ||
824 | * Therefore don't add it for polling. | ||
825 | */ | ||
826 | if (!evsel->system_wide && | ||
827 | __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { | ||
820 | perf_evlist__mmap_put(evlist, idx); | 828 | perf_evlist__mmap_put(evlist, idx); |
821 | return -1; | 829 | return -1; |
822 | } | 830 | } |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 34344ffa79ca..f2dc91fb87fa 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -658,6 +658,14 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
658 | attr->mmap_data = track; | 658 | attr->mmap_data = track; |
659 | } | 659 | } |
660 | 660 | ||
661 | /* | ||
662 | * We don't allow user space callchains for function trace | ||
663 | * event, due to issues with page faults while tracing page | ||
664 | * fault handler and its overall trickiness nature. | ||
665 | */ | ||
666 | if (perf_evsel__is_function_event(evsel)) | ||
667 | evsel->attr.exclude_callchain_user = 1; | ||
668 | |||
661 | if (callchain_param.enabled && !evsel->no_aux_samples) | 669 | if (callchain_param.enabled && !evsel->no_aux_samples) |
662 | perf_evsel__config_callgraph(evsel); | 670 | perf_evsel__config_callgraph(evsel); |
663 | 671 | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 05fab7a188dc..b20e40c74468 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include "build-id.h" | 24 | #include "build-id.h" |
25 | #include "data.h" | 25 | #include "data.h" |
26 | 26 | ||
27 | static bool no_buildid_cache = false; | ||
28 | |||
29 | static u32 header_argc; | 27 | static u32 header_argc; |
30 | static const char **header_argv; | 28 | static const char **header_argv; |
31 | 29 | ||
@@ -191,8 +189,7 @@ static int write_build_id(int fd, struct perf_header *h, | |||
191 | pr_debug("failed to write buildid table\n"); | 189 | pr_debug("failed to write buildid table\n"); |
192 | return err; | 190 | return err; |
193 | } | 191 | } |
194 | if (!no_buildid_cache) | 192 | perf_session__cache_build_ids(session); |
195 | perf_session__cache_build_ids(session); | ||
196 | 193 | ||
197 | return 0; | 194 | return 0; |
198 | } | 195 | } |
@@ -2791,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, | |||
2791 | session); | 2788 | session); |
2792 | return 0; | 2789 | return 0; |
2793 | } | 2790 | } |
2794 | |||
2795 | void disable_buildid_cache(void) | ||
2796 | { | ||
2797 | no_buildid_cache = true; | ||
2798 | } | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 52e94902afb1..d97309c87bd6 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1381,6 +1381,34 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, | |||
1381 | return mi; | 1381 | return mi; |
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | static int add_callchain_ip(struct thread *thread, | ||
1385 | struct symbol **parent, | ||
1386 | struct addr_location *root_al, | ||
1387 | int cpumode, | ||
1388 | u64 ip) | ||
1389 | { | ||
1390 | struct addr_location al; | ||
1391 | |||
1392 | al.filtered = 0; | ||
1393 | al.sym = NULL; | ||
1394 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | ||
1395 | ip, &al); | ||
1396 | if (al.sym != NULL) { | ||
1397 | if (sort__has_parent && !*parent && | ||
1398 | symbol__match_regex(al.sym, &parent_regex)) | ||
1399 | *parent = al.sym; | ||
1400 | else if (have_ignore_callees && root_al && | ||
1401 | symbol__match_regex(al.sym, &ignore_callees_regex)) { | ||
1402 | /* Treat this symbol as the root, | ||
1403 | forgetting its callees. */ | ||
1404 | *root_al = al; | ||
1405 | callchain_cursor_reset(&callchain_cursor); | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); | ||
1410 | } | ||
1411 | |||
1384 | struct branch_info *sample__resolve_bstack(struct perf_sample *sample, | 1412 | struct branch_info *sample__resolve_bstack(struct perf_sample *sample, |
1385 | struct addr_location *al) | 1413 | struct addr_location *al) |
1386 | { | 1414 | { |
@@ -1427,7 +1455,6 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1427 | 1455 | ||
1428 | for (i = 0; i < chain_nr; i++) { | 1456 | for (i = 0; i < chain_nr; i++) { |
1429 | u64 ip; | 1457 | u64 ip; |
1430 | struct addr_location al; | ||
1431 | 1458 | ||
1432 | if (callchain_param.order == ORDER_CALLEE) | 1459 | if (callchain_param.order == ORDER_CALLEE) |
1433 | j = i; | 1460 | j = i; |
@@ -1464,24 +1491,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1464 | continue; | 1491 | continue; |
1465 | } | 1492 | } |
1466 | 1493 | ||
1467 | al.filtered = 0; | 1494 | err = add_callchain_ip(thread, parent, root_al, |
1468 | thread__find_addr_location(thread, cpumode, | 1495 | cpumode, ip); |
1469 | MAP__FUNCTION, ip, &al); | 1496 | if (err == -EINVAL) |
1470 | if (al.sym != NULL) { | 1497 | break; |
1471 | if (sort__has_parent && !*parent && | ||
1472 | symbol__match_regex(al.sym, &parent_regex)) | ||
1473 | *parent = al.sym; | ||
1474 | else if (have_ignore_callees && root_al && | ||
1475 | symbol__match_regex(al.sym, &ignore_callees_regex)) { | ||
1476 | /* Treat this symbol as the root, | ||
1477 | forgetting its callees. */ | ||
1478 | *root_al = al; | ||
1479 | callchain_cursor_reset(&callchain_cursor); | ||
1480 | } | ||
1481 | } | ||
1482 | |||
1483 | err = callchain_cursor_append(&callchain_cursor, | ||
1484 | ip, al.map, al.sym); | ||
1485 | if (err) | 1498 | if (err) |
1486 | return err; | 1499 | return err; |
1487 | } | 1500 | } |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 9402885a77f3..82a5596241a7 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -309,7 +309,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) | |||
309 | static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, | 309 | static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, |
310 | size_t size, unsigned int width) | 310 | size_t size, unsigned int width) |
311 | { | 311 | { |
312 | return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline); | 312 | return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline); |
313 | } | 313 | } |
314 | 314 | ||
315 | struct sort_entry sort_srcline = { | 315 | struct sort_entry sort_srcline = { |
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index f3e4bc5fe5d2..77c180637138 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr) | |||
274 | if (!addr2line(dso_name, addr, &file, &line, dso)) | 274 | if (!addr2line(dso_name, addr, &file, &line, dso)) |
275 | goto out; | 275 | goto out; |
276 | 276 | ||
277 | if (asprintf(&srcline, "%s:%u", file, line) < 0) { | 277 | if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) { |
278 | free(file); | 278 | free(file); |
279 | goto out; | 279 | goto out; |
280 | } | 280 | } |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index c9541fea9514..fa585c63f56a 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -341,7 +341,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, | |||
341 | 341 | ||
342 | if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { | 342 | if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { |
343 | dso__set_build_id(dso, build_id); | 343 | dso__set_build_id(dso, build_id); |
344 | return 1; | ||
345 | } | 344 | } |
346 | return 0; | 345 | return 0; |
347 | } | 346 | } |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index a2157f0ef1df..9ebc8b1f9be5 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -103,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread) | |||
103 | return last; | 103 | return last; |
104 | } | 104 | } |
105 | 105 | ||
106 | /* CHECKME: time should always be 0 if event aren't ordered */ | ||
107 | int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, | 106 | int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, |
108 | bool exec) | 107 | bool exec) |
109 | { | 108 | { |
110 | struct comm *new, *curr = thread__comm(thread); | 109 | struct comm *new, *curr = thread__comm(thread); |
111 | int err; | 110 | int err; |
112 | 111 | ||
113 | /* Override latest entry if it had no specific time coverage */ | 112 | /* Override the default :tid entry */ |
114 | if (!curr->start && !curr->exec) { | 113 | if (!thread->comm_set) { |
115 | err = comm__override(curr, str, timestamp, exec); | 114 | err = comm__override(curr, str, timestamp, exec); |
116 | if (err) | 115 | if (err) |
117 | return err; | 116 | return err; |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 7dc44cfe25b3..76d23d83eae5 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NOR | |||
154 | 154 | ||
155 | extern int prefixcmp(const char *str, const char *prefix); | 155 | extern int prefixcmp(const char *str, const char *prefix); |
156 | extern void set_buildid_dir(void); | 156 | extern void set_buildid_dir(void); |
157 | extern void disable_buildid_cache(void); | ||
158 | 157 | ||
159 | static inline const char *skip_prefix(const char *str, const char *prefix) | 158 | static inline const char *skip_prefix(const char *str, const char *prefix) |
160 | { | 159 | { |