aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/perf-trace.txt53
-rw-r--r--tools/perf/Makefile13
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-test.c120
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/builtin-trace.c310
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/config/feature-tests.mak11
-rw-r--r--tools/perf/perf.c3
-rw-r--r--tools/perf/util/cpumap.h11
-rw-r--r--tools/perf/util/dwarf-aux.c2
-rw-r--r--tools/perf/util/evlist.c61
-rw-r--r--tools/perf/util/evlist.h6
-rw-r--r--tools/perf/util/evsel.c88
-rw-r--r--tools/perf/util/evsel.h18
-rw-r--r--tools/perf/util/header.c6
-rw-r--r--tools/perf/util/hist.c9
-rw-r--r--tools/perf/util/parse-events.c46
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/session.c6
22 files changed, 683 insertions, 90 deletions
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
new file mode 100644
index 000000000000..3a2ae37310a9
--- /dev/null
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -0,0 +1,53 @@
1perf-trace(1)
2=============
3
4NAME
5----
6perf-trace - strace inspired tool
7
8SYNOPSIS
9--------
10[verse]
11'perf trace'
12
13DESCRIPTION
14-----------
15This command will show the events associated with the target, initially
16syscalls, but other system events like pagefaults, task lifetime events,
17scheduling events, etc.
18
19Initially this is a live mode only tool, but eventually will work with
20perf.data files like the other tools, allowing a detached 'record' from
21analysis phases.
22
23OPTIONS
24-------
25
26--all-cpus::
27 System-wide collection from all CPUs.
28
29-p::
30--pid=::
31 Record events on existing process ID (comma separated list).
32
33--tid=::
34 Record events on existing thread ID (comma separated list).
35
36--uid=::
37 Record events in threads owned by uid. Name or number.
38
39--no-inherit::
40 Child tasks do not inherit counters.
41
42--mmap-pages=::
43 Number of mmap data pages. Must be a power of two.
44
45--cpu::
46Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
47comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
48In per-thread mode with inheritance mode on (default), Events are captured only when
49the thread executes on the designated CPUs. Default is to monitor all CPUs.
50
51SEE ALSO
52--------
53linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 251dcd7fb5ac..e5e71e7d95a0 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -559,6 +559,19 @@ else
559 LIB_OBJS += $(OUTPUT)util/unwind.o 559 LIB_OBJS += $(OUTPUT)util/unwind.o
560endif 560endif
561 561
562ifdef NO_LIBAUDIT
563 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
564else
565 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
566 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
567 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
568 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
569 else
570 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
571 EXTLIBS += -laudit
572 endif
573endif
574
562ifdef NO_NEWT 575ifdef NO_NEWT
563 BASIC_CFLAGS += -DNO_NEWT_SUPPORT 576 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
564else 577else
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2cb74343de3e..f14cb5fdb91f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -320,7 +320,7 @@ try_again:
320 } 320 }
321 } 321 }
322 322
323 if (perf_evlist__set_filters(evlist)) { 323 if (perf_evlist__apply_filters(evlist)) {
324 error("failed to set filter with %d (%s)\n", errno, 324 error("failed to set filter with %d (%s)\n", errno,
325 strerror(errno)); 325 strerror(errno));
326 rc = -1; 326 rc = -1;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e0f65fe65944..e8cd4d81b06e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -478,7 +478,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
478 counter->supported = true; 478 counter->supported = true;
479 } 479 }
480 480
481 if (perf_evlist__set_filters(evsel_list)) { 481 if (perf_evlist__apply_filters(evsel_list)) {
482 error("failed to set filter with %d (%s)\n", errno, 482 error("failed to set filter with %d (%s)\n", errno,
483 strerror(errno)); 483 strerror(errno));
484 return -1; 484 return -1;
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 78b47a75a7c9..484f26cc0c00 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -564,7 +564,7 @@ static int test__basic_mmap(void)
564 goto out_munmap; 564 goto out_munmap;
565 } 565 }
566 566
567 err = perf_evlist__parse_sample(evlist, event, &sample, false); 567 err = perf_evlist__parse_sample(evlist, event, &sample);
568 if (err) { 568 if (err) {
569 pr_err("Can't parse sample, err = %d\n", err); 569 pr_err("Can't parse sample, err = %d\n", err);
570 goto out_munmap; 570 goto out_munmap;
@@ -781,7 +781,7 @@ static int test__PERF_RECORD(void)
781 if (type < PERF_RECORD_MAX) 781 if (type < PERF_RECORD_MAX)
782 nr_events[type]++; 782 nr_events[type]++;
783 783
784 err = perf_evlist__parse_sample(evlist, event, &sample, false); 784 err = perf_evlist__parse_sample(evlist, event, &sample);
785 if (err < 0) { 785 if (err < 0) {
786 if (verbose) 786 if (verbose)
787 perf_event__fprintf(event, stderr); 787 perf_event__fprintf(event, stderr);
@@ -1289,6 +1289,118 @@ static int perf_evsel__tp_sched_test(void)
1289 return ret; 1289 return ret;
1290} 1290}
1291 1291
1292static int test__syscall_open_tp_fields(void)
1293{
1294 struct perf_record_opts opts = {
1295 .target = {
1296 .uid = UINT_MAX,
1297 .uses_mmap = true,
1298 },
1299 .no_delay = true,
1300 .freq = 1,
1301 .mmap_pages = 256,
1302 .raw_samples = true,
1303 };
1304 const char *filename = "/etc/passwd";
1305 int flags = O_RDONLY | O_DIRECTORY;
1306 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1307 struct perf_evsel *evsel;
1308 int err = -1, i, nr_events = 0, nr_polls = 0;
1309
1310 if (evlist == NULL) {
1311 pr_debug("%s: perf_evlist__new\n", __func__);
1312 goto out;
1313 }
1314
1315 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
1316 if (evsel == NULL) {
1317 pr_debug("%s: perf_evsel__newtp\n", __func__);
1318 goto out_delete_evlist;
1319 }
1320
1321 perf_evlist__add(evlist, evsel);
1322
1323 err = perf_evlist__create_maps(evlist, &opts.target);
1324 if (err < 0) {
1325 pr_debug("%s: perf_evlist__create_maps\n", __func__);
1326 goto out_delete_evlist;
1327 }
1328
1329 perf_evsel__config(evsel, &opts, evsel);
1330
1331 evlist->threads->map[0] = getpid();
1332
1333 err = perf_evlist__open(evlist);
1334 if (err < 0) {
1335 pr_debug("perf_evlist__open: %s\n", strerror(errno));
1336 goto out_delete_evlist;
1337 }
1338
1339 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1340 if (err < 0) {
1341 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
1342 goto out_delete_evlist;
1343 }
1344
1345 perf_evlist__enable(evlist);
1346
1347 /*
1348 * Generate the event:
1349 */
1350 open(filename, flags);
1351
1352 while (1) {
1353 int before = nr_events;
1354
1355 for (i = 0; i < evlist->nr_mmaps; i++) {
1356 union perf_event *event;
1357
1358 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1359 const u32 type = event->header.type;
1360 int tp_flags;
1361 struct perf_sample sample;
1362
1363 ++nr_events;
1364
1365 if (type != PERF_RECORD_SAMPLE)
1366 continue;
1367
1368 err = perf_evsel__parse_sample(evsel, event, &sample);
1369 if (err) {
1370 pr_err("Can't parse sample, err = %d\n", err);
1371 goto out_munmap;
1372 }
1373
1374 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
1375
1376 if (flags != tp_flags) {
1377 pr_debug("%s: Expected flags=%#x, got %#x\n",
1378 __func__, flags, tp_flags);
1379 goto out_munmap;
1380 }
1381
1382 goto out_ok;
1383 }
1384 }
1385
1386 if (nr_events == before)
1387 poll(evlist->pollfd, evlist->nr_fds, 10);
1388
1389 if (++nr_polls > 5) {
1390 pr_debug("%s: no events!\n", __func__);
1391 goto out_munmap;
1392 }
1393 }
1394out_ok:
1395 err = 0;
1396out_munmap:
1397 perf_evlist__munmap(evlist);
1398out_delete_evlist:
1399 perf_evlist__delete(evlist);
1400out:
1401 return err;
1402}
1403
1292static struct test { 1404static struct test {
1293 const char *desc; 1405 const char *desc;
1294 int (*func)(void); 1406 int (*func)(void);
@@ -1340,6 +1452,10 @@ static struct test {
1340 .func = perf_evsel__tp_sched_test, 1452 .func = perf_evsel__tp_sched_test,
1341 }, 1453 },
1342 { 1454 {
1455 .desc = "Generate and check syscalls:sys_enter_open event fields",
1456 .func = test__syscall_open_tp_fields,
1457 },
1458 {
1343 .func = NULL, 1459 .func = NULL,
1344 }, 1460 },
1345}; 1461};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5550754c05f2..e434a16bb5ac 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -823,7 +823,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
823 int ret; 823 int ret;
824 824
825 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { 825 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
826 ret = perf_evlist__parse_sample(top->evlist, event, &sample, false); 826 ret = perf_evlist__parse_sample(top->evlist, event, &sample);
827 if (ret) { 827 if (ret) {
828 pr_err("Can't parse sample, err = %d\n", ret); 828 pr_err("Can't parse sample, err = %d\n", ret);
829 continue; 829 continue;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
new file mode 100644
index 000000000000..8f113dab8bf1
--- /dev/null
+++ b/tools/perf/builtin-trace.c
@@ -0,0 +1,310 @@
1#include "builtin.h"
2#include "util/evlist.h"
3#include "util/parse-options.h"
4#include "util/thread_map.h"
5#include "event-parse.h"
6
7#include <libaudit.h>
8#include <stdlib.h>
9
10static struct syscall_fmt {
11 const char *name;
12 const char *alias;
13 bool errmsg;
14 bool timeout;
15} syscall_fmts[] = {
16 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
17 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
18 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
19 { .name = "futex", .errmsg = true, },
20 { .name = "poll", .errmsg = true, .timeout = true, },
21 { .name = "ppoll", .errmsg = true, .timeout = true, },
22 { .name = "read", .errmsg = true, },
23 { .name = "recvfrom", .errmsg = true, },
24 { .name = "select", .errmsg = true, .timeout = true, },
25 { .name = "stat", .errmsg = true, .alias = "newstat", },
26};
27
28static int syscall_fmt__cmp(const void *name, const void *fmtp)
29{
30 const struct syscall_fmt *fmt = fmtp;
31 return strcmp(name, fmt->name);
32}
33
34static struct syscall_fmt *syscall_fmt__find(const char *name)
35{
36 const int nmemb = ARRAY_SIZE(syscall_fmts);
37 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
38}
39
40struct syscall {
41 struct event_format *tp_format;
42 const char *name;
43 struct syscall_fmt *fmt;
44};
45
46struct trace {
47 int audit_machine;
48 struct {
49 int max;
50 struct syscall *table;
51 } syscalls;
52 struct perf_record_opts opts;
53};
54
55static int trace__read_syscall_info(struct trace *trace, int id)
56{
57 char tp_name[128];
58 struct syscall *sc;
59
60 if (id > trace->syscalls.max) {
61 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
62
63 if (nsyscalls == NULL)
64 return -1;
65
66 if (trace->syscalls.max != -1) {
67 memset(nsyscalls + trace->syscalls.max + 1, 0,
68 (id - trace->syscalls.max) * sizeof(*sc));
69 } else {
70 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
71 }
72
73 trace->syscalls.table = nsyscalls;
74 trace->syscalls.max = id;
75 }
76
77 sc = trace->syscalls.table + id;
78 sc->name = audit_syscall_to_name(id, trace->audit_machine);
79 if (sc->name == NULL)
80 return -1;
81
82 sc->fmt = syscall_fmt__find(sc->name);
83
84 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
85 sc->tp_format = event_format__new("syscalls", tp_name);
86
87 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
88 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
89 sc->tp_format = event_format__new("syscalls", tp_name);
90 }
91
92 return sc->tp_format != NULL ? 0 : -1;
93}
94
95static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FILE *fp)
96{
97 int i = 0;
98 size_t printed = 0;
99
100 if (sc->tp_format != NULL) {
101 struct format_field *field;
102
103 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
104 printed += fprintf(fp, "%s%s: %ld", printed ? ", " : "",
105 field->name, args[i++]);
106 }
107 } else {
108 while (i < 6) {
109 printed += fprintf(fp, "%sarg%d: %ld", printed ? ", " : "", i, args[i]);
110 ++i;
111 }
112 }
113
114 return printed;
115}
116
117static int trace__run(struct trace *trace)
118{
119 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
120 struct perf_evsel *evsel, *evsel_enter, *evsel_exit;
121 int err = -1, i, nr_events = 0, before;
122
123 if (evlist == NULL) {
124 printf("Not enough memory to run!\n");
125 goto out;
126 }
127
128 evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
129 if (evsel_enter == NULL) {
130 printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
131 goto out_delete_evlist;
132 }
133
134 perf_evlist__add(evlist, evsel_enter);
135
136 evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
137 if (evsel_exit == NULL) {
138 printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
139 goto out_delete_evlist;
140 }
141
142 perf_evlist__add(evlist, evsel_exit);
143
144 err = perf_evlist__create_maps(evlist, &trace->opts.target);
145 if (err < 0) {
146 printf("Problems parsing the target to trace, check your options!\n");
147 goto out_delete_evlist;
148 }
149
150 perf_evlist__config_attrs(evlist, &trace->opts);
151
152 err = perf_evlist__open(evlist);
153 if (err < 0) {
154 printf("Couldn't create the events: %s\n", strerror(errno));
155 goto out_delete_evlist;
156 }
157
158 err = perf_evlist__mmap(evlist, UINT_MAX, false);
159 if (err < 0) {
160 printf("Couldn't mmap the events: %s\n", strerror(errno));
161 goto out_delete_evlist;
162 }
163
164 perf_evlist__enable(evlist);
165again:
166 before = nr_events;
167
168 for (i = 0; i < evlist->nr_mmaps; i++) {
169 union perf_event *event;
170
171 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
172 const u32 type = event->header.type;
173 struct syscall *sc;
174 struct perf_sample sample;
175 int id;
176
177 ++nr_events;
178
179 switch (type) {
180 case PERF_RECORD_SAMPLE:
181 break;
182 case PERF_RECORD_LOST:
183 printf("LOST %" PRIu64 " events!\n", event->lost.lost);
184 continue;
185 default:
186 printf("Unexpected %s event, skipping...\n",
187 perf_event__name(type));
188 continue;
189 }
190
191 err = perf_evlist__parse_sample(evlist, event, &sample);
192 if (err) {
193 printf("Can't parse sample, err = %d, skipping...\n", err);
194 continue;
195 }
196
197 evsel = perf_evlist__id2evsel(evlist, sample.id);
198 if (evsel == NULL) {
199 printf("Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
200 continue;
201 }
202
203 id = perf_evsel__intval(evsel, &sample, "id");
204 if (id < 0) {
205 printf("Invalid syscall %d id, skipping...\n", id);
206 continue;
207 }
208
209 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
210 trace__read_syscall_info(trace, id))
211 continue;
212
213 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
214 continue;
215
216 sc = &trace->syscalls.table[id];
217
218 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
219 printf("%d ", sample.tid);
220
221 if (evsel == evsel_enter) {
222 void *args = perf_evsel__rawptr(evsel, &sample, "args");
223
224 printf("%s(", sc->name);
225 syscall__fprintf_args(sc, args, stdout);
226 } else if (evsel == evsel_exit) {
227 int ret = perf_evsel__intval(evsel, &sample, "ret");
228
229 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
230 char bf[256];
231 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
232 *e = audit_errno_to_name(-ret);
233
234 printf(") = -1 %s %s", e, emsg);
235 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
236 printf(") = 0 Timeout");
237 else
238 printf(") = %d", ret);
239
240 putchar('\n');
241 }
242 }
243 }
244
245 if (nr_events == before)
246 poll(evlist->pollfd, evlist->nr_fds, -1);
247
248 goto again;
249
250out_delete_evlist:
251 perf_evlist__delete(evlist);
252out:
253 return err;
254}
255
256int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
257{
258 const char * const trace_usage[] = {
259 "perf trace [<options>]",
260 NULL
261 };
262 struct trace trace = {
263 .audit_machine = audit_detect_machine(),
264 .syscalls = {
265 . max = -1,
266 },
267 .opts = {
268 .target = {
269 .uid = UINT_MAX,
270 .uses_mmap = true,
271 },
272 .user_freq = UINT_MAX,
273 .user_interval = ULLONG_MAX,
274 .no_delay = true,
275 .mmap_pages = 1024,
276 },
277 };
278 const struct option trace_options[] = {
279 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
280 "trace events on existing process id"),
281 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid",
282 "trace events on existing thread id"),
283 OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide,
284 "system-wide collection from all CPUs"),
285 OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu",
286 "list of cpus to monitor"),
287 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
288 "child tasks do not inherit counters"),
289 OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages,
290 "number of mmap data pages"),
291 OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user",
292 "user to profile"),
293 OPT_END()
294 };
295 int err;
296
297 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
298 if (argc)
299 usage_with_options(trace_usage, trace_options);
300
301 err = perf_target__parse_uid(&trace.opts.target);
302 if (err) {
303 char bf[BUFSIZ];
304 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
305 printf("%s", bf);
306 return err;
307 }
308
309 return trace__run(&trace);
310}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 3ea74ed1b26b..08143bd854c7 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -34,6 +34,7 @@ extern int cmd_kmem(int argc, const char **argv, const char *prefix);
34extern int cmd_lock(int argc, const char **argv, const char *prefix); 34extern int cmd_lock(int argc, const char **argv, const char *prefix);
35extern int cmd_kvm(int argc, const char **argv, const char *prefix); 35extern int cmd_kvm(int argc, const char **argv, const char *prefix);
36extern int cmd_test(int argc, const char **argv, const char *prefix); 36extern int cmd_test(int argc, const char **argv, const char *prefix);
37extern int cmd_trace(int argc, const char **argv, const char *prefix);
37extern int cmd_inject(int argc, const char **argv, const char *prefix); 38extern int cmd_inject(int argc, const char **argv, const char *prefix);
38 39
39extern int find_scripts(char **scripts_array, char **scripts_path_array); 40extern int find_scripts(char **scripts_array, char **scripts_path_array);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 0303ec692274..3e86bbd8c2d5 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -17,6 +17,7 @@ perf-report mainporcelain common
17perf-stat mainporcelain common 17perf-stat mainporcelain common
18perf-timechart mainporcelain common 18perf-timechart mainporcelain common
19perf-top mainporcelain common 19perf-top mainporcelain common
20perf-trace mainporcelain common
20perf-script mainporcelain common 21perf-script mainporcelain common
21perf-probe mainporcelain full 22perf-probe mainporcelain full
22perf-kmem mainporcelain common 23perf-kmem mainporcelain common
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 116690a669d2..4add41bb0c7e 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -193,3 +193,14 @@ int main(void)
193} 193}
194endef 194endef
195endif 195endif
196
197ifndef NO_LIBAUDIT
198define SOURCE_LIBAUDIT
199#include <libaudit.h>
200
201int main(void)
202{
203 return audit_open();
204}
205endef
206endif \ No newline at end of file
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index fb8578cfa03c..fc2f770e3027 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -55,6 +55,9 @@ static struct cmd_struct commands[] = {
55 { "lock", cmd_lock, 0 }, 55 { "lock", cmd_lock, 0 },
56 { "kvm", cmd_kvm, 0 }, 56 { "kvm", cmd_kvm, 0 },
57 { "test", cmd_test, 0 }, 57 { "test", cmd_test, 0 },
58#ifndef NO_LIBAUDIT_SUPPORT
59 { "trace", cmd_trace, 0 },
60#endif
58 { "inject", cmd_inject, 0 }, 61 { "inject", cmd_inject, 0 },
59}; 62};
60 63
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 17b5264f6436..2f68a3b8c285 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -2,6 +2,7 @@
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
5 6
6struct cpu_map { 7struct cpu_map {
7 int nr; 8 int nr;
@@ -14,4 +15,14 @@ void cpu_map__delete(struct cpu_map *map);
14struct cpu_map *cpu_map__read(FILE *file); 15struct cpu_map *cpu_map__read(FILE *file);
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 16size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16 17
18static inline int cpu_map__nr(const struct cpu_map *map)
19{
20 return map ? map->nr : 1;
21}
22
23static inline bool cpu_map__all(const struct cpu_map *map)
24{
25 return map ? map->map[0] == -1 : true;
26}
27
17#endif /* __PERF_CPUMAP_H */ 28#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index ee51e9b4dc09..3e5f5430a28a 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -804,6 +804,8 @@ int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
804 tmp = "union "; 804 tmp = "union ";
805 else if (tag == DW_TAG_structure_type) 805 else if (tag == DW_TAG_structure_type)
806 tmp = "struct "; 806 tmp = "struct ";
807 else if (tag == DW_TAG_enumeration_type)
808 tmp = "enum ";
807 /* Write a base name */ 809 /* Write a base name */
808 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type)); 810 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
809 return (ret >= len) ? -E2BIG : ret; 811 return (ret >= len) ? -E2BIG : ret;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 892353729c7a..ae89686102f4 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -304,7 +304,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
304 int cpu, thread; 304 int cpu, thread;
305 struct perf_evsel *pos; 305 struct perf_evsel *pos;
306 306
307 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 307 for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
308 list_for_each_entry(pos, &evlist->entries, node) { 308 list_for_each_entry(pos, &evlist->entries, node) {
309 for (thread = 0; thread < evlist->threads->nr; thread++) 309 for (thread = 0; thread < evlist->threads->nr; thread++)
310 ioctl(FD(pos, cpu, thread), 310 ioctl(FD(pos, cpu, thread),
@@ -315,7 +315,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
315 315
316static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 316static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
317{ 317{
318 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 318 int nfds = cpu_map__nr(evlist->cpus) * evlist->threads->nr * evlist->nr_entries;
319 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 319 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
320 return evlist->pollfd != NULL ? 0 : -ENOMEM; 320 return evlist->pollfd != NULL ? 0 : -ENOMEM;
321} 321}
@@ -475,8 +475,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
475 475
476static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 476static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
477{ 477{
478 evlist->nr_mmaps = evlist->cpus->nr; 478 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
479 if (evlist->cpus->map[0] == -1) 479 if (cpu_map__all(evlist->cpus))
480 evlist->nr_mmaps = evlist->threads->nr; 480 evlist->nr_mmaps = evlist->threads->nr;
481 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 481 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
482 return evlist->mmap != NULL ? 0 : -ENOMEM; 482 return evlist->mmap != NULL ? 0 : -ENOMEM;
@@ -622,11 +622,11 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
622 list_for_each_entry(evsel, &evlist->entries, node) { 622 list_for_each_entry(evsel, &evlist->entries, node) {
623 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 623 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
624 evsel->sample_id == NULL && 624 evsel->sample_id == NULL &&
625 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) 625 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
626 return -ENOMEM; 626 return -ENOMEM;
627 } 627 }
628 628
629 if (evlist->cpus->map[0] == -1) 629 if (cpu_map__all(cpus))
630 return perf_evlist__mmap_per_thread(evlist, prot, mask); 630 return perf_evlist__mmap_per_thread(evlist, prot, mask);
631 631
632 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 632 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
@@ -666,32 +666,39 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist)
666 evlist->threads = NULL; 666 evlist->threads = NULL;
667} 667}
668 668
669int perf_evlist__set_filters(struct perf_evlist *evlist) 669int perf_evlist__apply_filters(struct perf_evlist *evlist)
670{ 670{
671 const struct thread_map *threads = evlist->threads;
672 const struct cpu_map *cpus = evlist->cpus;
673 struct perf_evsel *evsel; 671 struct perf_evsel *evsel;
674 char *filter; 672 int err = 0;
675 int thread; 673 const int ncpus = cpu_map__nr(evlist->cpus),
676 int cpu; 674 nthreads = evlist->threads->nr;
677 int err;
678 int fd;
679 675
680 list_for_each_entry(evsel, &evlist->entries, node) { 676 list_for_each_entry(evsel, &evlist->entries, node) {
681 filter = evsel->filter; 677 if (evsel->filter == NULL)
682 if (!filter)
683 continue; 678 continue;
684 for (cpu = 0; cpu < cpus->nr; cpu++) { 679
685 for (thread = 0; thread < threads->nr; thread++) { 680 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
686 fd = FD(evsel, cpu, thread); 681 if (err)
687 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); 682 break;
688 if (err)
689 return err;
690 }
691 }
692 } 683 }
693 684
694 return 0; 685 return err;
686}
687
688int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
689{
690 struct perf_evsel *evsel;
691 int err = 0;
692 const int ncpus = cpu_map__nr(evlist->cpus),
693 nthreads = evlist->threads->nr;
694
695 list_for_each_entry(evsel, &evlist->entries, node) {
696 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
697 if (err)
698 break;
699 }
700
701 return err;
695} 702}
696 703
697bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 704bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
@@ -884,10 +891,10 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
884} 891}
885 892
886int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 893int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
887 struct perf_sample *sample, bool swapped) 894 struct perf_sample *sample)
888{ 895{
889 struct perf_evsel *evsel = perf_evlist__first(evlist); 896 struct perf_evsel *evsel = perf_evlist__first(evlist);
890 return perf_evsel__parse_sample(evsel, event, sample, swapped); 897 return perf_evsel__parse_sample(evsel, event, sample);
891} 898}
892 899
893size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) 900size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 3f2e1e4ccdd5..3f1fb66be022 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -72,6 +72,8 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
74 74
75int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
76
75struct perf_evsel * 77struct perf_evsel *
76perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); 78perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
77 79
@@ -115,7 +117,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
115int perf_evlist__create_maps(struct perf_evlist *evlist, 117int perf_evlist__create_maps(struct perf_evlist *evlist,
116 struct perf_target *target); 118 struct perf_target *target);
117void perf_evlist__delete_maps(struct perf_evlist *evlist); 119void perf_evlist__delete_maps(struct perf_evlist *evlist);
118int perf_evlist__set_filters(struct perf_evlist *evlist); 120int perf_evlist__apply_filters(struct perf_evlist *evlist);
119 121
120void __perf_evlist__set_leader(struct list_head *list); 122void __perf_evlist__set_leader(struct list_head *list);
121void perf_evlist__set_leader(struct perf_evlist *evlist); 123void perf_evlist__set_leader(struct perf_evlist *evlist);
@@ -125,7 +127,7 @@ bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
125u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist); 127u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
126 128
127int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 129int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
128 struct perf_sample *sample, bool swapped); 130 struct perf_sample *sample);
129 131
130bool perf_evlist__valid_sample_type(struct perf_evlist *evlist); 132bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
131bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist); 133bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 00936ad29ff2..ffdd94e9c9c3 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -70,7 +70,7 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
70 return evsel; 70 return evsel;
71} 71}
72 72
73static struct event_format *event_format__new(const char *sys, const char *name) 73struct event_format *event_format__new(const char *sys, const char *name)
74{ 74{
75 int fd, n; 75 int fd, n;
76 char *filename; 76 char *filename;
@@ -117,21 +117,28 @@ struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx)
117 117
118 if (evsel != NULL) { 118 if (evsel != NULL) {
119 struct perf_event_attr attr = { 119 struct perf_event_attr attr = {
120 .type = PERF_TYPE_TRACEPOINT, 120 .type = PERF_TYPE_TRACEPOINT,
121 .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
122 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
121 }; 123 };
122 124
125 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
126 goto out_free;
127
123 evsel->tp_format = event_format__new(sys, name); 128 evsel->tp_format = event_format__new(sys, name);
124 if (evsel->tp_format == NULL) 129 if (evsel->tp_format == NULL)
125 goto out_free; 130 goto out_free;
126 131
132 event_attr_init(&attr);
127 attr.config = evsel->tp_format->id; 133 attr.config = evsel->tp_format->id;
134 attr.sample_period = 1;
128 perf_evsel__init(evsel, &attr, idx); 135 perf_evsel__init(evsel, &attr, idx);
129 evsel->name = evsel->tp_format->name;
130 } 136 }
131 137
132 return evsel; 138 return evsel;
133 139
134out_free: 140out_free:
141 free(evsel->name);
135 free(evsel); 142 free(evsel);
136 return NULL; 143 return NULL;
137} 144}
@@ -501,6 +508,24 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
501 return evsel->fd != NULL ? 0 : -ENOMEM; 508 return evsel->fd != NULL ? 0 : -ENOMEM;
502} 509}
503 510
511int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
512 const char *filter)
513{
514 int cpu, thread;
515
516 for (cpu = 0; cpu < ncpus; cpu++) {
517 for (thread = 0; thread < nthreads; thread++) {
518 int fd = FD(evsel, cpu, thread),
519 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
520
521 if (err)
522 return err;
523 }
524 }
525
526 return 0;
527}
528
504int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 529int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
505{ 530{
506 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 531 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
@@ -562,10 +587,8 @@ void perf_evsel__delete(struct perf_evsel *evsel)
562 perf_evsel__exit(evsel); 587 perf_evsel__exit(evsel);
563 close_cgroup(evsel->cgrp); 588 close_cgroup(evsel->cgrp);
564 free(evsel->group_name); 589 free(evsel->group_name);
565 if (evsel->tp_format && evsel->name == evsel->tp_format->name) { 590 if (evsel->tp_format)
566 evsel->name = NULL;
567 pevent_free_format(evsel->tp_format); 591 pevent_free_format(evsel->tp_format);
568 }
569 free(evsel->name); 592 free(evsel->name);
570 free(evsel); 593 free(evsel);
571} 594}
@@ -763,11 +786,13 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel,
763 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads); 786 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
764} 787}
765 788
766static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 789static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
767 struct perf_sample *sample, 790 const union perf_event *event,
768 bool swapped) 791 struct perf_sample *sample)
769{ 792{
793 u64 type = evsel->attr.sample_type;
770 const u64 *array = event->sample.array; 794 const u64 *array = event->sample.array;
795 bool swapped = evsel->needs_swap;
771 union u64_swap u; 796 union u64_swap u;
772 797
773 array += ((event->header.size - 798 array += ((event->header.size -
@@ -828,10 +853,11 @@ static bool sample_overlap(const union perf_event *event,
828} 853}
829 854
830int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 855int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
831 struct perf_sample *data, bool swapped) 856 struct perf_sample *data)
832{ 857{
833 u64 type = evsel->attr.sample_type; 858 u64 type = evsel->attr.sample_type;
834 u64 regs_user = evsel->attr.sample_regs_user; 859 u64 regs_user = evsel->attr.sample_regs_user;
860 bool swapped = evsel->needs_swap;
835 const u64 *array; 861 const u64 *array;
836 862
837 /* 863 /*
@@ -848,7 +874,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
848 if (event->header.type != PERF_RECORD_SAMPLE) { 874 if (event->header.type != PERF_RECORD_SAMPLE) {
849 if (!evsel->attr.sample_id_all) 875 if (!evsel->attr.sample_id_all)
850 return 0; 876 return 0;
851 return perf_event__parse_id_sample(event, type, data, swapped); 877 return perf_evsel__parse_id_sample(evsel, event, data);
852 } 878 }
853 879
854 array = event->sample.array; 880 array = event->sample.array;
@@ -1078,7 +1104,7 @@ struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *nam
1078 return pevent_find_field(evsel->tp_format, name); 1104 return pevent_find_field(evsel->tp_format, name);
1079} 1105}
1080 1106
1081char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, 1107void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
1082 const char *name) 1108 const char *name)
1083{ 1109{
1084 struct format_field *field = perf_evsel__field(evsel, name); 1110 struct format_field *field = perf_evsel__field(evsel, name);
@@ -1101,13 +1127,43 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1101 const char *name) 1127 const char *name)
1102{ 1128{
1103 struct format_field *field = perf_evsel__field(evsel, name); 1129 struct format_field *field = perf_evsel__field(evsel, name);
1104 u64 val; 1130 void *ptr;
1131 u64 value;
1105 1132
1106 if (!field) 1133 if (!field)
1107 return 0; 1134 return 0;
1108 1135
1109 val = pevent_read_number(evsel->tp_format->pevent, 1136 ptr = sample->raw_data + field->offset;
1110 sample->raw_data + field->offset, field->size);
1111 return val;
1112 1137
1138 switch (field->size) {
1139 case 1:
1140 return *(u8 *)ptr;
1141 case 2:
1142 value = *(u16 *)ptr;
1143 break;
1144 case 4:
1145 value = *(u32 *)ptr;
1146 break;
1147 case 8:
1148 value = *(u64 *)ptr;
1149 break;
1150 default:
1151 return 0;
1152 }
1153
1154 if (!evsel->needs_swap)
1155 return value;
1156
1157 switch (field->size) {
1158 case 2:
1159 return bswap_16(value);
1160 case 4:
1161 return bswap_32(value);
1162 case 8:
1163 return bswap_64(value);
1164 default:
1165 return 0;
1166 }
1167
1168 return 0;
1113} 1169}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index bb445d1cbc7b..3ead0d59c03d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -69,6 +69,7 @@ struct perf_evsel {
69 struct cpu_map *cpus; 69 struct cpu_map *cpus;
70 unsigned int sample_size; 70 unsigned int sample_size;
71 bool supported; 71 bool supported;
72 bool needs_swap;
72 /* parse modifier helper */ 73 /* parse modifier helper */
73 int exclude_GH; 74 int exclude_GH;
74 struct perf_evsel *leader; 75 struct perf_evsel *leader;
@@ -82,6 +83,9 @@ struct perf_record_opts;
82 83
83struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 84struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
84struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); 85struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx);
86
87struct event_format *event_format__new(const char *sys, const char *name);
88
85void perf_evsel__init(struct perf_evsel *evsel, 89void perf_evsel__init(struct perf_evsel *evsel,
86 struct perf_event_attr *attr, int idx); 90 struct perf_event_attr *attr, int idx);
87void perf_evsel__exit(struct perf_evsel *evsel); 91void perf_evsel__exit(struct perf_evsel *evsel);
@@ -114,6 +118,9 @@ void perf_evsel__free_fd(struct perf_evsel *evsel);
114void perf_evsel__free_id(struct perf_evsel *evsel); 118void perf_evsel__free_id(struct perf_evsel *evsel);
115void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 119void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
116 120
121int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
122 const char *filter);
123
117int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 124int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
118 struct cpu_map *cpus); 125 struct cpu_map *cpus);
119int perf_evsel__open_per_thread(struct perf_evsel *evsel, 126int perf_evsel__open_per_thread(struct perf_evsel *evsel,
@@ -124,11 +131,18 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
124 131
125struct perf_sample; 132struct perf_sample;
126 133
127char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, 134void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
128 const char *name); 135 const char *name);
129u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, 136u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
130 const char *name); 137 const char *name);
131 138
139static inline char *perf_evsel__strval(struct perf_evsel *evsel,
140 struct perf_sample *sample,
141 const char *name)
142{
143 return perf_evsel__rawptr(evsel, sample, name);
144}
145
132struct format_field; 146struct format_field;
133 147
134struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); 148struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
@@ -205,7 +219,7 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
205void hists__init(struct hists *hists); 219void hists__init(struct hists *hists);
206 220
207int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 221int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
208 struct perf_sample *sample, bool swapped); 222 struct perf_sample *sample);
209 223
210static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) 224static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
211{ 225{
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6aae3290358e..7daad237dea5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1256,8 +1256,10 @@ read_event_desc(struct perf_header *ph, int fd)
1256 if (ret != (ssize_t)sizeof(nr)) 1256 if (ret != (ssize_t)sizeof(nr))
1257 goto error; 1257 goto error;
1258 1258
1259 if (ph->needs_swap) 1259 if (ph->needs_swap) {
1260 nr = bswap_32(nr); 1260 nr = bswap_32(nr);
1261 evsel->needs_swap = true;
1262 }
1261 1263
1262 evsel->name = do_read_string(fd, ph); 1264 evsel->name = do_read_string(fd, ph);
1263 1265
@@ -2626,6 +2628,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2626 2628
2627 if (evsel == NULL) 2629 if (evsel == NULL)
2628 goto out_delete_evlist; 2630 goto out_delete_evlist;
2631
2632 evsel->needs_swap = header->needs_swap;
2629 /* 2633 /*
2630 * Do it before so that if perf_evsel__alloc_id fails, this 2634 * Do it before so that if perf_evsel__alloc_id fails, this
2631 * entry gets purged too at perf_evlist__delete(). 2635 * entry gets purged too at perf_evlist__delete().
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6ec5398de89d..236bc9d98ff2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -410,8 +410,13 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
410 cmp = hist_entry__collapse(iter, he); 410 cmp = hist_entry__collapse(iter, he);
411 411
412 if (!cmp) { 412 if (!cmp) {
413 iter->period += he->period; 413 iter->period += he->period;
414 iter->nr_events += he->nr_events; 414 iter->period_sys += he->period_sys;
415 iter->period_us += he->period_us;
416 iter->period_guest_sys += he->period_guest_sys;
417 iter->period_guest_us += he->period_guest_us;
418 iter->nr_events += he->nr_events;
419
415 if (symbol_conf.use_callchain) { 420 if (symbol_conf.use_callchain) {
416 callchain_cursor_reset(&callchain_cursor); 421 callchain_cursor_reset(&callchain_cursor);
417 callchain_merge(&callchain_cursor, 422 callchain_merge(&callchain_cursor,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index bf5d033ee1b4..aed38e4b9dfa 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -356,42 +356,28 @@ int parse_events_add_cache(struct list_head **list, int *idx,
356 return add_event(list, idx, &attr, name); 356 return add_event(list, idx, &attr, name);
357} 357}
358 358
359static int add_tracepoint(struct list_head **list, int *idx, 359static int add_tracepoint(struct list_head **listp, int *idx,
360 char *sys_name, char *evt_name) 360 char *sys_name, char *evt_name)
361{ 361{
362 struct perf_event_attr attr; 362 struct perf_evsel *evsel;
363 char name[MAX_NAME_LEN]; 363 struct list_head *list = *listp;
364 char evt_path[MAXPATHLEN];
365 char id_buf[4];
366 u64 id;
367 int fd;
368
369 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
370 sys_name, evt_name);
371
372 fd = open(evt_path, O_RDONLY);
373 if (fd < 0)
374 return -1;
375 364
376 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 365 if (!list) {
377 close(fd); 366 list = malloc(sizeof(*list));
378 return -1; 367 if (!list)
368 return -ENOMEM;
369 INIT_LIST_HEAD(list);
379 } 370 }
380 371
381 close(fd); 372 evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++);
382 id = atoll(id_buf); 373 if (!evsel) {
383 374 free(list);
384 memset(&attr, 0, sizeof(attr)); 375 return -ENOMEM;
385 attr.config = id; 376 }
386 attr.type = PERF_TYPE_TRACEPOINT;
387 attr.sample_type |= PERF_SAMPLE_RAW;
388 attr.sample_type |= PERF_SAMPLE_TIME;
389 attr.sample_type |= PERF_SAMPLE_CPU;
390 attr.sample_type |= PERF_SAMPLE_PERIOD;
391 attr.sample_period = 1;
392 377
393 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); 378 list_add_tail(&evsel->node, list);
394 return add_event(list, idx, &attr, name); 379 *listp = list;
380 return 0;
395} 381}
396 382
397static int add_tracepoint_multi(struct list_head **list, int *idx, 383static int add_tracepoint_multi(struct list_head **list, int *idx,
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index ca85444bcfbf..9181bf212fb9 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -805,7 +805,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
805 if (pyevent == NULL) 805 if (pyevent == NULL)
806 return PyErr_NoMemory(); 806 return PyErr_NoMemory();
807 807
808 err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false); 808 err = perf_evlist__parse_sample(evlist, event, &pevent->sample);
809 if (err) 809 if (err)
810 return PyErr_Format(PyExc_OSError, 810 return PyErr_Format(PyExc_OSError,
811 "perf: can't parse sample, err=%d", err); 811 "perf: can't parse sample, err=%d", err);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 3049b0ae7003..8cdd23239c90 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -722,8 +722,7 @@ static int flush_sample_queue(struct perf_session *s,
722 if (iter->timestamp > limit) 722 if (iter->timestamp > limit)
723 break; 723 break;
724 724
725 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample, 725 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
726 s->header.needs_swap);
727 if (ret) 726 if (ret)
728 pr_err("Can't parse sample, err = %d\n", ret); 727 pr_err("Can't parse sample, err = %d\n", ret);
729 else { 728 else {
@@ -1174,8 +1173,7 @@ static int perf_session__process_event(struct perf_session *session,
1174 /* 1173 /*
1175 * For all kernel events we get the sample data 1174 * For all kernel events we get the sample data
1176 */ 1175 */
1177 ret = perf_evlist__parse_sample(session->evlist, event, &sample, 1176 ret = perf_evlist__parse_sample(session->evlist, event, &sample);
1178 session->header.needs_swap);
1179 if (ret) 1177 if (ret)
1180 return ret; 1178 return ret;
1181 1179