diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-10-01 03:03:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-10-01 03:03:57 -0400 |
commit | 4bc6a58fcbf63dc3da9870c41eeab1bd030bc585 (patch) | |
tree | 965af8015bcc5a9375e8858bf6aea52f5e45357c | |
parent | 9c17dbc6eb73bdd8a6aaea1baefd37ff78d86148 (diff) | |
parent | 7f8d1ade1b19f684ed3a7c4fb1dc5d347127b438 (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:
User visible changes:
- By default use the most precise "cycles" hw counter available, i.e.
when the user doesn't specify any event, it will try using cycles:ppp,
cycles:pp, etc. (Arnaldo Carvalho de Melo)
- Remove blank lines, headers when piping output in 'perf list', so that it can
be sanely used with 'wc -l', etc. (Arnaldo Carvalho de Melo)
- Amend documentation about max_stack and synthesized callchains. (Adrian Hunter)
- Fix 'perf probe -l' for probes added to kernel module functions. (Masami Hiramatsu)
Build fixes:
- Fix shadowed declarations that break the build on older distros. (Jiri Olsa)
- Fix build break on powerpc due to sample_reg_masks. (Sukadev Bhattiprolu)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/include/linux/err.h | 4 | ||||
-rw-r--r-- | tools/lib/symbol/kallsyms.c | 6 | ||||
-rw-r--r-- | tools/lib/symbol/kallsyms.h | 4 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 2 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-list.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/vmlinux-kallsyms.c | 4 | ||||
-rw-r--r-- | tools/perf/util/Build | 2 | ||||
-rw-r--r-- | tools/perf/util/event.c | 7 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 22 | ||||
-rw-r--r-- | tools/perf/util/intel-pt.c | 2 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 26 | ||||
-rw-r--r-- | tools/perf/util/machine.h | 8 | ||||
-rw-r--r-- | tools/perf/util/map.c | 21 | ||||
-rw-r--r-- | tools/perf/util/map.h | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 53 | ||||
-rw-r--r-- | tools/perf/util/perf_regs.c | 2 | ||||
-rw-r--r-- | tools/perf/util/perf_regs.h | 1 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 2 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 96 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 58 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 2 |
24 files changed, 224 insertions, 108 deletions
diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h index c9ada48f5156..bdc3dd8131d4 100644 --- a/tools/include/linux/err.h +++ b/tools/include/linux/err.h | |||
@@ -31,9 +31,9 @@ | |||
31 | 31 | ||
32 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) | 32 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) |
33 | 33 | ||
34 | static inline void * __must_check ERR_PTR(long error) | 34 | static inline void * __must_check ERR_PTR(long error_) |
35 | { | 35 | { |
36 | return (void *) error; | 36 | return (void *) error_; |
37 | } | 37 | } |
38 | 38 | ||
39 | static inline long __must_check PTR_ERR(__force const void *ptr) | 39 | static inline long __must_check PTR_ERR(__force const void *ptr) |
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c index 18bc271a4bbc..5e431077fcd6 100644 --- a/tools/lib/symbol/kallsyms.c +++ b/tools/lib/symbol/kallsyms.c | |||
@@ -2,6 +2,12 @@ | |||
2 | #include <stdio.h> | 2 | #include <stdio.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | 4 | ||
5 | u8 kallsyms2elf_type(char type) | ||
6 | { | ||
7 | type = tolower(type); | ||
8 | return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT; | ||
9 | } | ||
10 | |||
5 | int kallsyms__parse(const char *filename, void *arg, | 11 | int kallsyms__parse(const char *filename, void *arg, |
6 | int (*process_symbol)(void *arg, const char *name, | 12 | int (*process_symbol)(void *arg, const char *name, |
7 | char type, u64 start)) | 13 | char type, u64 start)) |
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h index 6084f5e18b3c..4071316a766e 100644 --- a/tools/lib/symbol/kallsyms.h +++ b/tools/lib/symbol/kallsyms.h | |||
@@ -9,7 +9,7 @@ | |||
9 | #define KSYM_NAME_LEN 256 | 9 | #define KSYM_NAME_LEN 256 |
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | static inline u8 kallsyms2elf_type(char type) | 12 | static inline u8 kallsyms2elf_binding(char type) |
13 | { | 13 | { |
14 | if (type == 'W') | 14 | if (type == 'W') |
15 | return STB_WEAK; | 15 | return STB_WEAK; |
@@ -17,6 +17,8 @@ static inline u8 kallsyms2elf_type(char type) | |||
17 | return isupper(type) ? STB_GLOBAL : STB_LOCAL; | 17 | return isupper(type) ? STB_GLOBAL : STB_LOCAL; |
18 | } | 18 | } |
19 | 19 | ||
20 | u8 kallsyms2elf_type(char type); | ||
21 | |||
20 | int kallsyms__parse(const char *filename, void *arg, | 22 | int kallsyms__parse(const char *filename, void *arg, |
21 | int (*process_symbol)(void *arg, const char *name, | 23 | int (*process_symbol)(void *arg, const char *name, |
22 | char type, u64 start)); | 24 | char type, u64 start)); |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index b941d5e07e28..ce499035e6d8 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -205,6 +205,8 @@ OPTIONS | |||
205 | beyond the specified depth will be ignored. This is a trade-off | 205 | beyond the specified depth will be ignored. This is a trade-off |
206 | between information loss and faster processing especially for | 206 | between information loss and faster processing especially for |
207 | workloads that can have a very long callchain stack. | 207 | workloads that can have a very long callchain stack. |
208 | Note that when using the --itrace option the synthesized callchain size | ||
209 | will override this value if the synthesized callchain size is bigger. | ||
208 | 210 | ||
209 | Default: 127 | 211 | Default: 127 |
210 | 212 | ||
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 23b1faaaa4cc..93ce665f976f 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -329,7 +329,7 @@ static int build_alloc_func_list(void) | |||
329 | return -EINVAL; | 329 | return -EINVAL; |
330 | } | 330 | } |
331 | 331 | ||
332 | kernel_map = machine->vmlinux_maps[MAP__FUNCTION]; | 332 | kernel_map = machine__kernel_map(machine); |
333 | if (map__load(kernel_map, NULL) < 0) { | 333 | if (map__load(kernel_map, NULL) < 0) { |
334 | pr_err("cannot load kernel map\n"); | 334 | pr_err("cannot load kernel map\n"); |
335 | return -ENOENT; | 335 | return -ENOENT; |
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index af5bd0514108..602414040344 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c | |||
@@ -36,7 +36,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
36 | 36 | ||
37 | setup_pager(); | 37 | setup_pager(); |
38 | 38 | ||
39 | if (!raw_dump) | 39 | if (!raw_dump && pager_in_use()) |
40 | printf("\nList of pre-defined events (to be used in -e):\n\n"); | 40 | printf("\nList of pre-defined events (to be used in -e):\n\n"); |
41 | 41 | ||
42 | if (argc == 0) { | 42 | if (argc == 0) { |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 37c9f5125887..b5623639f67d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -387,7 +387,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
387 | 387 | ||
388 | static void report__warn_kptr_restrict(const struct report *rep) | 388 | static void report__warn_kptr_restrict(const struct report *rep) |
389 | { | 389 | { |
390 | struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; | 390 | struct map *kernel_map = machine__kernel_map(&rep->session->machines.host); |
391 | struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; | 391 | struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; |
392 | 392 | ||
393 | if (kernel_map == NULL || | 393 | if (kernel_map == NULL || |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 2d21183bd661..49b1959dda41 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -473,7 +473,7 @@ static int do_test_code_reading(bool try_kcore) | |||
473 | symbol_conf.kallsyms_name = "/proc/kallsyms"; | 473 | symbol_conf.kallsyms_name = "/proc/kallsyms"; |
474 | 474 | ||
475 | /* Load kernel map */ | 475 | /* Load kernel map */ |
476 | map = machine->vmlinux_maps[MAP__FUNCTION]; | 476 | map = machine__kernel_map(machine); |
477 | ret = map__load(map, NULL); | 477 | ret = map__load(map, NULL); |
478 | if (ret < 0) { | 478 | if (ret < 0) { |
479 | pr_debug("map__load failed\n"); | 479 | pr_debug("map__load failed\n"); |
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index b34c5fc829ae..d677e018e504 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c | |||
@@ -68,7 +68,7 @@ int test__vmlinux_matches_kallsyms(void) | |||
68 | * to see if the running kernel was relocated by checking if it has the | 68 | * to see if the running kernel was relocated by checking if it has the |
69 | * same value in the vmlinux file we load. | 69 | * same value in the vmlinux file we load. |
70 | */ | 70 | */ |
71 | kallsyms_map = machine__kernel_map(&kallsyms, type); | 71 | kallsyms_map = machine__kernel_map(&kallsyms); |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * Step 5: | 74 | * Step 5: |
@@ -80,7 +80,7 @@ int test__vmlinux_matches_kallsyms(void) | |||
80 | goto out; | 80 | goto out; |
81 | } | 81 | } |
82 | 82 | ||
83 | vmlinux_map = machine__kernel_map(&vmlinux, type); | 83 | vmlinux_map = machine__kernel_map(&vmlinux); |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Step 6: | 86 | * Step 6: |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4bc7a9ab45b1..9217119c4108 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -18,6 +18,7 @@ libperf-y += levenshtein.o | |||
18 | libperf-y += llvm-utils.o | 18 | libperf-y += llvm-utils.o |
19 | libperf-y += parse-options.o | 19 | libperf-y += parse-options.o |
20 | libperf-y += parse-events.o | 20 | libperf-y += parse-events.o |
21 | libperf-y += perf_regs.o | ||
21 | libperf-y += path.o | 22 | libperf-y += path.o |
22 | libperf-y += rbtree.o | 23 | libperf-y += rbtree.o |
23 | libperf-y += bitmap.o | 24 | libperf-y += bitmap.o |
@@ -104,7 +105,6 @@ libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o | |||
104 | 105 | ||
105 | libperf-y += scripting-engines/ | 106 | libperf-y += scripting-engines/ |
106 | 107 | ||
107 | libperf-$(CONFIG_PERF_REGS) += perf_regs.o | ||
108 | libperf-$(CONFIG_ZLIB) += zlib.o | 108 | libperf-$(CONFIG_ZLIB) += zlib.o |
109 | libperf-$(CONFIG_LZMA) += lzma.o | 109 | libperf-$(CONFIG_LZMA) += lzma.o |
110 | 110 | ||
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index b1bb348ec3b6..cb98b5af9e17 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -649,12 +649,12 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | |||
649 | size_t size; | 649 | size_t size; |
650 | const char *mmap_name; | 650 | const char *mmap_name; |
651 | char name_buff[PATH_MAX]; | 651 | char name_buff[PATH_MAX]; |
652 | struct map *map; | 652 | struct map *map = machine__kernel_map(machine); |
653 | struct kmap *kmap; | 653 | struct kmap *kmap; |
654 | int err; | 654 | int err; |
655 | union perf_event *event; | 655 | union perf_event *event; |
656 | 656 | ||
657 | if (machine->vmlinux_maps[0] == NULL) | 657 | if (map == NULL) |
658 | return -1; | 658 | return -1; |
659 | 659 | ||
660 | /* | 660 | /* |
@@ -680,7 +680,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | |||
680 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; | 680 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
681 | } | 681 | } |
682 | 682 | ||
683 | map = machine->vmlinux_maps[MAP__FUNCTION]; | ||
684 | kmap = map__kmap(map); | 683 | kmap = map__kmap(map); |
685 | size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), | 684 | size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), |
686 | "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; | 685 | "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; |
@@ -1008,7 +1007,7 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
1008 | * it now. | 1007 | * it now. |
1009 | */ | 1008 | */ |
1010 | if (cpumode == PERF_RECORD_MISC_KERNEL && | 1009 | if (cpumode == PERF_RECORD_MISC_KERNEL && |
1011 | machine->vmlinux_maps[MAP__FUNCTION] == NULL) | 1010 | machine__kernel_map(machine) == NULL) |
1012 | machine__create_kernel_maps(machine); | 1011 | machine__create_kernel_maps(machine); |
1013 | 1012 | ||
1014 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); | 1013 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 89546228b8ed..e7e195d867ea 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -205,6 +205,20 @@ void perf_evlist__set_leader(struct perf_evlist *evlist) | |||
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | static void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) | ||
209 | { | ||
210 | attr->precise_ip = 3; | ||
211 | |||
212 | while (attr->precise_ip != 0) { | ||
213 | int fd = sys_perf_event_open(attr, 0, -1, -1, 0); | ||
214 | if (fd != -1) { | ||
215 | close(fd); | ||
216 | break; | ||
217 | } | ||
218 | --attr->precise_ip; | ||
219 | } | ||
220 | } | ||
221 | |||
208 | int perf_evlist__add_default(struct perf_evlist *evlist) | 222 | int perf_evlist__add_default(struct perf_evlist *evlist) |
209 | { | 223 | { |
210 | struct perf_event_attr attr = { | 224 | struct perf_event_attr attr = { |
@@ -215,13 +229,15 @@ int perf_evlist__add_default(struct perf_evlist *evlist) | |||
215 | 229 | ||
216 | event_attr_init(&attr); | 230 | event_attr_init(&attr); |
217 | 231 | ||
232 | perf_event_attr__set_max_precise_ip(&attr); | ||
233 | |||
218 | evsel = perf_evsel__new(&attr); | 234 | evsel = perf_evsel__new(&attr); |
219 | if (evsel == NULL) | 235 | if (evsel == NULL) |
220 | goto error; | 236 | goto error; |
221 | 237 | ||
222 | /* use strdup() because free(evsel) assumes name is allocated */ | 238 | /* use asprintf() because free(evsel) assumes name is allocated */ |
223 | evsel->name = strdup("cycles"); | 239 | if (asprintf(&evsel->name, "cycles%.*s", |
224 | if (!evsel->name) | 240 | attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) |
225 | goto error_free; | 241 | goto error_free; |
226 | 242 | ||
227 | perf_evlist__add(evlist, evsel); | 243 | perf_evlist__add(evlist, evsel); |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 03ff072b5993..97f963a3dcb9 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
@@ -1268,7 +1268,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip) | |||
1268 | if (ptss_ip) | 1268 | if (ptss_ip) |
1269 | *ptss_ip = 0; | 1269 | *ptss_ip = 0; |
1270 | 1270 | ||
1271 | map = machine__kernel_map(machine, MAP__FUNCTION); | 1271 | map = machine__kernel_map(machine); |
1272 | if (!map) | 1272 | if (!map) |
1273 | return 0; | 1273 | return 0; |
1274 | 1274 | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index fd1efeafb343..76fe167c359e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -625,7 +625,7 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) | |||
625 | { | 625 | { |
626 | int i; | 626 | int i; |
627 | size_t printed = 0; | 627 | size_t printed = 0; |
628 | struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; | 628 | struct dso *kdso = machine__kernel_map(machine)->dso; |
629 | 629 | ||
630 | if (kdso->has_build_id) { | 630 | if (kdso->has_build_id) { |
631 | char filename[PATH_MAX]; | 631 | char filename[PATH_MAX]; |
@@ -741,6 +741,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | |||
741 | 741 | ||
742 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 742 | for (type = 0; type < MAP__NR_TYPES; ++type) { |
743 | struct kmap *kmap; | 743 | struct kmap *kmap; |
744 | struct map *map; | ||
744 | 745 | ||
745 | machine->vmlinux_maps[type] = map__new2(start, kernel, type); | 746 | machine->vmlinux_maps[type] = map__new2(start, kernel, type); |
746 | if (machine->vmlinux_maps[type] == NULL) | 747 | if (machine->vmlinux_maps[type] == NULL) |
@@ -749,13 +750,13 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | |||
749 | machine->vmlinux_maps[type]->map_ip = | 750 | machine->vmlinux_maps[type]->map_ip = |
750 | machine->vmlinux_maps[type]->unmap_ip = | 751 | machine->vmlinux_maps[type]->unmap_ip = |
751 | identity__map_ip; | 752 | identity__map_ip; |
752 | kmap = map__kmap(machine->vmlinux_maps[type]); | 753 | map = __machine__kernel_map(machine, type); |
754 | kmap = map__kmap(map); | ||
753 | if (!kmap) | 755 | if (!kmap) |
754 | return -1; | 756 | return -1; |
755 | 757 | ||
756 | kmap->kmaps = &machine->kmaps; | 758 | kmap->kmaps = &machine->kmaps; |
757 | map_groups__insert(&machine->kmaps, | 759 | map_groups__insert(&machine->kmaps, map); |
758 | machine->vmlinux_maps[type]); | ||
759 | } | 760 | } |
760 | 761 | ||
761 | return 0; | 762 | return 0; |
@@ -767,13 +768,13 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
767 | 768 | ||
768 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 769 | for (type = 0; type < MAP__NR_TYPES; ++type) { |
769 | struct kmap *kmap; | 770 | struct kmap *kmap; |
771 | struct map *map = __machine__kernel_map(machine, type); | ||
770 | 772 | ||
771 | if (machine->vmlinux_maps[type] == NULL) | 773 | if (map == NULL) |
772 | continue; | 774 | continue; |
773 | 775 | ||
774 | kmap = map__kmap(machine->vmlinux_maps[type]); | 776 | kmap = map__kmap(map); |
775 | map_groups__remove(&machine->kmaps, | 777 | map_groups__remove(&machine->kmaps, map); |
776 | machine->vmlinux_maps[type]); | ||
777 | if (kmap && kmap->ref_reloc_sym) { | 778 | if (kmap && kmap->ref_reloc_sym) { |
778 | /* | 779 | /* |
779 | * ref_reloc_sym is shared among all maps, so free just | 780 | * ref_reloc_sym is shared among all maps, so free just |
@@ -867,7 +868,7 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid) | |||
867 | int machine__load_kallsyms(struct machine *machine, const char *filename, | 868 | int machine__load_kallsyms(struct machine *machine, const char *filename, |
868 | enum map_type type, symbol_filter_t filter) | 869 | enum map_type type, symbol_filter_t filter) |
869 | { | 870 | { |
870 | struct map *map = machine->vmlinux_maps[type]; | 871 | struct map *map = machine__kernel_map(machine); |
871 | int ret = dso__load_kallsyms(map->dso, filename, map, filter); | 872 | int ret = dso__load_kallsyms(map->dso, filename, map, filter); |
872 | 873 | ||
873 | if (ret > 0) { | 874 | if (ret > 0) { |
@@ -886,7 +887,7 @@ int machine__load_kallsyms(struct machine *machine, const char *filename, | |||
886 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, | 887 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, |
887 | symbol_filter_t filter) | 888 | symbol_filter_t filter) |
888 | { | 889 | { |
889 | struct map *map = machine->vmlinux_maps[type]; | 890 | struct map *map = machine__kernel_map(machine); |
890 | int ret = dso__load_vmlinux_path(map->dso, map, filter); | 891 | int ret = dso__load_vmlinux_path(map->dso, map, filter); |
891 | 892 | ||
892 | if (ret > 0) | 893 | if (ret > 0) |
@@ -1244,8 +1245,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
1244 | /* | 1245 | /* |
1245 | * preload dso of guest kernel and modules | 1246 | * preload dso of guest kernel and modules |
1246 | */ | 1247 | */ |
1247 | dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], | 1248 | dso__load(kernel, machine__kernel_map(machine), NULL); |
1248 | NULL); | ||
1249 | } | 1249 | } |
1250 | } | 1250 | } |
1251 | return 0; | 1251 | return 0; |
@@ -1997,7 +1997,7 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, | |||
1997 | 1997 | ||
1998 | int machine__get_kernel_start(struct machine *machine) | 1998 | int machine__get_kernel_start(struct machine *machine) |
1999 | { | 1999 | { |
2000 | struct map *map = machine__kernel_map(machine, MAP__FUNCTION); | 2000 | struct map *map = machine__kernel_map(machine); |
2001 | int err = 0; | 2001 | int err = 0; |
2002 | 2002 | ||
2003 | /* | 2003 | /* |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 9dfc4281f940..2c2b443df5ba 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -48,11 +48,17 @@ struct machine { | |||
48 | }; | 48 | }; |
49 | 49 | ||
50 | static inline | 50 | static inline |
51 | struct map *machine__kernel_map(struct machine *machine, enum map_type type) | 51 | struct map *__machine__kernel_map(struct machine *machine, enum map_type type) |
52 | { | 52 | { |
53 | return machine->vmlinux_maps[type]; | 53 | return machine->vmlinux_maps[type]; |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline | ||
57 | struct map *machine__kernel_map(struct machine *machine) | ||
58 | { | ||
59 | return __machine__kernel_map(machine, MAP__FUNCTION); | ||
60 | } | ||
61 | |||
56 | int machine__get_kernel_start(struct machine *machine); | 62 | int machine__get_kernel_start(struct machine *machine); |
57 | 63 | ||
58 | static inline u64 machine__kernel_start(struct machine *machine) | 64 | static inline u64 machine__kernel_start(struct machine *machine) |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index b1c475d9b240..4e38c396a897 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -235,7 +235,7 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
235 | */ | 235 | */ |
236 | bool __map__is_kernel(const struct map *map) | 236 | bool __map__is_kernel(const struct map *map) |
237 | { | 237 | { |
238 | return map->groups->machine->vmlinux_maps[map->type] == map; | 238 | return __machine__kernel_map(map->groups->machine, map->type) == map; |
239 | } | 239 | } |
240 | 240 | ||
241 | static void map__exit(struct map *map) | 241 | static void map__exit(struct map *map) |
@@ -553,13 +553,9 @@ struct symbol *map_groups__find_symbol(struct map_groups *mg, | |||
553 | return NULL; | 553 | return NULL; |
554 | } | 554 | } |
555 | 555 | ||
556 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | 556 | struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, |
557 | enum map_type type, | 557 | struct map **mapp, symbol_filter_t filter) |
558 | const char *name, | ||
559 | struct map **mapp, | ||
560 | symbol_filter_t filter) | ||
561 | { | 558 | { |
562 | struct maps *maps = &mg->maps[type]; | ||
563 | struct symbol *sym; | 559 | struct symbol *sym; |
564 | struct rb_node *nd; | 560 | struct rb_node *nd; |
565 | 561 | ||
@@ -583,6 +579,17 @@ out: | |||
583 | return sym; | 579 | return sym; |
584 | } | 580 | } |
585 | 581 | ||
582 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | ||
583 | enum map_type type, | ||
584 | const char *name, | ||
585 | struct map **mapp, | ||
586 | symbol_filter_t filter) | ||
587 | { | ||
588 | struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp, filter); | ||
589 | |||
590 | return sym; | ||
591 | } | ||
592 | |||
586 | int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) | 593 | int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) |
587 | { | 594 | { |
588 | if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { | 595 | if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 57829e89b78b..7309d64ce39e 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -190,6 +190,8 @@ void maps__remove(struct maps *maps, struct map *map); | |||
190 | struct map *maps__find(struct maps *maps, u64 addr); | 190 | struct map *maps__find(struct maps *maps, u64 addr); |
191 | struct map *maps__first(struct maps *maps); | 191 | struct map *maps__first(struct maps *maps); |
192 | struct map *map__next(struct map *map); | 192 | struct map *map__next(struct map *map); |
193 | struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, | ||
194 | struct map **mapp, symbol_filter_t filter); | ||
193 | void map_groups__init(struct map_groups *mg, struct machine *machine); | 195 | void map_groups__init(struct map_groups *mg, struct machine *machine); |
194 | void map_groups__exit(struct map_groups *mg); | 196 | void map_groups__exit(struct map_groups *mg); |
195 | int map_groups__clone(struct map_groups *mg, | 197 | int map_groups__clone(struct map_groups *mg, |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 5ffb356cbcc6..5d0cfce2599b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -389,7 +389,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, | |||
389 | return add_event(list, idx, &attr, name, NULL); | 389 | return add_event(list, idx, &attr, name, NULL); |
390 | } | 390 | } |
391 | 391 | ||
392 | static void tracepoint_error(struct parse_events_error *error, int err, | 392 | static void tracepoint_error(struct parse_events_error *e, int err, |
393 | char *sys, char *name) | 393 | char *sys, char *name) |
394 | { | 394 | { |
395 | char help[BUFSIZ]; | 395 | char help[BUFSIZ]; |
@@ -402,30 +402,30 @@ static void tracepoint_error(struct parse_events_error *error, int err, | |||
402 | 402 | ||
403 | switch (err) { | 403 | switch (err) { |
404 | case EACCES: | 404 | case EACCES: |
405 | error->str = strdup("can't access trace events"); | 405 | e->str = strdup("can't access trace events"); |
406 | break; | 406 | break; |
407 | case ENOENT: | 407 | case ENOENT: |
408 | error->str = strdup("unknown tracepoint"); | 408 | e->str = strdup("unknown tracepoint"); |
409 | break; | 409 | break; |
410 | default: | 410 | default: |
411 | error->str = strdup("failed to add tracepoint"); | 411 | e->str = strdup("failed to add tracepoint"); |
412 | break; | 412 | break; |
413 | } | 413 | } |
414 | 414 | ||
415 | tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); | 415 | tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); |
416 | error->help = strdup(help); | 416 | e->help = strdup(help); |
417 | } | 417 | } |
418 | 418 | ||
419 | static int add_tracepoint(struct list_head *list, int *idx, | 419 | static int add_tracepoint(struct list_head *list, int *idx, |
420 | char *sys_name, char *evt_name, | 420 | char *sys_name, char *evt_name, |
421 | struct parse_events_error *error __maybe_unused, | 421 | struct parse_events_error *err, |
422 | struct list_head *head_config) | 422 | struct list_head *head_config) |
423 | { | 423 | { |
424 | struct perf_evsel *evsel; | 424 | struct perf_evsel *evsel; |
425 | 425 | ||
426 | evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); | 426 | evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); |
427 | if (IS_ERR(evsel)) { | 427 | if (IS_ERR(evsel)) { |
428 | tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name); | 428 | tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name); |
429 | return PTR_ERR(evsel); | 429 | return PTR_ERR(evsel); |
430 | } | 430 | } |
431 | 431 | ||
@@ -443,7 +443,7 @@ static int add_tracepoint(struct list_head *list, int *idx, | |||
443 | 443 | ||
444 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, | 444 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, |
445 | char *sys_name, char *evt_name, | 445 | char *sys_name, char *evt_name, |
446 | struct parse_events_error *error, | 446 | struct parse_events_error *err, |
447 | struct list_head *head_config) | 447 | struct list_head *head_config) |
448 | { | 448 | { |
449 | char evt_path[MAXPATHLEN]; | 449 | char evt_path[MAXPATHLEN]; |
@@ -454,7 +454,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
454 | snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); | 454 | snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); |
455 | evt_dir = opendir(evt_path); | 455 | evt_dir = opendir(evt_path); |
456 | if (!evt_dir) { | 456 | if (!evt_dir) { |
457 | tracepoint_error(error, errno, sys_name, evt_name); | 457 | tracepoint_error(err, errno, sys_name, evt_name); |
458 | return -1; | 458 | return -1; |
459 | } | 459 | } |
460 | 460 | ||
@@ -469,7 +469,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
469 | continue; | 469 | continue; |
470 | 470 | ||
471 | ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, | 471 | ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, |
472 | error, head_config); | 472 | err, head_config); |
473 | } | 473 | } |
474 | 474 | ||
475 | closedir(evt_dir); | 475 | closedir(evt_dir); |
@@ -478,19 +478,19 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
478 | 478 | ||
479 | static int add_tracepoint_event(struct list_head *list, int *idx, | 479 | static int add_tracepoint_event(struct list_head *list, int *idx, |
480 | char *sys_name, char *evt_name, | 480 | char *sys_name, char *evt_name, |
481 | struct parse_events_error *error, | 481 | struct parse_events_error *err, |
482 | struct list_head *head_config) | 482 | struct list_head *head_config) |
483 | { | 483 | { |
484 | return strpbrk(evt_name, "*?") ? | 484 | return strpbrk(evt_name, "*?") ? |
485 | add_tracepoint_multi_event(list, idx, sys_name, evt_name, | 485 | add_tracepoint_multi_event(list, idx, sys_name, evt_name, |
486 | error, head_config) : | 486 | err, head_config) : |
487 | add_tracepoint(list, idx, sys_name, evt_name, | 487 | add_tracepoint(list, idx, sys_name, evt_name, |
488 | error, head_config); | 488 | err, head_config); |
489 | } | 489 | } |
490 | 490 | ||
491 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | 491 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, |
492 | char *sys_name, char *evt_name, | 492 | char *sys_name, char *evt_name, |
493 | struct parse_events_error *error, | 493 | struct parse_events_error *err, |
494 | struct list_head *head_config) | 494 | struct list_head *head_config) |
495 | { | 495 | { |
496 | struct dirent *events_ent; | 496 | struct dirent *events_ent; |
@@ -499,7 +499,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
499 | 499 | ||
500 | events_dir = opendir(tracing_events_path); | 500 | events_dir = opendir(tracing_events_path); |
501 | if (!events_dir) { | 501 | if (!events_dir) { |
502 | tracepoint_error(error, errno, sys_name, evt_name); | 502 | tracepoint_error(err, errno, sys_name, evt_name); |
503 | return -1; | 503 | return -1; |
504 | } | 504 | } |
505 | 505 | ||
@@ -515,7 +515,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
515 | continue; | 515 | continue; |
516 | 516 | ||
517 | ret = add_tracepoint_event(list, idx, events_ent->d_name, | 517 | ret = add_tracepoint_event(list, idx, events_ent->d_name, |
518 | evt_name, error, head_config); | 518 | evt_name, err, head_config); |
519 | } | 519 | } |
520 | 520 | ||
521 | closedir(events_dir); | 521 | closedir(events_dir); |
@@ -767,23 +767,23 @@ do { \ | |||
767 | 767 | ||
768 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | 768 | int parse_events_add_tracepoint(struct list_head *list, int *idx, |
769 | char *sys, char *event, | 769 | char *sys, char *event, |
770 | struct parse_events_error *error, | 770 | struct parse_events_error *err, |
771 | struct list_head *head_config) | 771 | struct list_head *head_config) |
772 | { | 772 | { |
773 | if (head_config) { | 773 | if (head_config) { |
774 | struct perf_event_attr attr; | 774 | struct perf_event_attr attr; |
775 | 775 | ||
776 | if (config_attr(&attr, head_config, error, | 776 | if (config_attr(&attr, head_config, err, |
777 | config_term_tracepoint)) | 777 | config_term_tracepoint)) |
778 | return -EINVAL; | 778 | return -EINVAL; |
779 | } | 779 | } |
780 | 780 | ||
781 | if (strpbrk(sys, "*?")) | 781 | if (strpbrk(sys, "*?")) |
782 | return add_tracepoint_multi_sys(list, idx, sys, event, | 782 | return add_tracepoint_multi_sys(list, idx, sys, event, |
783 | error, head_config); | 783 | err, head_config); |
784 | else | 784 | else |
785 | return add_tracepoint_event(list, idx, sys, event, | 785 | return add_tracepoint_event(list, idx, sys, event, |
786 | error, head_config); | 786 | err, head_config); |
787 | } | 787 | } |
788 | 788 | ||
789 | int parse_events_add_numeric(struct parse_events_evlist *data, | 789 | int parse_events_add_numeric(struct parse_events_evlist *data, |
@@ -1534,7 +1534,7 @@ restart: | |||
1534 | printf(" %-50s [%s]\n", evt_list[evt_i++], | 1534 | printf(" %-50s [%s]\n", evt_list[evt_i++], |
1535 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); | 1535 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); |
1536 | } | 1536 | } |
1537 | if (evt_num) | 1537 | if (evt_num && pager_in_use()) |
1538 | printf("\n"); | 1538 | printf("\n"); |
1539 | 1539 | ||
1540 | out_free: | 1540 | out_free: |
@@ -1690,7 +1690,7 @@ restart: | |||
1690 | printf(" %-50s [%s]\n", evt_list[evt_i++], | 1690 | printf(" %-50s [%s]\n", evt_list[evt_i++], |
1691 | event_type_descriptors[PERF_TYPE_HW_CACHE]); | 1691 | event_type_descriptors[PERF_TYPE_HW_CACHE]); |
1692 | } | 1692 | } |
1693 | if (evt_num) | 1693 | if (evt_num && pager_in_use()) |
1694 | printf("\n"); | 1694 | printf("\n"); |
1695 | 1695 | ||
1696 | out_free: | 1696 | out_free: |
@@ -1763,7 +1763,7 @@ restart: | |||
1763 | } | 1763 | } |
1764 | printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); | 1764 | printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); |
1765 | } | 1765 | } |
1766 | if (evt_num) | 1766 | if (evt_num && pager_in_use()) |
1767 | printf("\n"); | 1767 | printf("\n"); |
1768 | 1768 | ||
1769 | out_free: | 1769 | out_free: |
@@ -1804,13 +1804,14 @@ void print_events(const char *event_glob, bool name_only) | |||
1804 | printf(" %-50s [%s]\n", | 1804 | printf(" %-50s [%s]\n", |
1805 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", | 1805 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", |
1806 | event_type_descriptors[PERF_TYPE_RAW]); | 1806 | event_type_descriptors[PERF_TYPE_RAW]); |
1807 | printf(" (see 'man perf-list' on how to encode it)\n"); | 1807 | if (pager_in_use()) |
1808 | printf("\n"); | 1808 | printf(" (see 'man perf-list' on how to encode it)\n\n"); |
1809 | 1809 | ||
1810 | printf(" %-50s [%s]\n", | 1810 | printf(" %-50s [%s]\n", |
1811 | "mem:<addr>[/len][:access]", | 1811 | "mem:<addr>[/len][:access]", |
1812 | event_type_descriptors[PERF_TYPE_BREAKPOINT]); | 1812 | event_type_descriptors[PERF_TYPE_BREAKPOINT]); |
1813 | printf("\n"); | 1813 | if (pager_in_use()) |
1814 | printf("\n"); | ||
1814 | } | 1815 | } |
1815 | 1816 | ||
1816 | print_tracepoint_events(NULL, NULL, name_only); | 1817 | print_tracepoint_events(NULL, NULL, name_only); |
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index 885e8ac83997..6b8eb13e14e4 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c | |||
@@ -6,6 +6,7 @@ const struct sample_reg __weak sample_reg_masks[] = { | |||
6 | SMPL_REG_END | 6 | SMPL_REG_END |
7 | }; | 7 | }; |
8 | 8 | ||
9 | #ifdef HAVE_PERF_REGS_SUPPORT | ||
9 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) | 10 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) |
10 | { | 11 | { |
11 | int i, idx = 0; | 12 | int i, idx = 0; |
@@ -29,3 +30,4 @@ out: | |||
29 | *valp = regs->cache_regs[id]; | 30 | *valp = regs->cache_regs[id]; |
30 | return 0; | 31 | return 0; |
31 | } | 32 | } |
33 | #endif | ||
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 2984dcc54d67..679d6e493962 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __PERF_REGS_H | 2 | #define __PERF_REGS_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <linux/compiler.h> | ||
5 | 6 | ||
6 | struct regs_dump; | 7 | struct regs_dump; |
7 | 8 | ||
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index ac42c97be9e4..41a356ba3cfe 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -1026,7 +1026,7 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
1026 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); | 1026 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); |
1027 | printed++; | 1027 | printed++; |
1028 | } | 1028 | } |
1029 | if (printed) | 1029 | if (printed && pager_in_use()) |
1030 | printf("\n"); | 1030 | printf("\n"); |
1031 | out_free: | 1031 | out_free: |
1032 | for (j = 0; j < len; j++) | 1032 | for (j = 0; j < len; j++) |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 7fb0533ab18c..3010abc071ff 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -126,17 +126,19 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | |||
126 | { | 126 | { |
127 | /* kmap->ref_reloc_sym should be set if host_machine is initialized */ | 127 | /* kmap->ref_reloc_sym should be set if host_machine is initialized */ |
128 | struct kmap *kmap; | 128 | struct kmap *kmap; |
129 | struct map *map = machine__kernel_map(host_machine); | ||
129 | 130 | ||
130 | if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0) | 131 | if (map__load(map, NULL) < 0) |
131 | return NULL; | 132 | return NULL; |
132 | 133 | ||
133 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); | 134 | kmap = map__kmap(map); |
134 | if (!kmap) | 135 | if (!kmap) |
135 | return NULL; | 136 | return NULL; |
136 | return kmap->ref_reloc_sym; | 137 | return kmap->ref_reloc_sym; |
137 | } | 138 | } |
138 | 139 | ||
139 | static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) | 140 | static int kernel_get_symbol_address_by_name(const char *name, u64 *addr, |
141 | bool reloc, bool reladdr) | ||
140 | { | 142 | { |
141 | struct ref_reloc_sym *reloc_sym; | 143 | struct ref_reloc_sym *reloc_sym; |
142 | struct symbol *sym; | 144 | struct symbol *sym; |
@@ -145,12 +147,14 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) | |||
145 | /* ref_reloc_sym is just a label. Need a special fix*/ | 147 | /* ref_reloc_sym is just a label. Need a special fix*/ |
146 | reloc_sym = kernel_get_ref_reloc_sym(); | 148 | reloc_sym = kernel_get_ref_reloc_sym(); |
147 | if (reloc_sym && strcmp(name, reloc_sym->name) == 0) | 149 | if (reloc_sym && strcmp(name, reloc_sym->name) == 0) |
148 | return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; | 150 | *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; |
149 | else { | 151 | else { |
150 | sym = __find_kernel_function_by_name(name, &map); | 152 | sym = __find_kernel_function_by_name(name, &map); |
151 | if (sym) | 153 | if (!sym) |
152 | return map->unmap_ip(map, sym->start) - | 154 | return -ENOENT; |
153 | ((reloc) ? 0 : map->reloc); | 155 | *addr = map->unmap_ip(map, sym->start) - |
156 | ((reloc) ? 0 : map->reloc) - | ||
157 | ((reladdr) ? map->start : 0); | ||
154 | } | 158 | } |
155 | return 0; | 159 | return 0; |
156 | } | 160 | } |
@@ -244,12 +248,14 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) | |||
244 | static bool kprobe_blacklist__listed(unsigned long address); | 248 | static bool kprobe_blacklist__listed(unsigned long address); |
245 | static bool kprobe_warn_out_range(const char *symbol, unsigned long address) | 249 | static bool kprobe_warn_out_range(const char *symbol, unsigned long address) |
246 | { | 250 | { |
247 | u64 etext_addr; | 251 | u64 etext_addr = 0; |
252 | int ret; | ||
248 | 253 | ||
249 | /* Get the address of _etext for checking non-probable text symbol */ | 254 | /* Get the address of _etext for checking non-probable text symbol */ |
250 | etext_addr = kernel_get_symbol_address_by_name("_etext", false); | 255 | ret = kernel_get_symbol_address_by_name("_etext", &etext_addr, |
256 | false, false); | ||
251 | 257 | ||
252 | if (etext_addr != 0 && etext_addr < address) | 258 | if (ret == 0 && etext_addr < address) |
253 | pr_warning("%s is out of .text, skip it.\n", symbol); | 259 | pr_warning("%s is out of .text, skip it.\n", symbol); |
254 | else if (kprobe_blacklist__listed(address)) | 260 | else if (kprobe_blacklist__listed(address)) |
255 | pr_warning("%s is blacklisted function, skip it.\n", symbol); | 261 | pr_warning("%s is blacklisted function, skip it.\n", symbol); |
@@ -281,7 +287,7 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso) | |||
281 | return -ENOENT; | 287 | return -ENOENT; |
282 | } | 288 | } |
283 | 289 | ||
284 | map = host_machine->vmlinux_maps[MAP__FUNCTION]; | 290 | map = machine__kernel_map(host_machine); |
285 | dso = map->dso; | 291 | dso = map->dso; |
286 | 292 | ||
287 | vmlinux_name = symbol_conf.vmlinux_name; | 293 | vmlinux_name = symbol_conf.vmlinux_name; |
@@ -435,19 +441,22 @@ static char *debuginfo_cache_path; | |||
435 | 441 | ||
436 | static struct debuginfo *debuginfo_cache__open(const char *module, bool silent) | 442 | static struct debuginfo *debuginfo_cache__open(const char *module, bool silent) |
437 | { | 443 | { |
438 | if ((debuginfo_cache_path && !strcmp(debuginfo_cache_path, module)) || | 444 | const char *path = module; |
439 | (!debuginfo_cache_path && !module && debuginfo_cache)) | 445 | |
446 | /* If the module is NULL, it should be the kernel. */ | ||
447 | if (!module) | ||
448 | path = "kernel"; | ||
449 | |||
450 | if (debuginfo_cache_path && !strcmp(debuginfo_cache_path, path)) | ||
440 | goto out; | 451 | goto out; |
441 | 452 | ||
442 | /* Copy module path */ | 453 | /* Copy module path */ |
443 | free(debuginfo_cache_path); | 454 | free(debuginfo_cache_path); |
444 | if (module) { | 455 | debuginfo_cache_path = strdup(path); |
445 | debuginfo_cache_path = strdup(module); | 456 | if (!debuginfo_cache_path) { |
446 | if (!debuginfo_cache_path) { | 457 | debuginfo__delete(debuginfo_cache); |
447 | debuginfo__delete(debuginfo_cache); | 458 | debuginfo_cache = NULL; |
448 | debuginfo_cache = NULL; | 459 | goto out; |
449 | goto out; | ||
450 | } | ||
451 | } | 460 | } |
452 | 461 | ||
453 | debuginfo_cache = open_debuginfo(module, silent); | 462 | debuginfo_cache = open_debuginfo(module, silent); |
@@ -516,8 +525,10 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp, | |||
516 | goto error; | 525 | goto error; |
517 | addr += stext; | 526 | addr += stext; |
518 | } else if (tp->symbol) { | 527 | } else if (tp->symbol) { |
519 | addr = kernel_get_symbol_address_by_name(tp->symbol, false); | 528 | /* If the module is given, this returns relative address */ |
520 | if (addr == 0) | 529 | ret = kernel_get_symbol_address_by_name(tp->symbol, &addr, |
530 | false, !!tp->module); | ||
531 | if (ret != 0) | ||
521 | goto error; | 532 | goto error; |
522 | addr += tp->offset; | 533 | addr += tp->offset; |
523 | } | 534 | } |
@@ -1883,8 +1894,12 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, | |||
1883 | goto out; | 1894 | goto out; |
1884 | sym = map__find_symbol(map, addr, NULL); | 1895 | sym = map__find_symbol(map, addr, NULL); |
1885 | } else { | 1896 | } else { |
1886 | if (tp->symbol) | 1897 | if (tp->symbol && !addr) { |
1887 | addr = kernel_get_symbol_address_by_name(tp->symbol, true); | 1898 | ret = kernel_get_symbol_address_by_name(tp->symbol, |
1899 | &addr, true, false); | ||
1900 | if (ret < 0) | ||
1901 | goto out; | ||
1902 | } | ||
1888 | if (addr) { | 1903 | if (addr) { |
1889 | addr += tp->offset; | 1904 | addr += tp->offset; |
1890 | sym = __find_kernel_function(addr, &map); | 1905 | sym = __find_kernel_function(addr, &map); |
@@ -2288,36 +2303,41 @@ static int get_new_event_name(char *buf, size_t len, const char *base, | |||
2288 | struct strlist *namelist, bool allow_suffix) | 2303 | struct strlist *namelist, bool allow_suffix) |
2289 | { | 2304 | { |
2290 | int i, ret; | 2305 | int i, ret; |
2291 | char *p; | 2306 | char *p, *nbase; |
2292 | 2307 | ||
2293 | if (*base == '.') | 2308 | if (*base == '.') |
2294 | base++; | 2309 | base++; |
2310 | nbase = strdup(base); | ||
2311 | if (!nbase) | ||
2312 | return -ENOMEM; | ||
2313 | |||
2314 | /* Cut off the dot suffixes (e.g. .const, .isra)*/ | ||
2315 | p = strchr(nbase, '.'); | ||
2316 | if (p && p != nbase) | ||
2317 | *p = '\0'; | ||
2295 | 2318 | ||
2296 | /* Try no suffix */ | 2319 | /* Try no suffix number */ |
2297 | ret = e_snprintf(buf, len, "%s", base); | 2320 | ret = e_snprintf(buf, len, "%s", nbase); |
2298 | if (ret < 0) { | 2321 | if (ret < 0) { |
2299 | pr_debug("snprintf() failed: %d\n", ret); | 2322 | pr_debug("snprintf() failed: %d\n", ret); |
2300 | return ret; | 2323 | goto out; |
2301 | } | 2324 | } |
2302 | /* Cut off the postfixes (e.g. .const, .isra)*/ | ||
2303 | p = strchr(buf, '.'); | ||
2304 | if (p && p != buf) | ||
2305 | *p = '\0'; | ||
2306 | if (!strlist__has_entry(namelist, buf)) | 2325 | if (!strlist__has_entry(namelist, buf)) |
2307 | return 0; | 2326 | goto out; |
2308 | 2327 | ||
2309 | if (!allow_suffix) { | 2328 | if (!allow_suffix) { |
2310 | pr_warning("Error: event \"%s\" already exists. " | 2329 | pr_warning("Error: event \"%s\" already exists. " |
2311 | "(Use -f to force duplicates.)\n", base); | 2330 | "(Use -f to force duplicates.)\n", buf); |
2312 | return -EEXIST; | 2331 | ret = -EEXIST; |
2332 | goto out; | ||
2313 | } | 2333 | } |
2314 | 2334 | ||
2315 | /* Try to add suffix */ | 2335 | /* Try to add suffix */ |
2316 | for (i = 1; i < MAX_EVENT_INDEX; i++) { | 2336 | for (i = 1; i < MAX_EVENT_INDEX; i++) { |
2317 | ret = e_snprintf(buf, len, "%s_%d", base, i); | 2337 | ret = e_snprintf(buf, len, "%s_%d", nbase, i); |
2318 | if (ret < 0) { | 2338 | if (ret < 0) { |
2319 | pr_debug("snprintf() failed: %d\n", ret); | 2339 | pr_debug("snprintf() failed: %d\n", ret); |
2320 | return ret; | 2340 | goto out; |
2321 | } | 2341 | } |
2322 | if (!strlist__has_entry(namelist, buf)) | 2342 | if (!strlist__has_entry(namelist, buf)) |
2323 | break; | 2343 | break; |
@@ -2327,6 +2347,8 @@ static int get_new_event_name(char *buf, size_t len, const char *base, | |||
2327 | ret = -ERANGE; | 2347 | ret = -ERANGE; |
2328 | } | 2348 | } |
2329 | 2349 | ||
2350 | out: | ||
2351 | free(nbase); | ||
2330 | return ret; | 2352 | return ret; |
2331 | } | 2353 | } |
2332 | 2354 | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 29c43c0680a8..bd8f03de5e40 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -70,6 +70,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, | |||
70 | if (!dbg->dwfl) | 70 | if (!dbg->dwfl) |
71 | goto error; | 71 | goto error; |
72 | 72 | ||
73 | dwfl_report_begin(dbg->dwfl); | ||
73 | dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); | 74 | dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); |
74 | if (!dbg->mod) | 75 | if (!dbg->mod) |
75 | goto error; | 76 | goto error; |
@@ -78,6 +79,8 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, | |||
78 | if (!dbg->dbg) | 79 | if (!dbg->dbg) |
79 | goto error; | 80 | goto error; |
80 | 81 | ||
82 | dwfl_report_end(dbg->dwfl, NULL, NULL); | ||
83 | |||
81 | return 0; | 84 | return 0; |
82 | error: | 85 | error: |
83 | if (dbg->dwfl) | 86 | if (dbg->dwfl) |
@@ -591,6 +594,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
591 | /* Convert subprogram DIE to trace point */ | 594 | /* Convert subprogram DIE to trace point */ |
592 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | 595 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, |
593 | Dwarf_Addr paddr, bool retprobe, | 596 | Dwarf_Addr paddr, bool retprobe, |
597 | const char *function, | ||
594 | struct probe_trace_point *tp) | 598 | struct probe_trace_point *tp) |
595 | { | 599 | { |
596 | Dwarf_Addr eaddr, highaddr; | 600 | Dwarf_Addr eaddr, highaddr; |
@@ -634,8 +638,10 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | |||
634 | /* Return probe must be on the head of a subprogram */ | 638 | /* Return probe must be on the head of a subprogram */ |
635 | if (retprobe) { | 639 | if (retprobe) { |
636 | if (eaddr != paddr) { | 640 | if (eaddr != paddr) { |
637 | pr_warning("Return probe must be on the head of" | 641 | pr_warning("Failed to find \"%s%%return\",\n" |
638 | " a real function.\n"); | 642 | " because %s is an inlined function and" |
643 | " has no return point.\n", function, | ||
644 | function); | ||
639 | return -EINVAL; | 645 | return -EINVAL; |
640 | } | 646 | } |
641 | tp->retprobe = true; | 647 | tp->retprobe = true; |
@@ -1175,6 +1181,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1175 | { | 1181 | { |
1176 | struct trace_event_finder *tf = | 1182 | struct trace_event_finder *tf = |
1177 | container_of(pf, struct trace_event_finder, pf); | 1183 | container_of(pf, struct trace_event_finder, pf); |
1184 | struct perf_probe_point *pp = &pf->pev->point; | ||
1178 | struct probe_trace_event *tev; | 1185 | struct probe_trace_event *tev; |
1179 | struct perf_probe_arg *args; | 1186 | struct perf_probe_arg *args; |
1180 | int ret, i; | 1187 | int ret, i; |
@@ -1189,7 +1196,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1189 | 1196 | ||
1190 | /* Trace point should be converted from subprogram DIE */ | 1197 | /* Trace point should be converted from subprogram DIE */ |
1191 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, | 1198 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, |
1192 | pf->pev->point.retprobe, &tev->point); | 1199 | pp->retprobe, pp->function, &tev->point); |
1193 | if (ret < 0) | 1200 | if (ret < 0) |
1194 | return ret; | 1201 | return ret; |
1195 | 1202 | ||
@@ -1319,6 +1326,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1319 | { | 1326 | { |
1320 | struct available_var_finder *af = | 1327 | struct available_var_finder *af = |
1321 | container_of(pf, struct available_var_finder, pf); | 1328 | container_of(pf, struct available_var_finder, pf); |
1329 | struct perf_probe_point *pp = &pf->pev->point; | ||
1322 | struct variable_list *vl; | 1330 | struct variable_list *vl; |
1323 | Dwarf_Die die_mem; | 1331 | Dwarf_Die die_mem; |
1324 | int ret; | 1332 | int ret; |
@@ -1332,7 +1340,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1332 | 1340 | ||
1333 | /* Trace point should be converted from subprogram DIE */ | 1341 | /* Trace point should be converted from subprogram DIE */ |
1334 | ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, | 1342 | ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, |
1335 | pf->pev->point.retprobe, &vl->point); | 1343 | pp->retprobe, pp->function, &vl->point); |
1336 | if (ret < 0) | 1344 | if (ret < 0) |
1337 | return ret; | 1345 | return ret; |
1338 | 1346 | ||
@@ -1399,6 +1407,41 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, | |||
1399 | return (ret < 0) ? ret : af.nvls; | 1407 | return (ret < 0) ? ret : af.nvls; |
1400 | } | 1408 | } |
1401 | 1409 | ||
1410 | /* For the kernel module, we need a special code to get a DIE */ | ||
1411 | static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) | ||
1412 | { | ||
1413 | int n, i; | ||
1414 | Elf32_Word shndx; | ||
1415 | Elf_Scn *scn; | ||
1416 | Elf *elf; | ||
1417 | GElf_Shdr mem, *shdr; | ||
1418 | const char *p; | ||
1419 | |||
1420 | elf = dwfl_module_getelf(dbg->mod, &dbg->bias); | ||
1421 | if (!elf) | ||
1422 | return -EINVAL; | ||
1423 | |||
1424 | /* Get the number of relocations */ | ||
1425 | n = dwfl_module_relocations(dbg->mod); | ||
1426 | if (n < 0) | ||
1427 | return -ENOENT; | ||
1428 | /* Search the relocation related .text section */ | ||
1429 | for (i = 0; i < n; i++) { | ||
1430 | p = dwfl_module_relocation_info(dbg->mod, i, &shndx); | ||
1431 | if (strcmp(p, ".text") == 0) { | ||
1432 | /* OK, get the section header */ | ||
1433 | scn = elf_getscn(elf, shndx); | ||
1434 | if (!scn) | ||
1435 | return -ENOENT; | ||
1436 | shdr = gelf_getshdr(scn, &mem); | ||
1437 | if (!shdr) | ||
1438 | return -ENOENT; | ||
1439 | *offs = shdr->sh_addr; | ||
1440 | } | ||
1441 | } | ||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1402 | /* Reverse search */ | 1445 | /* Reverse search */ |
1403 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | 1446 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, |
1404 | struct perf_probe_point *ppt) | 1447 | struct perf_probe_point *ppt) |
@@ -1407,9 +1450,16 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | |||
1407 | Dwarf_Addr _addr = 0, baseaddr = 0; | 1450 | Dwarf_Addr _addr = 0, baseaddr = 0; |
1408 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; | 1451 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; |
1409 | int baseline = 0, lineno = 0, ret = 0; | 1452 | int baseline = 0, lineno = 0, ret = 0; |
1453 | bool reloc = false; | ||
1410 | 1454 | ||
1455 | retry: | ||
1411 | /* Find cu die */ | 1456 | /* Find cu die */ |
1412 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { | 1457 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { |
1458 | if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { | ||
1459 | addr += baseaddr; | ||
1460 | reloc = true; | ||
1461 | goto retry; | ||
1462 | } | ||
1413 | pr_warning("Failed to find debug information for address %lx\n", | 1463 | pr_warning("Failed to find debug information for address %lx\n", |
1414 | addr); | 1464 | addr); |
1415 | ret = -EINVAL; | 1465 | ret = -EINVAL; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 1f97ffb158a6..bcda43bee4d4 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -624,7 +624,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name, | |||
624 | * symbols, setting length to 0, and rely on | 624 | * symbols, setting length to 0, and rely on |
625 | * symbols__fixup_end() to fix it up. | 625 | * symbols__fixup_end() to fix it up. |
626 | */ | 626 | */ |
627 | sym = symbol__new(start, 0, kallsyms2elf_type(type), name); | 627 | sym = symbol__new(start, 0, kallsyms2elf_binding(type), name); |
628 | if (sym == NULL) | 628 | if (sym == NULL) |
629 | return -ENOMEM; | 629 | return -ENOMEM; |
630 | /* | 630 | /* |