aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-09-29 13:09:58 -0400
committerIngo Molnar <mingo@kernel.org>2016-09-29 13:09:58 -0400
commit41aad2a6d4fcdda8d73c9739daf7a9f3f49499d6 (patch)
treed679538c1fa9111ba5d604ad5ef016176c71f278
parent6b652de2b27c0a4020ce0e8f277e782b6af76096 (diff)
parentd18019a53a07e009899ff6b8dc5ec30f249360d9 (diff)
Merge tag 'perf-core-for-mingo-20160929' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: --------------------- New features: - Add support for using symbols in address filters with Intel PT and ARM CoreSight (hardware assisted tracing facilities) (Adrian Hunter, Mathieu Poirier) Fixes: - Fix MMAP event synthesis for pre-existing threads when no hugetlbfs mount is in place (Adrian Hunter) - Don't ignore kernel idle symbols in 'perf script' (Adrian Hunter) - Assorted Intel PT fixes (Adrian Hunter) Improvements: - Fix handling of C++ symbols in 'perf probe' (Masami Hiramatsu) - Beautify sched_[gs]et_attr return value in 'perf trace' (Arnaldo Carvalho de Melo) Infrastructure changes: ----------------------- New features: - Add dwarf unwind 'perf test' for powerpc (Ravi Bangoria) Fixes: - Fix error paths in 'perf record' (Adrian Hunter) Documentation: - Update documentation info about quipper, a C++ parser for converting to/from perf.data/chromium profiling format (Simon Que) Build Fixes: Fix building in 32 bit platform with libbabeltrace (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf-record.txt61
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt6
-rw-r--r--tools/perf/arch/powerpc/Build1
-rw-r--r--tools/perf/arch/powerpc/include/arch-tests.h13
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h2
-rw-r--r--tools/perf/arch/powerpc/tests/Build4
-rw-r--r--tools/perf/arch/powerpc/tests/arch-tests.c15
-rw-r--r--tools/perf/arch/powerpc/tests/dwarf-unwind.c62
-rw-r--r--tools/perf/arch/powerpc/tests/regs_load.S94
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c57
-rw-r--r--tools/perf/builtin-record.c32
-rw-r--r--tools/perf/builtin-trace.c10
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/util/auxtrace.c737
-rw-r--r--tools/perf/util/auxtrace.h54
-rw-r--r--tools/perf/util/build-id.c4
-rw-r--r--tools/perf/util/data-convert-bt.c2
-rw-r--r--tools/perf/util/dwarf-aux.c28
-rw-r--r--tools/perf/util/dwarf-aux.h3
-rw-r--r--tools/perf/util/event.c3
-rw-r--r--tools/perf/util/evsel.c16
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/evsel_fprintf.c7
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c30
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h1
-rw-r--r--tools/perf/util/intel-pt.c172
-rw-r--r--tools/perf/util/intel-pt.h4
-rw-r--r--tools/perf/util/parse-events.c41
-rw-r--r--tools/perf/util/probe-event.c10
-rw-r--r--tools/perf/util/probe-file.c2
-rw-r--r--tools/perf/util/probe-finder.c17
-rw-r--r--tools/perf/util/symbol.c15
-rw-r--r--tools/perf/util/symbol.h1
34 files changed, 1451 insertions, 62 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 1a24f4d64328..92335193dc33 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -35,15 +35,15 @@ OPTIONS
35 35
36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where 36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
37 'param1', 'param2', etc are defined as formats for the PMU in 37 'param1', 'param2', etc are defined as formats for the PMU in
38 /sys/bus/event_sources/devices/<pmu>/format/*. 38 /sys/bus/event_source/devices/<pmu>/format/*.
39 39
40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/' 40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
41 41
42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable 42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable
43 values for each of 'config', 'config1' and 'config2' are defined by 43 values for each of 'config', 'config1' and 'config2' are defined by
44 corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/* 44 corresponding entries in /sys/bus/event_source/devices/<pmu>/format/*
45 param1 and param2 are defined as formats for the PMU in: 45 param1 and param2 are defined as formats for the PMU in:
46 /sys/bus/event_sources/devices/<pmu>/format/* 46 /sys/bus/event_source/devices/<pmu>/format/*
47 47
48 There are also some params which are not defined in .../<pmu>/format/*. 48 There are also some params which are not defined in .../<pmu>/format/*.
49 These params can be used to overload default config values per event. 49 These params can be used to overload default config values per event.
@@ -89,9 +89,62 @@ OPTIONS
89 89
90--filter=<filter>:: 90--filter=<filter>::
91 Event filter. This option should follow a event selector (-e) which 91 Event filter. This option should follow a event selector (-e) which
92 selects tracepoint event(s). Multiple '--filter' options are combined 92 selects either tracepoint event(s) or a hardware trace PMU
93 (e.g. Intel PT or CoreSight).
94
95 - tracepoint filters
96
97 In the case of tracepoints, multiple '--filter' options are combined
93 using '&&'. 98 using '&&'.
94 99
100 - address filters
101
102 A hardware trace PMU advertises its ability to accept a number of
103 address filters by specifying a non-zero value in
104 /sys/bus/event_source/devices/<pmu>/nr_addr_filters.
105
106 Address filters have the format:
107
108 filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
109
110 Where:
111 - 'filter': defines a region that will be traced.
112 - 'start': defines an address at which tracing will begin.
113 - 'stop': defines an address at which tracing will stop.
114 - 'tracestop': defines a region in which tracing will stop.
115
116 <file name> is the name of the object file, <start> is the offset to the
117 code to trace in that file, and <size> is the size of the region to
118 trace. 'start' and 'stop' filters need not specify a <size>.
119
120 If no object file is specified then the kernel is assumed, in which case
121 the start address must be a current kernel memory address.
122
123 <start> can also be specified by providing the name of a symbol. If the
124 symbol name is not unique, it can be disambiguated by inserting #n where
125 'n' selects the n'th symbol in address order. Alternately #0, #g or #G
126 select only a global symbol. <size> can also be specified by providing
127 the name of a symbol, in which case the size is calculated to the end
128 of that symbol. For 'filter' and 'tracestop' filters, if <size> is
129 omitted and <start> is a symbol, then the size is calculated to the end
130 of that symbol.
131
132 If <size> is omitted and <start> is '*', then the start and size will
133 be calculated from the first and last symbols, i.e. to trace the whole
134 file.
135
136 If symbol names (or '*') are provided, they must be surrounded by white
137 space.
138
139 The filter passed to the kernel is not necessarily the same as entered.
140 To see the filter that is passed, use the -v option.
141
142 The kernel may not be able to configure a trace region if it is not
143 within a single mapping. MMAP events (or /proc/<pid>/maps) can be
144 examined to determine if that is a possibility.
145
146 Multiple filters can be separated with space or comma.
147
95--exclude-perf:: 148--exclude-perf::
96 Don't record events issued by perf itself. This option should follow 149 Don't record events issued by perf itself. This option should follow
97 a event selector (-e) which selects tracepoint event(s). It adds a 150 a event selector (-e) which selects tracepoint event(s). It adds a
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index fdc99fe6bbc3..b664b18d3991 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -437,6 +437,10 @@ in pmu-tools parser. This allows to read perf.data from python and dump it.
437quipper 437quipper
438 438
439The quipper C++ parser is available at 439The quipper C++ parser is available at
440https://chromium.googlesource.com/chromiumos/platform/chromiumos-wide-profiling/ 440https://chromium.googlesource.com/chromiumos/platform2
441
442It is under the chromiumos-wide-profiling/ subdirectory. This library can
443convert a perf data file to a protobuf and vice versa.
444
441Unfortunately this parser tends to be many versions behind and may not be able 445Unfortunately this parser tends to be many versions behind and may not be able
442to parse data files generated by recent perf. 446to parse data files generated by recent perf.
diff --git a/tools/perf/arch/powerpc/Build b/tools/perf/arch/powerpc/Build
index 54afe4a467e7..db52fa22d3a1 100644
--- a/tools/perf/arch/powerpc/Build
+++ b/tools/perf/arch/powerpc/Build
@@ -1 +1,2 @@
1libperf-y += util/ 1libperf-y += util/
2libperf-y += tests/
diff --git a/tools/perf/arch/powerpc/include/arch-tests.h b/tools/perf/arch/powerpc/include/arch-tests.h
new file mode 100644
index 000000000000..84d8dedef2ed
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/arch-tests.h
@@ -0,0 +1,13 @@
1#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H
3
4#ifdef HAVE_DWARF_UNWIND_SUPPORT
5struct thread;
6struct perf_sample;
7int test__arch_unwind_sample(struct perf_sample *sample,
8 struct thread *thread);
9#endif
10
11extern struct test arch_tests[];
12
13#endif
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
index 75de0e92e71e..c12f4e804f66 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -5,6 +5,8 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8void perf_regs_load(u64 *regs);
9
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) 10#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX 11#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__ 12#ifdef __powerpc64__
diff --git a/tools/perf/arch/powerpc/tests/Build b/tools/perf/arch/powerpc/tests/Build
new file mode 100644
index 000000000000..d827ef384b33
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/Build
@@ -0,0 +1,4 @@
1libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
2libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/powerpc/tests/arch-tests.c b/tools/perf/arch/powerpc/tests/arch-tests.c
new file mode 100644
index 000000000000..e24f46241f40
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/arch-tests.c
@@ -0,0 +1,15 @@
1#include <string.h>
2#include "tests/tests.h"
3#include "arch-tests.h"
4
5struct test arch_tests[] = {
6#ifdef HAVE_DWARF_UNWIND_SUPPORT
7 {
8 .desc = "Test dwarf unwind",
9 .func = test__dwarf_unwind,
10 },
11#endif
12 {
13 .func = NULL,
14 },
15};
diff --git a/tools/perf/arch/powerpc/tests/dwarf-unwind.c b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
new file mode 100644
index 000000000000..0bac3137ccbd
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
@@ -0,0 +1,62 @@
1#include <string.h>
2#include "perf_regs.h"
3#include "thread.h"
4#include "map.h"
5#include "event.h"
6#include "debug.h"
7#include "tests/tests.h"
8#include "arch-tests.h"
9
10#define STACK_SIZE 8192
11
12static int sample_ustack(struct perf_sample *sample,
13 struct thread *thread, u64 *regs)
14{
15 struct stack_dump *stack = &sample->user_stack;
16 struct map *map;
17 unsigned long sp;
18 u64 stack_size, *buf;
19
20 buf = malloc(STACK_SIZE);
21 if (!buf) {
22 pr_debug("failed to allocate sample uregs data\n");
23 return -1;
24 }
25
26 sp = (unsigned long) regs[PERF_REG_POWERPC_R1];
27
28 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp);
29 if (!map) {
30 pr_debug("failed to get stack map\n");
31 free(buf);
32 return -1;
33 }
34
35 stack_size = map->end - sp;
36 stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
37
38 memcpy(buf, (void *) sp, stack_size);
39 stack->data = (char *) buf;
40 stack->size = stack_size;
41 return 0;
42}
43
44int test__arch_unwind_sample(struct perf_sample *sample,
45 struct thread *thread)
46{
47 struct regs_dump *regs = &sample->user_regs;
48 u64 *buf;
49
50 buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
51 if (!buf) {
52 pr_debug("failed to allocate sample uregs data\n");
53 return -1;
54 }
55
56 perf_regs_load(buf);
57 regs->abi = PERF_SAMPLE_REGS_ABI;
58 regs->regs = buf;
59 regs->mask = PERF_REGS_MASK;
60
61 return sample_ustack(sample, thread, buf);
62}
diff --git a/tools/perf/arch/powerpc/tests/regs_load.S b/tools/perf/arch/powerpc/tests/regs_load.S
new file mode 100644
index 000000000000..d76c9a32f327
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/regs_load.S
@@ -0,0 +1,94 @@
1#include <linux/linkage.h>
2
3/* Offset is based on macros from arch/powerpc/include/uapi/asm/ptrace.h. */
4#define R0 0
5#define R1 1 * 8
6#define R2 2 * 8
7#define R3 3 * 8
8#define R4 4 * 8
9#define R5 5 * 8
10#define R6 6 * 8
11#define R7 7 * 8
12#define R8 8 * 8
13#define R9 9 * 8
14#define R10 10 * 8
15#define R11 11 * 8
16#define R12 12 * 8
17#define R13 13 * 8
18#define R14 14 * 8
19#define R15 15 * 8
20#define R16 16 * 8
21#define R17 17 * 8
22#define R18 18 * 8
23#define R19 19 * 8
24#define R20 20 * 8
25#define R21 21 * 8
26#define R22 22 * 8
27#define R23 23 * 8
28#define R24 24 * 8
29#define R25 25 * 8
30#define R26 26 * 8
31#define R27 27 * 8
32#define R28 28 * 8
33#define R29 29 * 8
34#define R30 30 * 8
35#define R31 31 * 8
36#define NIP 32 * 8
37#define CTR 35 * 8
38#define LINK 36 * 8
39#define XER 37 * 8
40
41.globl perf_regs_load
42perf_regs_load:
43 std 0, R0(3)
44 std 1, R1(3)
45 std 2, R2(3)
46 std 3, R3(3)
47 std 4, R4(3)
48 std 5, R5(3)
49 std 6, R6(3)
50 std 7, R7(3)
51 std 8, R8(3)
52 std 9, R9(3)
53 std 10, R10(3)
54 std 11, R11(3)
55 std 12, R12(3)
56 std 13, R13(3)
57 std 14, R14(3)
58 std 15, R15(3)
59 std 16, R16(3)
60 std 17, R17(3)
61 std 18, R18(3)
62 std 19, R19(3)
63 std 20, R20(3)
64 std 21, R21(3)
65 std 22, R22(3)
66 std 23, R23(3)
67 std 24, R24(3)
68 std 25, R25(3)
69 std 26, R26(3)
70 std 27, R27(3)
71 std 28, R28(3)
72 std 29, R29(3)
73 std 30, R30(3)
74 std 31, R31(3)
75
76 /* store NIP */
77 mflr 4
78 std 4, NIP(3)
79
80 /* Store LR */
81 std 4, LINK(3)
82
83 /* Store XER */
84 mfxer 4
85 std 4, XER(3)
86
87 /* Store CTR */
88 mfctr 4
89 std 4, CTR(3)
90
91 /* Restore original value of r4 */
92 ld 4, R4(3)
93
94 blr
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a2412e9d883b..90fa2286edcf 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -62,6 +62,7 @@ struct intel_pt_recording {
62 size_t snapshot_ref_buf_size; 62 size_t snapshot_ref_buf_size;
63 int snapshot_ref_cnt; 63 int snapshot_ref_cnt;
64 struct intel_pt_snapshot_ref *snapshot_refs; 64 struct intel_pt_snapshot_ref *snapshot_refs;
65 size_t priv_size;
65}; 66};
66 67
67static int intel_pt_parse_terms_with_default(struct list_head *formats, 68static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
273 return attr; 274 return attr;
274} 275}
275 276
277static const char *intel_pt_find_filter(struct perf_evlist *evlist,
278 struct perf_pmu *intel_pt_pmu)
279{
280 struct perf_evsel *evsel;
281
282 evlist__for_each_entry(evlist, evsel) {
283 if (evsel->attr.type == intel_pt_pmu->type)
284 return evsel->filter;
285 }
286
287 return NULL;
288}
289
290static size_t intel_pt_filter_bytes(const char *filter)
291{
292 size_t len = filter ? strlen(filter) : 0;
293
294 return len ? roundup(len + 1, 8) : 0;
295}
296
276static size_t 297static size_t
277intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused, 298intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
278 struct perf_evlist *evlist __maybe_unused)
279{ 299{
280 return INTEL_PT_AUXTRACE_PRIV_SIZE; 300 struct intel_pt_recording *ptr =
301 container_of(itr, struct intel_pt_recording, itr);
302 const char *filter = intel_pt_find_filter(evlist, ptr->intel_pt_pmu);
303
304 ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) +
305 intel_pt_filter_bytes(filter);
306
307 return ptr->priv_size;
281} 308}
282 309
283static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d) 310static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
@@ -302,9 +329,13 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
302 bool cap_user_time_zero = false, per_cpu_mmaps; 329 bool cap_user_time_zero = false, per_cpu_mmaps;
303 u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit; 330 u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
304 u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; 331 u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
332 unsigned long max_non_turbo_ratio;
333 size_t filter_str_len;
334 const char *filter;
335 u64 *info;
305 int err; 336 int err;
306 337
307 if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) 338 if (priv_size != ptr->priv_size)
308 return -EINVAL; 339 return -EINVAL;
309 340
310 intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); 341 intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
@@ -317,6 +348,13 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
317 348
318 intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); 349 intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
319 350
351 if (perf_pmu__scan_file(intel_pt_pmu, "max_nonturbo_ratio",
352 "%lu", &max_non_turbo_ratio) != 1)
353 max_non_turbo_ratio = 0;
354
355 filter = intel_pt_find_filter(session->evlist, ptr->intel_pt_pmu);
356 filter_str_len = filter ? strlen(filter) : 0;
357
320 if (!session->evlist->nr_mmaps) 358 if (!session->evlist->nr_mmaps)
321 return -EINVAL; 359 return -EINVAL;
322 360
@@ -351,6 +389,17 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
351 auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n; 389 auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
352 auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d; 390 auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
353 auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit; 391 auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
392 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
393 auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] = filter_str_len;
394
395 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
396
397 if (filter_str_len) {
398 size_t len = intel_pt_filter_bytes(filter);
399
400 strncpy((char *)info, filter, len);
401 info += len >> 3;
402 }
354 403
355 return 0; 404 return 0;
356} 405}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2d0d69be3bf8..67d2a9003294 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1573,29 +1573,39 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1573 if (!rec->itr) { 1573 if (!rec->itr) {
1574 rec->itr = auxtrace_record__init(rec->evlist, &err); 1574 rec->itr = auxtrace_record__init(rec->evlist, &err);
1575 if (err) 1575 if (err)
1576 return err; 1576 goto out;
1577 } 1577 }
1578 1578
1579 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 1579 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1580 rec->opts.auxtrace_snapshot_opts); 1580 rec->opts.auxtrace_snapshot_opts);
1581 if (err) 1581 if (err)
1582 return err; 1582 goto out;
1583
1584 /*
1585 * Allow aliases to facilitate the lookup of symbols for address
1586 * filters. Refer to auxtrace_parse_filters().
1587 */
1588 symbol_conf.allow_aliases = true;
1589
1590 symbol__init(NULL);
1591
1592 err = auxtrace_parse_filters(rec->evlist);
1593 if (err)
1594 goto out;
1583 1595
1584 if (dry_run) 1596 if (dry_run)
1585 return 0; 1597 goto out;
1586 1598
1587 err = bpf__setup_stdout(rec->evlist); 1599 err = bpf__setup_stdout(rec->evlist);
1588 if (err) { 1600 if (err) {
1589 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1601 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1590 pr_err("ERROR: Setup BPF stdout failed: %s\n", 1602 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1591 errbuf); 1603 errbuf);
1592 return err; 1604 goto out;
1593 } 1605 }
1594 1606
1595 err = -ENOMEM; 1607 err = -ENOMEM;
1596 1608
1597 symbol__init(NULL);
1598
1599 if (symbol_conf.kptr_restrict) 1609 if (symbol_conf.kptr_restrict)
1600 pr_warning( 1610 pr_warning(
1601"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1611"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
@@ -1643,7 +1653,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1643 if (rec->evlist->nr_entries == 0 && 1653 if (rec->evlist->nr_entries == 0 &&
1644 perf_evlist__add_default(rec->evlist) < 0) { 1654 perf_evlist__add_default(rec->evlist) < 0) {
1645 pr_err("Not enough memory for event selector list\n"); 1655 pr_err("Not enough memory for event selector list\n");
1646 goto out_symbol_exit; 1656 goto out;
1647 } 1657 }
1648 1658
1649 if (rec->opts.target.tid && !rec->opts.no_inherit_set) 1659 if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1663,7 +1673,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1663 ui__error("%s", errbuf); 1673 ui__error("%s", errbuf);
1664 1674
1665 err = -saved_errno; 1675 err = -saved_errno;
1666 goto out_symbol_exit; 1676 goto out;
1667 } 1677 }
1668 1678
1669 err = -ENOMEM; 1679 err = -ENOMEM;
@@ -1672,7 +1682,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1672 1682
1673 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1683 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1674 if (err) 1684 if (err)
1675 goto out_symbol_exit; 1685 goto out;
1676 1686
1677 /* 1687 /*
1678 * We take all buildids when the file contains 1688 * We take all buildids when the file contains
@@ -1684,11 +1694,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1684 1694
1685 if (record_opts__config(&rec->opts)) { 1695 if (record_opts__config(&rec->opts)) {
1686 err = -EINVAL; 1696 err = -EINVAL;
1687 goto out_symbol_exit; 1697 goto out;
1688 } 1698 }
1689 1699
1690 err = __cmd_record(&record, argc, argv); 1700 err = __cmd_record(&record, argc, argv);
1691out_symbol_exit: 1701out:
1692 perf_evlist__delete(rec->evlist); 1702 perf_evlist__delete(rec->evlist);
1693 symbol__exit(); 1703 symbol__exit();
1694 auxtrace_record__free(rec->itr); 1704 auxtrace_record__free(rec->itr);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index b4fc1ab3d2a7..c298bd3e1d90 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -742,6 +742,8 @@ static struct syscall_fmt {
742 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 742 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
743 { .name = "rt_tgsigqueueinfo", .errmsg = true, 743 { .name = "rt_tgsigqueueinfo", .errmsg = true,
744 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 744 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
745 { .name = "sched_getattr", .errmsg = true, },
746 { .name = "sched_setattr", .errmsg = true, },
745 { .name = "sched_setscheduler", .errmsg = true, 747 { .name = "sched_setscheduler", .errmsg = true,
746 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, }, 748 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
747 { .name = "seccomp", .errmsg = true, 749 { .name = "seccomp", .errmsg = true,
@@ -2141,6 +2143,7 @@ out_delete_sys_enter:
2141static int trace__set_ev_qualifier_filter(struct trace *trace) 2143static int trace__set_ev_qualifier_filter(struct trace *trace)
2142{ 2144{
2143 int err = -1; 2145 int err = -1;
2146 struct perf_evsel *sys_exit;
2144 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier, 2147 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2145 trace->ev_qualifier_ids.nr, 2148 trace->ev_qualifier_ids.nr,
2146 trace->ev_qualifier_ids.entries); 2149 trace->ev_qualifier_ids.entries);
@@ -2148,8 +2151,11 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
2148 if (filter == NULL) 2151 if (filter == NULL)
2149 goto out_enomem; 2152 goto out_enomem;
2150 2153
2151 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter)) 2154 if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
2152 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter); 2155 filter)) {
2156 sys_exit = trace->syscalls.events.sys_exit;
2157 err = perf_evsel__append_tp_filter(sys_exit, filter);
2158 }
2153 2159
2154 free(filter); 2160 free(filter);
2155out: 2161out:
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index dc51bc570e51..8a4ce492f7b2 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -71,7 +71,7 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
71 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ 71 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
72 $(Q)echo ';' >> $@ 72 $(Q)echo ';' >> $@
73 73
74ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) 74ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64 powerpc))
75perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 75perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
76endif 76endif
77 77
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 8f6eb853aaf7..1046491de4b2 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -11,7 +11,7 @@
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h" 12#include "callchain.h"
13 13
14#if defined (__x86_64__) || defined (__i386__) 14#if defined (__x86_64__) || defined (__i386__) || defined (__powerpc__)
15#include "arch-tests.h" 15#include "arch-tests.h"
16#endif 16#endif
17 17
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c0aba8e839aa..c5a6e0b12452 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -16,6 +16,10 @@
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/mman.h> 17#include <sys/mman.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <ctype.h>
20#include <string.h>
21#include <limits.h>
22#include <errno.h>
19 23
20#include <linux/kernel.h> 24#include <linux/kernel.h>
21#include <linux/perf_event.h> 25#include <linux/perf_event.h>
@@ -35,9 +39,14 @@
35#include "../perf.h" 39#include "../perf.h"
36#include "util.h" 40#include "util.h"
37#include "evlist.h" 41#include "evlist.h"
42#include "dso.h"
43#include "map.h"
44#include "pmu.h"
45#include "evsel.h"
38#include "cpumap.h" 46#include "cpumap.h"
39#include "thread_map.h" 47#include "thread_map.h"
40#include "asm/bug.h" 48#include "asm/bug.h"
49#include "symbol/kallsyms.h"
41#include "auxtrace.h" 50#include "auxtrace.h"
42 51
43#include <linux/hash.h> 52#include <linux/hash.h>
@@ -1399,3 +1408,731 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
1399 1408
1400 return NULL; 1409 return NULL;
1401} 1410}
1411
1412static void addr_filter__free_str(struct addr_filter *filt)
1413{
1414 free(filt->str);
1415 filt->action = NULL;
1416 filt->sym_from = NULL;
1417 filt->sym_to = NULL;
1418 filt->filename = NULL;
1419 filt->str = NULL;
1420}
1421
1422static struct addr_filter *addr_filter__new(void)
1423{
1424 struct addr_filter *filt = zalloc(sizeof(*filt));
1425
1426 if (filt)
1427 INIT_LIST_HEAD(&filt->list);
1428
1429 return filt;
1430}
1431
1432static void addr_filter__free(struct addr_filter *filt)
1433{
1434 if (filt)
1435 addr_filter__free_str(filt);
1436 free(filt);
1437}
1438
1439static void addr_filters__add(struct addr_filters *filts,
1440 struct addr_filter *filt)
1441{
1442 list_add_tail(&filt->list, &filts->head);
1443 filts->cnt += 1;
1444}
1445
1446static void addr_filters__del(struct addr_filters *filts,
1447 struct addr_filter *filt)
1448{
1449 list_del_init(&filt->list);
1450 filts->cnt -= 1;
1451}
1452
1453void addr_filters__init(struct addr_filters *filts)
1454{
1455 INIT_LIST_HEAD(&filts->head);
1456 filts->cnt = 0;
1457}
1458
1459void addr_filters__exit(struct addr_filters *filts)
1460{
1461 struct addr_filter *filt, *n;
1462
1463 list_for_each_entry_safe(filt, n, &filts->head, list) {
1464 addr_filters__del(filts, filt);
1465 addr_filter__free(filt);
1466 }
1467}
1468
1469static int parse_num_or_str(char **inp, u64 *num, const char **str,
1470 const char *str_delim)
1471{
1472 *inp += strspn(*inp, " ");
1473
1474 if (isdigit(**inp)) {
1475 char *endptr;
1476
1477 if (!num)
1478 return -EINVAL;
1479 errno = 0;
1480 *num = strtoull(*inp, &endptr, 0);
1481 if (errno)
1482 return -errno;
1483 if (endptr == *inp)
1484 return -EINVAL;
1485 *inp = endptr;
1486 } else {
1487 size_t n;
1488
1489 if (!str)
1490 return -EINVAL;
1491 *inp += strspn(*inp, " ");
1492 *str = *inp;
1493 n = strcspn(*inp, str_delim);
1494 if (!n)
1495 return -EINVAL;
1496 *inp += n;
1497 if (**inp) {
1498 **inp = '\0';
1499 *inp += 1;
1500 }
1501 }
1502 return 0;
1503}
1504
1505static int parse_action(struct addr_filter *filt)
1506{
1507 if (!strcmp(filt->action, "filter")) {
1508 filt->start = true;
1509 filt->range = true;
1510 } else if (!strcmp(filt->action, "start")) {
1511 filt->start = true;
1512 } else if (!strcmp(filt->action, "stop")) {
1513 filt->start = false;
1514 } else if (!strcmp(filt->action, "tracestop")) {
1515 filt->start = false;
1516 filt->range = true;
1517 filt->action += 5; /* Change 'tracestop' to 'stop' */
1518 } else {
1519 return -EINVAL;
1520 }
1521 return 0;
1522}
1523
1524static int parse_sym_idx(char **inp, int *idx)
1525{
1526 *idx = -1;
1527
1528 *inp += strspn(*inp, " ");
1529
1530 if (**inp != '#')
1531 return 0;
1532
1533 *inp += 1;
1534
1535 if (**inp == 'g' || **inp == 'G') {
1536 *inp += 1;
1537 *idx = 0;
1538 } else {
1539 unsigned long num;
1540 char *endptr;
1541
1542 errno = 0;
1543 num = strtoul(*inp, &endptr, 0);
1544 if (errno)
1545 return -errno;
1546 if (endptr == *inp || num > INT_MAX)
1547 return -EINVAL;
1548 *inp = endptr;
1549 *idx = num;
1550 }
1551
1552 return 0;
1553}
1554
1555static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
1556{
1557 int err = parse_num_or_str(inp, num, str, " ");
1558
1559 if (!err && *str)
1560 err = parse_sym_idx(inp, idx);
1561
1562 return err;
1563}
1564
1565static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
1566{
1567 char *fstr;
1568 int err;
1569
1570 filt->str = fstr = strdup(*filter_inp);
1571 if (!fstr)
1572 return -ENOMEM;
1573
1574 err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
1575 if (err)
1576 goto out_err;
1577
1578 err = parse_action(filt);
1579 if (err)
1580 goto out_err;
1581
1582 err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
1583 &filt->sym_from_idx);
1584 if (err)
1585 goto out_err;
1586
1587 fstr += strspn(fstr, " ");
1588
1589 if (*fstr == '/') {
1590 fstr += 1;
1591 err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
1592 &filt->sym_to_idx);
1593 if (err)
1594 goto out_err;
1595 filt->range = true;
1596 }
1597
1598 fstr += strspn(fstr, " ");
1599
1600 if (*fstr == '@') {
1601 fstr += 1;
1602 err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
1603 if (err)
1604 goto out_err;
1605 }
1606
1607 fstr += strspn(fstr, " ,");
1608
1609 *filter_inp += fstr - filt->str;
1610
1611 return 0;
1612
1613out_err:
1614 addr_filter__free_str(filt);
1615
1616 return err;
1617}
1618
1619int addr_filters__parse_bare_filter(struct addr_filters *filts,
1620 const char *filter)
1621{
1622 struct addr_filter *filt;
1623 const char *fstr = filter;
1624 int err;
1625
1626 while (*fstr) {
1627 filt = addr_filter__new();
1628 err = parse_one_filter(filt, &fstr);
1629 if (err) {
1630 addr_filter__free(filt);
1631 addr_filters__exit(filts);
1632 return err;
1633 }
1634 addr_filters__add(filts, filt);
1635 }
1636
1637 return 0;
1638}
1639
1640struct sym_args {
1641 const char *name;
1642 u64 start;
1643 u64 size;
1644 int idx;
1645 int cnt;
1646 bool started;
1647 bool global;
1648 bool selected;
1649 bool duplicate;
1650 bool near;
1651};
1652
1653static bool kern_sym_match(struct sym_args *args, const char *name, char type)
1654{
1655 /* A function with the same name, and global or the n'th found or any */
1656 return symbol_type__is_a(type, MAP__FUNCTION) &&
1657 !strcmp(name, args->name) &&
1658 ((args->global && isupper(type)) ||
1659 (args->selected && ++(args->cnt) == args->idx) ||
1660 (!args->global && !args->selected));
1661}
1662
1663static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1664{
1665 struct sym_args *args = arg;
1666
1667 if (args->started) {
1668 if (!args->size)
1669 args->size = start - args->start;
1670 if (args->selected) {
1671 if (args->size)
1672 return 1;
1673 } else if (kern_sym_match(args, name, type)) {
1674 args->duplicate = true;
1675 return 1;
1676 }
1677 } else if (kern_sym_match(args, name, type)) {
1678 args->started = true;
1679 args->start = start;
1680 }
1681
1682 return 0;
1683}
1684
1685static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1686{
1687 struct sym_args *args = arg;
1688
1689 if (kern_sym_match(args, name, type)) {
1690 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1691 ++args->cnt, start, type, name);
1692 args->near = true;
1693 } else if (args->near) {
1694 args->near = false;
1695 pr_err("\t\twhich is near\t\t%s\n", name);
1696 }
1697
1698 return 0;
1699}
1700
1701static int sym_not_found_error(const char *sym_name, int idx)
1702{
1703 if (idx > 0) {
1704 pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
1705 idx, sym_name);
1706 } else if (!idx) {
1707 pr_err("Global symbol '%s' not found.\n", sym_name);
1708 } else {
1709 pr_err("Symbol '%s' not found.\n", sym_name);
1710 }
1711 pr_err("Note that symbols must be functions.\n");
1712
1713 return -EINVAL;
1714}
1715
1716static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
1717{
1718 struct sym_args args = {
1719 .name = sym_name,
1720 .idx = idx,
1721 .global = !idx,
1722 .selected = idx > 0,
1723 };
1724 int err;
1725
1726 *start = 0;
1727 *size = 0;
1728
1729 err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
1730 if (err < 0) {
1731 pr_err("Failed to parse /proc/kallsyms\n");
1732 return err;
1733 }
1734
1735 if (args.duplicate) {
1736 pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
1737 args.cnt = 0;
1738 kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
1739 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1740 sym_name);
1741 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1742 return -EINVAL;
1743 }
1744
1745 if (!args.started) {
1746 pr_err("Kernel symbol lookup: ");
1747 return sym_not_found_error(sym_name, idx);
1748 }
1749
1750 *start = args.start;
1751 *size = args.size;
1752
1753 return 0;
1754}
1755
1756static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
1757 char type, u64 start)
1758{
1759 struct sym_args *args = arg;
1760
1761 if (!symbol_type__is_a(type, MAP__FUNCTION))
1762 return 0;
1763
1764 if (!args->started) {
1765 args->started = true;
1766 args->start = start;
1767 }
1768 /* Don't know exactly where the kernel ends, so we add a page */
1769 args->size = round_up(start, page_size) + page_size - args->start;
1770
1771 return 0;
1772}
1773
1774static int addr_filter__entire_kernel(struct addr_filter *filt)
1775{
1776 struct sym_args args = { .started = false };
1777 int err;
1778
1779 err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
1780 if (err < 0 || !args.started) {
1781 pr_err("Failed to parse /proc/kallsyms\n");
1782 return err;
1783 }
1784
1785 filt->addr = args.start;
1786 filt->size = args.size;
1787
1788 return 0;
1789}
1790
1791static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
1792{
1793 if (start + size >= filt->addr)
1794 return 0;
1795
1796 if (filt->sym_from) {
1797 pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
1798 filt->sym_to, start, filt->sym_from, filt->addr);
1799 } else {
1800 pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
1801 filt->sym_to, start, filt->addr);
1802 }
1803
1804 return -EINVAL;
1805}
1806
1807static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1808{
1809 bool no_size = false;
1810 u64 start, size;
1811 int err;
1812
1813 if (symbol_conf.kptr_restrict) {
1814 pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
1815 return -EINVAL;
1816 }
1817
1818 if (filt->sym_from && !strcmp(filt->sym_from, "*"))
1819 return addr_filter__entire_kernel(filt);
1820
1821 if (filt->sym_from) {
1822 err = find_kern_sym(filt->sym_from, &start, &size,
1823 filt->sym_from_idx);
1824 if (err)
1825 return err;
1826 filt->addr = start;
1827 if (filt->range && !filt->size && !filt->sym_to) {
1828 filt->size = size;
1829 no_size = !!size;
1830 }
1831 }
1832
1833 if (filt->sym_to) {
1834 err = find_kern_sym(filt->sym_to, &start, &size,
1835 filt->sym_to_idx);
1836 if (err)
1837 return err;
1838
1839 err = check_end_after_start(filt, start, size);
1840 if (err)
1841 return err;
1842 filt->size = start + size - filt->addr;
1843 no_size = !!size;
1844 }
1845
1846 /* The very last symbol in kallsyms does not imply a particular size */
1847 if (no_size) {
1848 pr_err("Cannot determine size of symbol '%s'\n",
1849 filt->sym_to ? filt->sym_to : filt->sym_from);
1850 return -EINVAL;
1851 }
1852
1853 return 0;
1854}
1855
1856static struct dso *load_dso(const char *name)
1857{
1858 struct map *map;
1859 struct dso *dso;
1860
1861 map = dso__new_map(name);
1862 if (!map)
1863 return NULL;
1864
1865 map__load(map);
1866
1867 dso = dso__get(map->dso);
1868
1869 map__put(map);
1870
1871 return dso;
1872}
1873
1874static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
1875 int idx)
1876{
1877 /* Same name, and global or the n'th found or any */
1878 return !arch__compare_symbol_names(name, sym->name) &&
1879 ((!idx && sym->binding == STB_GLOBAL) ||
1880 (idx > 0 && ++*cnt == idx) ||
1881 idx < 0);
1882}
1883
1884static void print_duplicate_syms(struct dso *dso, const char *sym_name)
1885{
1886 struct symbol *sym;
1887 bool near = false;
1888 int cnt = 0;
1889
1890 pr_err("Multiple symbols with name '%s'\n", sym_name);
1891
1892 sym = dso__first_symbol(dso, MAP__FUNCTION);
1893 while (sym) {
1894 if (dso_sym_match(sym, sym_name, &cnt, -1)) {
1895 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1896 ++cnt, sym->start,
1897 sym->binding == STB_GLOBAL ? 'g' :
1898 sym->binding == STB_LOCAL ? 'l' : 'w',
1899 sym->name);
1900 near = true;
1901 } else if (near) {
1902 near = false;
1903 pr_err("\t\twhich is near\t\t%s\n", sym->name);
1904 }
1905 sym = dso__next_symbol(sym);
1906 }
1907
1908 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1909 sym_name);
1910 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1911}
1912
1913static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
1914 u64 *size, int idx)
1915{
1916 struct symbol *sym;
1917 int cnt = 0;
1918
1919 *start = 0;
1920 *size = 0;
1921
1922 sym = dso__first_symbol(dso, MAP__FUNCTION);
1923 while (sym) {
1924 if (*start) {
1925 if (!*size)
1926 *size = sym->start - *start;
1927 if (idx > 0) {
1928 if (*size)
1929 return 1;
1930 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1931 print_duplicate_syms(dso, sym_name);
1932 return -EINVAL;
1933 }
1934 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1935 *start = sym->start;
1936 *size = sym->end - sym->start;
1937 }
1938 sym = dso__next_symbol(sym);
1939 }
1940
1941 if (!*start)
1942 return sym_not_found_error(sym_name, idx);
1943
1944 return 0;
1945}
1946
1947static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
1948{
1949 struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION);
1950 struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION);
1951
1952 if (!first_sym || !last_sym) {
1953 pr_err("Failed to determine filter for %s\nNo symbols found.\n",
1954 filt->filename);
1955 return -EINVAL;
1956 }
1957
1958 filt->addr = first_sym->start;
1959 filt->size = last_sym->end - first_sym->start;
1960
1961 return 0;
1962}
1963
1964static int addr_filter__resolve_syms(struct addr_filter *filt)
1965{
1966 u64 start, size;
1967 struct dso *dso;
1968 int err = 0;
1969
1970 if (!filt->sym_from && !filt->sym_to)
1971 return 0;
1972
1973 if (!filt->filename)
1974 return addr_filter__resolve_kernel_syms(filt);
1975
1976 dso = load_dso(filt->filename);
1977 if (!dso) {
1978 pr_err("Failed to load symbols from: %s\n", filt->filename);
1979 return -EINVAL;
1980 }
1981
1982 if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
1983 err = addr_filter__entire_dso(filt, dso);
1984 goto put_dso;
1985 }
1986
1987 if (filt->sym_from) {
1988 err = find_dso_sym(dso, filt->sym_from, &start, &size,
1989 filt->sym_from_idx);
1990 if (err)
1991 goto put_dso;
1992 filt->addr = start;
1993 if (filt->range && !filt->size && !filt->sym_to)
1994 filt->size = size;
1995 }
1996
1997 if (filt->sym_to) {
1998 err = find_dso_sym(dso, filt->sym_to, &start, &size,
1999 filt->sym_to_idx);
2000 if (err)
2001 goto put_dso;
2002
2003 err = check_end_after_start(filt, start, size);
2004 if (err)
2005 return err;
2006
2007 filt->size = start + size - filt->addr;
2008 }
2009
2010put_dso:
2011 dso__put(dso);
2012
2013 return err;
2014}
2015
2016static char *addr_filter__to_str(struct addr_filter *filt)
2017{
2018 char filename_buf[PATH_MAX];
2019 const char *at = "";
2020 const char *fn = "";
2021 char *filter;
2022 int err;
2023
2024 if (filt->filename) {
2025 at = "@";
2026 fn = realpath(filt->filename, filename_buf);
2027 if (!fn)
2028 return NULL;
2029 }
2030
2031 if (filt->range) {
2032 err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
2033 filt->action, filt->addr, filt->size, at, fn);
2034 } else {
2035 err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
2036 filt->action, filt->addr, at, fn);
2037 }
2038
2039 return err < 0 ? NULL : filter;
2040}
2041
2042static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
2043 int max_nr)
2044{
2045 struct addr_filters filts;
2046 struct addr_filter *filt;
2047 int err;
2048
2049 addr_filters__init(&filts);
2050
2051 err = addr_filters__parse_bare_filter(&filts, filter);
2052 if (err)
2053 goto out_exit;
2054
2055 if (filts.cnt > max_nr) {
2056 pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
2057 filts.cnt, max_nr);
2058 err = -EINVAL;
2059 goto out_exit;
2060 }
2061
2062 list_for_each_entry(filt, &filts.head, list) {
2063 char *new_filter;
2064
2065 err = addr_filter__resolve_syms(filt);
2066 if (err)
2067 goto out_exit;
2068
2069 new_filter = addr_filter__to_str(filt);
2070 if (!new_filter) {
2071 err = -ENOMEM;
2072 goto out_exit;
2073 }
2074
2075 if (perf_evsel__append_addr_filter(evsel, new_filter)) {
2076 err = -ENOMEM;
2077 goto out_exit;
2078 }
2079 }
2080
2081out_exit:
2082 addr_filters__exit(&filts);
2083
2084 if (err) {
2085 pr_err("Failed to parse address filter: '%s'\n", filter);
2086 pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
2087 pr_err("Where multiple filters are separated by space or comma.\n");
2088 }
2089
2090 return err;
2091}
2092
2093static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
2094{
2095 struct perf_pmu *pmu = NULL;
2096
2097 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
2098 if (pmu->type == evsel->attr.type)
2099 break;
2100 }
2101
2102 return pmu;
2103}
2104
2105static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
2106{
2107 struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
2108 int nr_addr_filters = 0;
2109
2110 if (!pmu)
2111 return 0;
2112
2113 perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
2114
2115 return nr_addr_filters;
2116}
2117
2118int auxtrace_parse_filters(struct perf_evlist *evlist)
2119{
2120 struct perf_evsel *evsel;
2121 char *filter;
2122 int err, max_nr;
2123
2124 evlist__for_each_entry(evlist, evsel) {
2125 filter = evsel->filter;
2126 max_nr = perf_evsel__nr_addr_filter(evsel);
2127 if (!filter || !max_nr)
2128 continue;
2129 evsel->filter = NULL;
2130 err = parse_addr_filter(evsel, filter, max_nr);
2131 free(filter);
2132 if (err)
2133 return err;
2134 pr_debug("Address filter: %s\n", evsel->filter);
2135 }
2136
2137 return 0;
2138}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 09286f193532..26fb1ee5746a 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -318,6 +318,48 @@ struct auxtrace_record {
318 unsigned int alignment; 318 unsigned int alignment;
319}; 319};
320 320
321/**
322 * struct addr_filter - address filter.
323 * @list: list node
324 * @range: true if it is a range filter
325 * @start: true if action is 'filter' or 'start'
326 * @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
327 * to 'stop')
328 * @sym_from: symbol name for the filter address
329 * @sym_to: symbol name that determines the filter size
330 * @sym_from_idx: selects n'th from symbols with the same name (0 means global
331 * and less than 0 means symbol must be unique)
332 * @sym_to_idx: same as @sym_from_idx but for @sym_to
333 * @addr: filter address
334 * @size: filter region size (for range filters)
335 * @filename: DSO file name or NULL for the kernel
336 * @str: allocated string that contains the other string members
337 */
338struct addr_filter {
339 struct list_head list;
340 bool range;
341 bool start;
342 const char *action;
343 const char *sym_from;
344 const char *sym_to;
345 int sym_from_idx;
346 int sym_to_idx;
347 u64 addr;
348 u64 size;
349 const char *filename;
350 char *str;
351};
352
353/**
354 * struct addr_filters - list of address filters.
355 * @head: list of address filters
356 * @cnt: number of address filters
357 */
358struct addr_filters {
359 struct list_head head;
360 int cnt;
361};
362
321#ifdef HAVE_AUXTRACE_SUPPORT 363#ifdef HAVE_AUXTRACE_SUPPORT
322 364
323/* 365/*
@@ -482,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
482 union perf_event *event); 524 union perf_event *event);
483void events_stats__auxtrace_error_warn(const struct events_stats *stats); 525void events_stats__auxtrace_error_warn(const struct events_stats *stats);
484 526
527void addr_filters__init(struct addr_filters *filts);
528void addr_filters__exit(struct addr_filters *filts);
529int addr_filters__parse_bare_filter(struct addr_filters *filts,
530 const char *filter);
531int auxtrace_parse_filters(struct perf_evlist *evlist);
532
485static inline int auxtrace__process_event(struct perf_session *session, 533static inline int auxtrace__process_event(struct perf_session *session,
486 union perf_event *event, 534 union perf_event *event,
487 struct perf_sample *sample, 535 struct perf_sample *sample,
@@ -640,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
640{ 688{
641} 689}
642 690
691static inline
692int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
693{
694 return 0;
695}
696
643int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 697int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
644 struct auxtrace_mmap_params *mp, 698 struct auxtrace_mmap_params *mp,
645 void *userpg, int fd); 699 void *userpg, int fd);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5651f3c12f93..e528c40739cc 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
620 620
621 ret = probe_cache__scan_sdt(cache, realname); 621 ret = probe_cache__scan_sdt(cache, realname);
622 if (ret >= 0) { 622 if (ret >= 0) {
623 pr_debug("Found %d SDTs in %s\n", ret, realname); 623 pr_debug4("Found %d SDTs in %s\n", ret, realname);
624 if (probe_cache__commit(cache) < 0) 624 if (probe_cache__commit(cache) < 0)
625 ret = -1; 625 ret = -1;
626 } 626 }
@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
691 691
692 /* Update SDT cache : error is just warned */ 692 /* Update SDT cache : error is just warned */
693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
694 pr_debug("Failed to update/scan SDT cache for %s\n", realname); 694 pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
695 695
696out_free: 696out_free:
697 if (!is_kallsyms) 697 if (!is_kallsyms)
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 4f979bb27b6c..7123f4de32cc 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -437,7 +437,7 @@ add_bpf_output_values(struct bt_ctf_event_class *event_class,
437 int ret; 437 int ret;
438 438
439 if (nr_elements * sizeof(u32) != raw_size) 439 if (nr_elements * sizeof(u32) != raw_size)
440 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n", 440 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %zu bytes\n",
441 raw_size, nr_elements * sizeof(u32) - raw_size); 441 raw_size, nr_elements * sizeof(u32) - raw_size);
442 442
443 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len"); 443 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index faec899435f2..41e068e94349 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -130,6 +130,22 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
130} 130}
131 131
132/** 132/**
133 * die_get_linkage_name - Get the linkage name of the object
134 * @dw_die: A DIE of the object
135 *
136 * Get the linkage name attiribute of given @dw_die.
137 * For C++ binary, the linkage name will be the mangled symbol.
138 */
139const char *die_get_linkage_name(Dwarf_Die *dw_die)
140{
141 Dwarf_Attribute attr;
142
143 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
144 return NULL;
145 return dwarf_formstring(&attr);
146}
147
148/**
133 * die_compare_name - Compare diename and tname 149 * die_compare_name - Compare diename and tname
134 * @dw_die: a DIE 150 * @dw_die: a DIE
135 * @tname: a string of target name 151 * @tname: a string of target name
@@ -145,18 +161,26 @@ bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
145} 161}
146 162
147/** 163/**
148 * die_match_name - Match diename and glob 164 * die_match_name - Match diename/linkage name and glob
149 * @dw_die: a DIE 165 * @dw_die: a DIE
150 * @glob: a string of target glob pattern 166 * @glob: a string of target glob pattern
151 * 167 *
152 * Glob matching the name of @dw_die and @glob. Return false if matching fail. 168 * Glob matching the name of @dw_die and @glob. Return false if matching fail.
169 * This also match linkage name.
153 */ 170 */
154bool die_match_name(Dwarf_Die *dw_die, const char *glob) 171bool die_match_name(Dwarf_Die *dw_die, const char *glob)
155{ 172{
156 const char *name; 173 const char *name;
157 174
158 name = dwarf_diename(dw_die); 175 name = dwarf_diename(dw_die);
159 return name ? strglobmatch(name, glob) : false; 176 if (name && strglobmatch(name, glob))
177 return true;
178 /* fall back to check linkage name */
179 name = die_get_linkage_name(dw_die);
180 if (name && strglobmatch(name, glob))
181 return true;
182
183 return false;
160} 184}
161 185
162/** 186/**
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 8b6d2f83af02..8ac53bf1ec4e 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -38,6 +38,9 @@ int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
38int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, 38int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
39 int (*callback)(Dwarf_Die *, void *), void *data); 39 int (*callback)(Dwarf_Die *, void *), void *data);
40 40
41/* Get DW_AT_linkage_name (should be NULL for C binary) */
42const char *die_get_linkage_name(Dwarf_Die *dw_die);
43
41/* Ensure that this DIE is a subprogram and definition (not declaration) */ 44/* Ensure that this DIE is a subprogram and definition (not declaration) */
42bool die_is_func_def(Dwarf_Die *dw_die); 45bool die_is_func_def(Dwarf_Die *dw_die);
43 46
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2880e2226fdb..8ab0d7da956b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -346,7 +346,8 @@ out:
346 if (!strcmp(execname, "")) 346 if (!strcmp(execname, ""))
347 strcpy(execname, anonstr); 347 strcpy(execname, anonstr);
348 348
349 if (!strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) { 349 if (hugetlbfs_mnt_len &&
350 !strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
350 strcpy(execname, anonstr); 351 strcpy(execname, anonstr);
351 event->mmap2.flags |= MAP_HUGETLB; 352 event->mmap2.flags |= MAP_HUGETLB;
352 } 353 }
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f3225a2e6eee..380e84c3af3d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1045,15 +1045,15 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
1045 return -1; 1045 return -1;
1046} 1046}
1047 1047
1048int perf_evsel__append_filter(struct perf_evsel *evsel, 1048static int perf_evsel__append_filter(struct perf_evsel *evsel,
1049 const char *op, const char *filter) 1049 const char *fmt, const char *filter)
1050{ 1050{
1051 char *new_filter; 1051 char *new_filter;
1052 1052
1053 if (evsel->filter == NULL) 1053 if (evsel->filter == NULL)
1054 return perf_evsel__set_filter(evsel, filter); 1054 return perf_evsel__set_filter(evsel, filter);
1055 1055
1056 if (asprintf(&new_filter,"(%s) %s (%s)", evsel->filter, op, filter) > 0) { 1056 if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) {
1057 free(evsel->filter); 1057 free(evsel->filter);
1058 evsel->filter = new_filter; 1058 evsel->filter = new_filter;
1059 return 0; 1059 return 0;
@@ -1062,6 +1062,16 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
1062 return -1; 1062 return -1;
1063} 1063}
1064 1064
1065int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter)
1066{
1067 return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter);
1068}
1069
1070int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1071{
1072 return perf_evsel__append_filter(evsel, "%s,%s", filter);
1073}
1074
1065int perf_evsel__enable(struct perf_evsel *evsel) 1075int perf_evsel__enable(struct perf_evsel *evsel)
1066{ 1076{
1067 int nthreads = thread_map__nr(evsel->threads); 1077 int nthreads = thread_map__nr(evsel->threads);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 323806082c58..b1503b0ecdff 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -235,8 +235,9 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
235 bool use_sample_identifier); 235 bool use_sample_identifier);
236 236
237int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter); 237int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
238int perf_evsel__append_filter(struct perf_evsel *evsel, 238int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
239 const char *op, const char *filter); 239int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
240 const char *filter);
240int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 241int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
241 const char *filter); 242 const char *filter);
242int perf_evsel__enable(struct perf_evsel *evsel); 243int perf_evsel__enable(struct perf_evsel *evsel);
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 9111e0666950..662a0a6182e7 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
122 if (!node) 122 if (!node)
123 break; 123 break;
124 124
125 if (node->sym && node->sym->idle)
126 goto next;
127
128 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 125 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
129 126
130 if (print_ip) 127 if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
158 155
159 if (!print_oneline) 156 if (!print_oneline)
160 printed += fprintf(fp, "\n"); 157 printed += fprintf(fp, "\n");
161next: 158
162 callchain_cursor_advance(cursor); 159 callchain_cursor_advance(cursor);
163 } 160 }
164 } 161 }
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
181 if (cursor != NULL) { 178 if (cursor != NULL) {
182 printed += sample__fprintf_callchain(sample, left_alignment, 179 printed += sample__fprintf_callchain(sample, left_alignment,
183 print_opts, cursor, fp); 180 print_opts, cursor, fp);
184 } else if (!(al->sym && al->sym->idle)) { 181 } else {
185 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 182 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
186 183
187 if (print_ip) 184 if (print_ip)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 8ff6c6a61291..7591a0c37473 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -80,6 +80,7 @@ struct intel_pt_decoder {
80 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 80 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
81 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 81 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
82 uint64_t max_insn_cnt, void *data); 82 uint64_t max_insn_cnt, void *data);
83 bool (*pgd_ip)(uint64_t ip, void *data);
83 void *data; 84 void *data;
84 struct intel_pt_state state; 85 struct intel_pt_state state;
85 const unsigned char *buf; 86 const unsigned char *buf;
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
186 187
187 decoder->get_trace = params->get_trace; 188 decoder->get_trace = params->get_trace;
188 decoder->walk_insn = params->walk_insn; 189 decoder->walk_insn = params->walk_insn;
190 decoder->pgd_ip = params->pgd_ip;
189 decoder->data = params->data; 191 decoder->data = params->data;
190 decoder->return_compression = params->return_compression; 192 decoder->return_compression = params->return_compression;
191 193
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1008 int err; 1010 int err;
1009 1011
1010 err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0); 1012 err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
1013 if (err == INTEL_PT_RETURN &&
1014 decoder->pgd_ip &&
1015 decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
1016 (decoder->state.type & INTEL_PT_BRANCH) &&
1017 decoder->pgd_ip(decoder->state.to_ip, decoder->data)) {
1018 /* Unconditional branch leaving filter region */
1019 decoder->no_progress = 0;
1020 decoder->pge = false;
1021 decoder->continuous_period = false;
1022 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1023 decoder->state.to_ip = 0;
1024 return 0;
1025 }
1011 if (err == INTEL_PT_RETURN) 1026 if (err == INTEL_PT_RETURN)
1012 return 0; 1027 return 0;
1013 if (err) 1028 if (err)
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1036 } 1051 }
1037 1052
1038 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { 1053 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
1054 uint64_t to_ip = decoder->ip + intel_pt_insn.length +
1055 intel_pt_insn.rel;
1056
1057 if (decoder->pgd_ip &&
1058 decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
1059 decoder->pgd_ip(to_ip, decoder->data)) {
1060 /* Conditional branch leaving filter region */
1061 decoder->pge = false;
1062 decoder->continuous_period = false;
1063 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1064 decoder->ip = to_ip;
1065 decoder->state.from_ip = decoder->ip;
1066 decoder->state.to_ip = 0;
1067 return 0;
1068 }
1039 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", 1069 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
1040 decoder->ip); 1070 decoder->ip);
1041 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1071 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 02c38fec1c37..89399985fa4d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -83,6 +83,7 @@ struct intel_pt_params {
83 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 83 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
84 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 84 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
85 uint64_t max_insn_cnt, void *data); 85 uint64_t max_insn_cnt, void *data);
86 bool (*pgd_ip)(uint64_t ip, void *data);
86 void *data; 87 void *data;
87 bool return_compression; 88 bool return_compression;
88 uint64_t period; 89 uint64_t period;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b9cc353cace2..dc041d4368c8 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -103,6 +103,9 @@ struct intel_pt {
103 unsigned max_non_turbo_ratio; 103 unsigned max_non_turbo_ratio;
104 104
105 unsigned long num_events; 105 unsigned long num_events;
106
107 char *filter;
108 struct addr_filters filts;
106}; 109};
107 110
108enum switch_state { 111enum switch_state {
@@ -241,7 +244,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
241 } 244 }
242 245
243 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 246 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
244 247next:
245 buffer = auxtrace_buffer__next(queue, buffer); 248 buffer = auxtrace_buffer__next(queue, buffer);
246 if (!buffer) { 249 if (!buffer) {
247 if (old_buffer) 250 if (old_buffer)
@@ -264,9 +267,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
264 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 267 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
265 return -ENOMEM; 268 return -ENOMEM;
266 269
267 if (old_buffer)
268 auxtrace_buffer__drop_data(old_buffer);
269
270 if (buffer->use_data) { 270 if (buffer->use_data) {
271 b->len = buffer->use_size; 271 b->len = buffer->use_size;
272 b->buf = buffer->use_data; 272 b->buf = buffer->use_data;
@@ -276,6 +276,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
276 } 276 }
277 b->ref_timestamp = buffer->reference; 277 b->ref_timestamp = buffer->reference;
278 278
279 /*
280 * If in snapshot mode and the buffer has no usable data, get next
281 * buffer and again check overlap against old_buffer.
282 */
283 if (ptq->pt->snapshot_mode && !b->len)
284 goto next;
285
286 if (old_buffer)
287 auxtrace_buffer__drop_data(old_buffer);
288
279 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode && 289 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
280 !buffer->consecutive)) { 290 !buffer->consecutive)) {
281 b->consecutive = false; 291 b->consecutive = false;
@@ -541,6 +551,76 @@ out_no_cache:
541 return 0; 551 return 0;
542} 552}
543 553
554static bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
555 uint64_t offset, const char *filename)
556{
557 struct addr_filter *filt;
558 bool have_filter = false;
559 bool hit_tracestop = false;
560 bool hit_filter = false;
561
562 list_for_each_entry(filt, &pt->filts.head, list) {
563 if (filt->start)
564 have_filter = true;
565
566 if ((filename && !filt->filename) ||
567 (!filename && filt->filename) ||
568 (filename && strcmp(filename, filt->filename)))
569 continue;
570
571 if (!(offset >= filt->addr && offset < filt->addr + filt->size))
572 continue;
573
574 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
575 ip, offset, filename ? filename : "[kernel]",
576 filt->start ? "filter" : "stop",
577 filt->addr, filt->size);
578
579 if (filt->start)
580 hit_filter = true;
581 else
582 hit_tracestop = true;
583 }
584
585 if (!hit_tracestop && !hit_filter)
586 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
587 ip, offset, filename ? filename : "[kernel]");
588
589 return hit_tracestop || (have_filter && !hit_filter);
590}
591
592static int __intel_pt_pgd_ip(uint64_t ip, void *data)
593{
594 struct intel_pt_queue *ptq = data;
595 struct thread *thread;
596 struct addr_location al;
597 u8 cpumode;
598 u64 offset;
599
600 if (ip >= ptq->pt->kernel_start)
601 return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
602
603 cpumode = PERF_RECORD_MISC_USER;
604
605 thread = ptq->thread;
606 if (!thread)
607 return -EINVAL;
608
609 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al);
610 if (!al.map || !al.map->dso)
611 return -EINVAL;
612
613 offset = al.map->map_ip(al.map, ip);
614
615 return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
616 al.map->dso->long_name);
617}
618
619static bool intel_pt_pgd_ip(uint64_t ip, void *data)
620{
621 return __intel_pt_pgd_ip(ip, data) > 0;
622}
623
544static bool intel_pt_get_config(struct intel_pt *pt, 624static bool intel_pt_get_config(struct intel_pt *pt,
545 struct perf_event_attr *attr, u64 *config) 625 struct perf_event_attr *attr, u64 *config)
546{ 626{
@@ -717,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
717 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; 797 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
718 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; 798 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
719 799
800 if (pt->filts.cnt > 0)
801 params.pgd_ip = intel_pt_pgd_ip;
802
720 if (pt->synth_opts.instructions) { 803 if (pt->synth_opts.instructions) {
721 if (pt->synth_opts.period) { 804 if (pt->synth_opts.period) {
722 switch (pt->synth_opts.period_type) { 805 switch (pt->synth_opts.period_type) {
@@ -1767,6 +1850,8 @@ static void intel_pt_free(struct perf_session *session)
1767 intel_pt_free_events(session); 1850 intel_pt_free_events(session);
1768 session->auxtrace = NULL; 1851 session->auxtrace = NULL;
1769 thread__put(pt->unknown_thread); 1852 thread__put(pt->unknown_thread);
1853 addr_filters__exit(&pt->filts);
1854 zfree(&pt->filter);
1770 free(pt); 1855 free(pt);
1771} 1856}
1772 1857
@@ -2016,6 +2101,8 @@ static const char * const intel_pt_info_fmts[] = {
2016 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", 2101 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n",
2017 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", 2102 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n",
2018 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", 2103 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n",
2104 [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n",
2105 [INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n",
2019}; 2106};
2020 2107
2021static void intel_pt_print_info(u64 *arr, int start, int finish) 2108static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2029,12 +2116,28 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
2029 fprintf(stdout, intel_pt_info_fmts[i], arr[i]); 2116 fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
2030} 2117}
2031 2118
2119static void intel_pt_print_info_str(const char *name, const char *str)
2120{
2121 if (!dump_trace)
2122 return;
2123
2124 fprintf(stdout, " %-20s%s\n", name, str ? str : "");
2125}
2126
2127static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
2128{
2129 return auxtrace_info->header.size >=
2130 sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
2131}
2132
2032int intel_pt_process_auxtrace_info(union perf_event *event, 2133int intel_pt_process_auxtrace_info(union perf_event *event,
2033 struct perf_session *session) 2134 struct perf_session *session)
2034{ 2135{
2035 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; 2136 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
2036 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS; 2137 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
2037 struct intel_pt *pt; 2138 struct intel_pt *pt;
2139 void *info_end;
2140 u64 *info;
2038 int err; 2141 int err;
2039 2142
2040 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) + 2143 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2045,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2045 if (!pt) 2148 if (!pt)
2046 return -ENOMEM; 2149 return -ENOMEM;
2047 2150
2151 addr_filters__init(&pt->filts);
2152
2048 perf_config(intel_pt_perf_config, pt); 2153 perf_config(intel_pt_perf_config, pt);
2049 2154
2050 err = auxtrace_queues__init(&pt->queues); 2155 err = auxtrace_queues__init(&pt->queues);
@@ -2069,8 +2174,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2069 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, 2174 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
2070 INTEL_PT_PER_CPU_MMAPS); 2175 INTEL_PT_PER_CPU_MMAPS);
2071 2176
2072 if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) + 2177 if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
2073 (sizeof(u64) * INTEL_PT_CYC_BIT)) {
2074 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT]; 2178 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
2075 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS]; 2179 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
2076 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N]; 2180 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
@@ -2080,6 +2184,54 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2080 INTEL_PT_CYC_BIT); 2184 INTEL_PT_CYC_BIT);
2081 } 2185 }
2082 2186
2187 if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
2188 pt->max_non_turbo_ratio =
2189 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
2190 intel_pt_print_info(&auxtrace_info->priv[0],
2191 INTEL_PT_MAX_NONTURBO_RATIO,
2192 INTEL_PT_MAX_NONTURBO_RATIO);
2193 }
2194
2195 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
2196 info_end = (void *)info + auxtrace_info->header.size;
2197
2198 if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
2199 size_t len;
2200
2201 len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
2202 intel_pt_print_info(&auxtrace_info->priv[0],
2203 INTEL_PT_FILTER_STR_LEN,
2204 INTEL_PT_FILTER_STR_LEN);
2205 if (len) {
2206 const char *filter = (const char *)info;
2207
2208 len = roundup(len + 1, 8);
2209 info += len >> 3;
2210 if ((void *)info > info_end) {
2211 pr_err("%s: bad filter string length\n", __func__);
2212 err = -EINVAL;
2213 goto err_free_queues;
2214 }
2215 pt->filter = memdup(filter, len);
2216 if (!pt->filter) {
2217 err = -ENOMEM;
2218 goto err_free_queues;
2219 }
2220 if (session->header.needs_swap)
2221 mem_bswap_64(pt->filter, len);
2222 if (pt->filter[len - 1]) {
2223 pr_err("%s: filter string not null terminated\n", __func__);
2224 err = -EINVAL;
2225 goto err_free_queues;
2226 }
2227 err = addr_filters__parse_bare_filter(&pt->filts,
2228 filter);
2229 if (err)
2230 goto err_free_queues;
2231 }
2232 intel_pt_print_info_str("Filter string", pt->filter);
2233 }
2234
2083 pt->timeless_decoding = intel_pt_timeless_decoding(pt); 2235 pt->timeless_decoding = intel_pt_timeless_decoding(pt);
2084 pt->have_tsc = intel_pt_have_tsc(pt); 2236 pt->have_tsc = intel_pt_have_tsc(pt);
2085 pt->sampling_mode = false; 2237 pt->sampling_mode = false;
@@ -2121,11 +2273,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2121 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist); 2273 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
2122 if (!pt->switch_evsel) { 2274 if (!pt->switch_evsel) {
2123 pr_err("%s: missing sched_switch event\n", __func__); 2275 pr_err("%s: missing sched_switch event\n", __func__);
2276 err = -EINVAL;
2124 goto err_delete_thread; 2277 goto err_delete_thread;
2125 } 2278 }
2126 } else if (pt->have_sched_switch == 2 && 2279 } else if (pt->have_sched_switch == 2 &&
2127 !intel_pt_find_switch(session->evlist)) { 2280 !intel_pt_find_switch(session->evlist)) {
2128 pr_err("%s: missing context_switch attribute flag\n", __func__); 2281 pr_err("%s: missing context_switch attribute flag\n", __func__);
2282 err = -EINVAL;
2129 goto err_delete_thread; 2283 goto err_delete_thread;
2130 } 2284 }
2131 2285
@@ -2149,7 +2303,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2149 if (pt->tc.time_mult) { 2303 if (pt->tc.time_mult) {
2150 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000); 2304 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
2151 2305
2152 pt->max_non_turbo_ratio = (tsc_freq + 50000000) / 100000000; 2306 if (!pt->max_non_turbo_ratio)
2307 pt->max_non_turbo_ratio =
2308 (tsc_freq + 50000000) / 100000000;
2153 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); 2309 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
2154 intel_pt_log("Maximum non-turbo ratio %u\n", 2310 intel_pt_log("Maximum non-turbo ratio %u\n",
2155 pt->max_non_turbo_ratio); 2311 pt->max_non_turbo_ratio);
@@ -2193,6 +2349,8 @@ err_free_queues:
2193 auxtrace_queues__free(&pt->queues); 2349 auxtrace_queues__free(&pt->queues);
2194 session->auxtrace = NULL; 2350 session->auxtrace = NULL;
2195err_free: 2351err_free:
2352 addr_filters__exit(&pt->filts);
2353 zfree(&pt->filter);
2196 free(pt); 2354 free(pt);
2197 return err; 2355 return err;
2198} 2356}
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 0065949df693..e13b14e5a37b 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -34,11 +34,11 @@ enum {
34 INTEL_PT_TSC_CTC_N, 34 INTEL_PT_TSC_CTC_N,
35 INTEL_PT_TSC_CTC_D, 35 INTEL_PT_TSC_CTC_D,
36 INTEL_PT_CYC_BIT, 36 INTEL_PT_CYC_BIT,
37 INTEL_PT_MAX_NONTURBO_RATIO,
38 INTEL_PT_FILTER_STR_LEN,
37 INTEL_PT_AUXTRACE_PRIV_MAX, 39 INTEL_PT_AUXTRACE_PRIV_MAX,
38}; 40};
39 41
40#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64))
41
42struct auxtrace_record; 42struct auxtrace_record;
43struct perf_tool; 43struct perf_tool;
44union perf_event; 44union perf_event;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 2eb8b1ed4cc8..33546c3ac1fe 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1760,20 +1760,49 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
1760static int set_filter(struct perf_evsel *evsel, const void *arg) 1760static int set_filter(struct perf_evsel *evsel, const void *arg)
1761{ 1761{
1762 const char *str = arg; 1762 const char *str = arg;
1763 bool found = false;
1764 int nr_addr_filters = 0;
1765 struct perf_pmu *pmu = NULL;
1763 1766
1764 if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { 1767 if (evsel == NULL)
1765 fprintf(stderr, 1768 goto err;
1766 "--filter option should follow a -e tracepoint option\n"); 1769
1767 return -1; 1770 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
1771 if (perf_evsel__append_tp_filter(evsel, str) < 0) {
1772 fprintf(stderr,
1773 "not enough memory to hold filter string\n");
1774 return -1;
1775 }
1776
1777 return 0;
1768 } 1778 }
1769 1779
1770 if (perf_evsel__append_filter(evsel, "&&", str) < 0) { 1780 while ((pmu = perf_pmu__scan(pmu)) != NULL)
1781 if (pmu->type == evsel->attr.type) {
1782 found = true;
1783 break;
1784 }
1785
1786 if (found)
1787 perf_pmu__scan_file(pmu, "nr_addr_filters",
1788 "%d", &nr_addr_filters);
1789
1790 if (!nr_addr_filters)
1791 goto err;
1792
1793 if (perf_evsel__append_addr_filter(evsel, str) < 0) {
1771 fprintf(stderr, 1794 fprintf(stderr,
1772 "not enough memory to hold filter string\n"); 1795 "not enough memory to hold filter string\n");
1773 return -1; 1796 return -1;
1774 } 1797 }
1775 1798
1776 return 0; 1799 return 0;
1800
1801err:
1802 fprintf(stderr,
1803 "--filter option should follow a -e tracepoint or HW tracer option\n");
1804
1805 return -1;
1777} 1806}
1778 1807
1779int parse_filter(const struct option *opt, const char *str, 1808int parse_filter(const struct option *opt, const char *str,
@@ -1798,7 +1827,7 @@ static int add_exclude_perf_filter(struct perf_evsel *evsel,
1798 1827
1799 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 1828 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
1800 1829
1801 if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) { 1830 if (perf_evsel__append_tp_filter(evsel, new_filter) < 0) {
1802 fprintf(stderr, 1831 fprintf(stderr,
1803 "not enough memory to hold filter string\n"); 1832 "not enough memory to hold filter string\n");
1804 return -1; 1833 return -1;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index bc60ce49720b..fcfbef07b92d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -213,9 +213,13 @@ static int convert_exec_to_group(const char *exec, char **result)
213 goto out; 213 goto out;
214 } 214 }
215 215
216 ptr2 = strpbrk(ptr1, "-._"); 216 for (ptr2 = ptr1; ptr2 != '\0'; ptr2++) {
217 if (ptr2) 217 if (!isalnum(*ptr2) && *ptr2 != '_') {
218 *ptr2 = '\0'; 218 *ptr2 = '\0';
219 break;
220 }
221 }
222
219 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); 223 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
220 if (ret < 0) 224 if (ret < 0)
221 goto out; 225 goto out;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 6f931e442f14..436b64731f65 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
699 INIT_LIST_HEAD(&sdtlist); 699 INIT_LIST_HEAD(&sdtlist);
700 ret = get_sdt_note_list(&sdtlist, pathname); 700 ret = get_sdt_note_list(&sdtlist, pathname);
701 if (ret < 0) { 701 if (ret < 0) {
702 pr_debug("Failed to get sdt note: %d\n", ret); 702 pr_debug4("Failed to get sdt note: %d\n", ret);
703 return ret; 703 return ret;
704 } 704 }
705 list_for_each_entry(note, &sdtlist, note_list) { 705 list_for_each_entry(note, &sdtlist, note_list) {
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 8daca4fc1f8d..df4debe564da 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -955,6 +955,11 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
955 dwarf_diename(in_die)); 955 dwarf_diename(in_die));
956 return -ENOENT; 956 return -ENOENT;
957 } 957 }
958 if (addr == 0) {
959 pr_debug("%s has no valid entry address. skipped.\n",
960 dwarf_diename(in_die));
961 return -ENOENT;
962 }
958 pf->addr = addr; 963 pf->addr = addr;
959 pf->addr += pp->offset; 964 pf->addr += pp->offset;
960 pr_debug("found inline addr: 0x%jx\n", 965 pr_debug("found inline addr: 0x%jx\n",
@@ -988,7 +993,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
988 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) 993 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
989 return DWARF_CB_OK; 994 return DWARF_CB_OK;
990 995
991 pr_debug("Matched function: %s\n", dwarf_diename(sp_die)); 996 pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
997 (unsigned long)dwarf_dieoffset(sp_die));
992 pf->fname = dwarf_decl_file(sp_die); 998 pf->fname = dwarf_decl_file(sp_die);
993 if (pp->line) { /* Function relative line */ 999 if (pp->line) { /* Function relative line */
994 dwarf_decl_line(sp_die, &pf->lno); 1000 dwarf_decl_line(sp_die, &pf->lno);
@@ -997,8 +1003,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
997 } else if (die_is_func_instance(sp_die)) { 1003 } else if (die_is_func_instance(sp_die)) {
998 /* Instances always have the entry address */ 1004 /* Instances always have the entry address */
999 dwarf_entrypc(sp_die, &pf->addr); 1005 dwarf_entrypc(sp_die, &pf->addr);
1006 /* But in some case the entry address is 0 */
1007 if (pf->addr == 0) {
1008 pr_debug("%s has no entry PC. Skipped\n",
1009 dwarf_diename(sp_die));
1010 param->retval = 0;
1000 /* Real function */ 1011 /* Real function */
1001 if (pp->lazy_line) 1012 } else if (pp->lazy_line)
1002 param->retval = find_probe_point_lazy(sp_die, pf); 1013 param->retval = find_probe_point_lazy(sp_die, pf);
1003 else { 1014 else {
1004 skip_prologue(sp_die, pf); 1015 skip_prologue(sp_die, pf);
@@ -1011,7 +1022,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1011 param->retval = die_walk_instances(sp_die, 1022 param->retval = die_walk_instances(sp_die,
1012 probe_point_inline_cb, (void *)pf); 1023 probe_point_inline_cb, (void *)pf);
1013 /* This could be a non-existed inline definition */ 1024 /* This could be a non-existed inline definition */
1014 if (param->retval == -ENOENT && strisglob(pp->function)) 1025 if (param->retval == -ENOENT)
1015 param->retval = 0; 1026 param->retval = 0;
1016 } 1027 }
1017 1028
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 19c9c558454f..aecff69a510d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -345,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)
345 return NULL; 345 return NULL;
346} 346}
347 347
348static struct symbol *symbols__last(struct rb_root *symbols)
349{
350 struct rb_node *n = rb_last(symbols);
351
352 if (n)
353 return rb_entry(n, struct symbol, rb_node);
354
355 return NULL;
356}
357
348static struct symbol *symbols__next(struct symbol *sym) 358static struct symbol *symbols__next(struct symbol *sym)
349{ 359{
350 struct rb_node *n = rb_next(&sym->rb_node); 360 struct rb_node *n = rb_next(&sym->rb_node);
@@ -466,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
466 return symbols__first(&dso->symbols[type]); 476 return symbols__first(&dso->symbols[type]);
467} 477}
468 478
479struct symbol *dso__last_symbol(struct dso *dso, enum map_type type)
480{
481 return symbols__last(&dso->symbols[type]);
482}
483
469struct symbol *dso__next_symbol(struct symbol *sym) 484struct symbol *dso__next_symbol(struct symbol *sym)
470{ 485{
471 return symbols__next(sym); 486 return symbols__next(sym);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0dacfb7d5b67..d964844eb314 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -259,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
259struct symbol *symbol__next_by_name(struct symbol *sym); 259struct symbol *symbol__next_by_name(struct symbol *sym);
260 260
261struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 261struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
262struct symbol *dso__last_symbol(struct dso *dso, enum map_type type);
262struct symbol *dso__next_symbol(struct symbol *sym); 263struct symbol *dso__next_symbol(struct symbol *sym);
263 264
264enum dso_type dso__type_fd(int fd); 265enum dso_type dso__type_fd(int fd);