diff options
| -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 | { |
