aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-10-01 03:03:57 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-01 03:03:57 -0400
commit4bc6a58fcbf63dc3da9870c41eeab1bd030bc585 (patch)
tree965af8015bcc5a9375e8858bf6aea52f5e45357c
parent9c17dbc6eb73bdd8a6aaea1baefd37ff78d86148 (diff)
parent7f8d1ade1b19f684ed3a7c4fb1dc5d347127b438 (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.h4
-rw-r--r--tools/lib/symbol/kallsyms.c6
-rw-r--r--tools/lib/symbol/kallsyms.h4
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-list.c2
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/tests/code-reading.c2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c4
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/event.c7
-rw-r--r--tools/perf/util/evlist.c22
-rw-r--r--tools/perf/util/intel-pt.c2
-rw-r--r--tools/perf/util/machine.c26
-rw-r--r--tools/perf/util/machine.h8
-rw-r--r--tools/perf/util/map.c21
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/parse-events.c53
-rw-r--r--tools/perf/util/perf_regs.c2
-rw-r--r--tools/perf/util/perf_regs.h1
-rw-r--r--tools/perf/util/pmu.c2
-rw-r--r--tools/perf/util/probe-event.c96
-rw-r--r--tools/perf/util/probe-finder.c58
-rw-r--r--tools/perf/util/symbol.c2
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
34static inline void * __must_check ERR_PTR(long error) 34static inline void * __must_check ERR_PTR(long error_)
35{ 35{
36 return (void *) error; 36 return (void *) error_;
37} 37}
38 38
39static inline long __must_check PTR_ERR(__force const void *ptr) 39static 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
5u8 kallsyms2elf_type(char type)
6{
7 type = tolower(type);
8 return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT;
9}
10
5int kallsyms__parse(const char *filename, void *arg, 11int 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
12static inline u8 kallsyms2elf_type(char type) 12static 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
20u8 kallsyms2elf_type(char type);
21
20int kallsyms__parse(const char *filename, void *arg, 22int 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
388static void report__warn_kptr_restrict(const struct report *rep) 388static 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
18libperf-y += llvm-utils.o 18libperf-y += llvm-utils.o
19libperf-y += parse-options.o 19libperf-y += parse-options.o
20libperf-y += parse-events.o 20libperf-y += parse-events.o
21libperf-y += perf_regs.o
21libperf-y += path.o 22libperf-y += path.o
22libperf-y += rbtree.o 23libperf-y += rbtree.o
23libperf-y += bitmap.o 24libperf-y += bitmap.o
@@ -104,7 +105,6 @@ libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
104 105
105libperf-y += scripting-engines/ 106libperf-y += scripting-engines/
106 107
107libperf-$(CONFIG_PERF_REGS) += perf_regs.o
108libperf-$(CONFIG_ZLIB) += zlib.o 108libperf-$(CONFIG_ZLIB) += zlib.o
109libperf-$(CONFIG_LZMA) += lzma.o 109libperf-$(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
208static 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
208int perf_evlist__add_default(struct perf_evlist *evlist) 222int 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)
867int machine__load_kallsyms(struct machine *machine, const char *filename, 868int 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,
886int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 887int 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
1998int machine__get_kernel_start(struct machine *machine) 1998int 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
50static inline 50static inline
51struct map *machine__kernel_map(struct machine *machine, enum map_type type) 51struct 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
56static inline
57struct map *machine__kernel_map(struct machine *machine)
58{
59 return __machine__kernel_map(machine, MAP__FUNCTION);
60}
61
56int machine__get_kernel_start(struct machine *machine); 62int machine__get_kernel_start(struct machine *machine);
57 63
58static inline u64 machine__kernel_start(struct machine *machine) 64static 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 */
236bool __map__is_kernel(const struct map *map) 236bool __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
241static void map__exit(struct map *map) 241static 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
556struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 556struct 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
582struct 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
586int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 593int 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);
190struct map *maps__find(struct maps *maps, u64 addr); 190struct map *maps__find(struct maps *maps, u64 addr);
191struct map *maps__first(struct maps *maps); 191struct map *maps__first(struct maps *maps);
192struct map *map__next(struct map *map); 192struct map *map__next(struct map *map);
193struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
194 struct map **mapp, symbol_filter_t filter);
193void map_groups__init(struct map_groups *mg, struct machine *machine); 195void map_groups__init(struct map_groups *mg, struct machine *machine);
194void map_groups__exit(struct map_groups *mg); 196void map_groups__exit(struct map_groups *mg);
195int map_groups__clone(struct map_groups *mg, 197int 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
392static void tracepoint_error(struct parse_events_error *error, int err, 392static 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
419static int add_tracepoint(struct list_head *list, int *idx, 419static 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
444static int add_tracepoint_multi_event(struct list_head *list, int *idx, 444static 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
479static int add_tracepoint_event(struct list_head *list, int *idx, 479static 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
491static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 491static 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
768int parse_events_add_tracepoint(struct list_head *list, int *idx, 768int 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
789int parse_events_add_numeric(struct parse_events_evlist *data, 789int 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
1540out_free: 1540out_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
1696out_free: 1696out_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
1769out_free: 1769out_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
9int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) 10int 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
6struct regs_dump; 7struct 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");
1031out_free: 1031out_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
139static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) 140static 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)
244static bool kprobe_blacklist__listed(unsigned long address); 248static bool kprobe_blacklist__listed(unsigned long address);
245static bool kprobe_warn_out_range(const char *symbol, unsigned long address) 249static 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
436static struct debuginfo *debuginfo_cache__open(const char *module, bool silent) 442static 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
2350out:
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;
82error: 85error:
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 */
592static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, 595static 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 */
1411static 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 */
1403int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 1446int 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
1455retry:
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 /*