hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/tools/perf/util/session.c
....@@ -1,30 +1,99 @@
11 // SPDX-License-Identifier: GPL-2.0
22 #include <errno.h>
33 #include <inttypes.h>
4
+#include <linux/err.h>
45 #include <linux/kernel.h>
5
-#include <traceevent/event-parse.h>
6
+#include <linux/zalloc.h>
67 #include <api/fs/fs.h>
78
89 #include <byteswap.h>
910 #include <unistd.h>
1011 #include <sys/types.h>
1112 #include <sys/mman.h>
13
+#include <perf/cpumap.h>
1214
15
+#include "map_symbol.h"
16
+#include "branch.h"
17
+#include "debug.h"
1318 #include "evlist.h"
1419 #include "evsel.h"
1520 #include "memswap.h"
21
+#include "map.h"
22
+#include "symbol.h"
1623 #include "session.h"
1724 #include "tool.h"
18
-#include "sort.h"
19
-#include "util.h"
20
-#include "cpumap.h"
2125 #include "perf_regs.h"
2226 #include "asm/bug.h"
2327 #include "auxtrace.h"
2428 #include "thread.h"
2529 #include "thread-stack.h"
30
+#include "sample-raw.h"
2631 #include "stat.h"
32
+#include "ui/progress.h"
33
+#include "../perf.h"
2734 #include "arch/common.h"
35
+#include <internal/lib.h>
36
+
37
+#ifdef HAVE_ZSTD_SUPPORT
38
+static int perf_session__process_compressed_event(struct perf_session *session,
39
+ union perf_event *event, u64 file_offset)
40
+{
41
+ void *src;
42
+ size_t decomp_size, src_size;
43
+ u64 decomp_last_rem = 0;
44
+ size_t mmap_len, decomp_len = session->header.env.comp_mmap_len;
45
+ struct decomp *decomp, *decomp_last = session->decomp_last;
46
+
47
+ if (decomp_last) {
48
+ decomp_last_rem = decomp_last->size - decomp_last->head;
49
+ decomp_len += decomp_last_rem;
50
+ }
51
+
52
+ mmap_len = sizeof(struct decomp) + decomp_len;
53
+ decomp = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE,
54
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
55
+ if (decomp == MAP_FAILED) {
56
+ pr_err("Couldn't allocate memory for decompression\n");
57
+ return -1;
58
+ }
59
+
60
+ decomp->file_pos = file_offset;
61
+ decomp->mmap_len = mmap_len;
62
+ decomp->head = 0;
63
+
64
+ if (decomp_last_rem) {
65
+ memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem);
66
+ decomp->size = decomp_last_rem;
67
+ }
68
+
69
+ src = (void *)event + sizeof(struct perf_record_compressed);
70
+ src_size = event->pack.header.size - sizeof(struct perf_record_compressed);
71
+
72
+ decomp_size = zstd_decompress_stream(&(session->zstd_data), src, src_size,
73
+ &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem);
74
+ if (!decomp_size) {
75
+ munmap(decomp, mmap_len);
76
+ pr_err("Couldn't decompress data\n");
77
+ return -1;
78
+ }
79
+
80
+ decomp->size += decomp_size;
81
+
82
+ if (session->decomp == NULL) {
83
+ session->decomp = decomp;
84
+ session->decomp_last = decomp;
85
+ } else {
86
+ session->decomp_last->next = decomp;
87
+ session->decomp_last = decomp;
88
+ }
89
+
90
+ pr_debug("decomp (B): %zd to %zd\n", src_size, decomp_size);
91
+
92
+ return 0;
93
+}
94
+#else /* !HAVE_ZSTD_SUPPORT */
95
+#define perf_session__process_compressed_event perf_session__process_compressed_event_stub
96
+#endif
2897
2998 static int perf_session__deliver_event(struct perf_session *session,
3099 union perf_event *event,
....@@ -46,12 +115,12 @@
46115 if (perf_header__has_feat(&session->header, HEADER_STAT))
47116 return 0;
48117
49
- if (!perf_evlist__valid_sample_type(session->evlist)) {
118
+ if (!evlist__valid_sample_type(session->evlist)) {
50119 pr_err("non matching sample_type\n");
51120 return -1;
52121 }
53122
54
- if (!perf_evlist__valid_sample_id_all(session->evlist)) {
123
+ if (!evlist__valid_sample_id_all(session->evlist)) {
55124 pr_err("non matching sample_id_all\n");
56125 return -1;
57126 }
....@@ -87,10 +156,10 @@
87156
88157 static bool perf_session__has_comm_exec(struct perf_session *session)
89158 {
90
- struct perf_evsel *evsel;
159
+ struct evsel *evsel;
91160
92161 evlist__for_each_entry(session->evlist, evsel) {
93
- if (evsel->attr.comm_exec)
162
+ if (evsel->core.attr.comm_exec)
94163 return true;
95164 }
96165
....@@ -117,6 +186,7 @@
117186 struct perf_session *perf_session__new(struct perf_data *data,
118187 bool repipe, struct perf_tool *tool)
119188 {
189
+ int ret = -ENOMEM;
120190 struct perf_session *session = zalloc(sizeof(*session));
121191
122192 if (!session)
....@@ -126,17 +196,21 @@
126196 session->tool = tool;
127197 INIT_LIST_HEAD(&session->auxtrace_index);
128198 machines__init(&session->machines);
129
- ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
199
+ ordered_events__init(&session->ordered_events,
200
+ ordered_events__deliver_event, NULL);
130201
202
+ perf_env__init(&session->header.env);
131203 if (data) {
132
- if (perf_data__open(data))
204
+ ret = perf_data__open(data);
205
+ if (ret < 0)
133206 goto out_delete;
134207
135208 session->data = data;
136209
137210 if (perf_data__is_read(data)) {
138
- if (perf_session__open(session) < 0)
139
- goto out_close;
211
+ ret = perf_session__open(session);
212
+ if (ret < 0)
213
+ goto out_delete;
140214
141215 /*
142216 * set session attributes that are present in perf.data
....@@ -146,6 +220,19 @@
146220 perf_session__set_id_hdr_size(session);
147221 perf_session__set_comm_exec(session);
148222 }
223
+
224
+ perf_evlist__init_trace_event_sample_raw(session->evlist);
225
+
226
+ /* Open the directory data. */
227
+ if (data->is_dir) {
228
+ ret = perf_data__open_dir(data);
229
+ if (ret)
230
+ goto out_delete;
231
+ }
232
+
233
+ if (!symbol_conf.kallsyms_name &&
234
+ !symbol_conf.vmlinux_name)
235
+ symbol_conf.kallsyms_name = perf_data__kallsyms_name(data);
149236 }
150237 } else {
151238 session->machines.host.env = &perf_env;
....@@ -165,27 +252,40 @@
165252
166253 /*
167254 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is
168
- * processed, so perf_evlist__sample_id_all is not meaningful here.
255
+ * processed, so evlist__sample_id_all is not meaningful here.
169256 */
170257 if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps &&
171
- tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
258
+ tool->ordered_events && !evlist__sample_id_all(session->evlist)) {
172259 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
173260 tool->ordered_events = false;
174261 }
175262
176263 return session;
177264
178
- out_close:
179
- perf_data__close(data);
180265 out_delete:
181266 perf_session__delete(session);
182267 out:
183
- return NULL;
268
+ return ERR_PTR(ret);
184269 }
185270
186271 static void perf_session__delete_threads(struct perf_session *session)
187272 {
188273 machine__delete_threads(&session->machines.host);
274
+}
275
+
276
+static void perf_session__release_decomp_events(struct perf_session *session)
277
+{
278
+ struct decomp *next, *decomp;
279
+ size_t mmap_len;
280
+ next = session->decomp;
281
+ do {
282
+ decomp = next;
283
+ if (decomp == NULL)
284
+ break;
285
+ next = decomp->next;
286
+ mmap_len = decomp->mmap_len;
287
+ munmap(decomp, mmap_len);
288
+ } while (1);
189289 }
190290
191291 void perf_session__delete(struct perf_session *session)
....@@ -196,6 +296,7 @@
196296 auxtrace_index__free(&session->auxtrace_index);
197297 perf_session__destroy_kernel_maps(session);
198298 perf_session__delete_threads(session);
299
+ perf_session__release_decomp_events(session);
199300 perf_env__exit(&session->header.env);
200301 machines__exit(&session->machines);
201302 if (session->data)
....@@ -203,12 +304,10 @@
203304 free(session);
204305 }
205306
206
-static int process_event_synth_tracing_data_stub(struct perf_tool *tool
307
+static int process_event_synth_tracing_data_stub(struct perf_session *session
207308 __maybe_unused,
208309 union perf_event *event
209
- __maybe_unused,
210
- struct perf_session *session
211
- __maybe_unused)
310
+ __maybe_unused)
212311 {
213312 dump_printf(": unhandled!\n");
214313 return 0;
....@@ -216,7 +315,7 @@
216315
217316 static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
218317 union perf_event *event __maybe_unused,
219
- struct perf_evlist **pevlist
318
+ struct evlist **pevlist
220319 __maybe_unused)
221320 {
222321 dump_printf(": unhandled!\n");
....@@ -225,7 +324,7 @@
225324
226325 static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused,
227326 union perf_event *event __maybe_unused,
228
- struct perf_evlist **pevlist
327
+ struct evlist **pevlist
229328 __maybe_unused)
230329 {
231330 if (dump_trace)
....@@ -238,7 +337,7 @@
238337 static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
239338 union perf_event *event __maybe_unused,
240339 struct perf_sample *sample __maybe_unused,
241
- struct perf_evsel *evsel __maybe_unused,
340
+ struct evsel *evsel __maybe_unused,
242341 struct machine *machine __maybe_unused)
243342 {
244343 dump_printf(": unhandled!\n");
....@@ -281,10 +380,8 @@
281380 return 0;
282381 }
283382
284
-static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
285
- union perf_event *event,
286
- struct perf_session *session
287
- __maybe_unused)
383
+static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused,
384
+ union perf_event *event)
288385 {
289386 dump_printf(": unhandled!\n");
290387 if (perf_data__is_pipe(session->data))
....@@ -292,9 +389,8 @@
292389 return event->auxtrace.size;
293390 }
294391
295
-static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
296
- union perf_event *event __maybe_unused,
297
- struct perf_session *session __maybe_unused)
392
+static int process_event_op2_stub(struct perf_session *session __maybe_unused,
393
+ union perf_event *event __maybe_unused)
298394 {
299395 dump_printf(": unhandled!\n");
300396 return 0;
....@@ -302,9 +398,8 @@
302398
303399
304400 static
305
-int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
306
- union perf_event *event __maybe_unused,
307
- struct perf_session *session __maybe_unused)
401
+int process_event_thread_map_stub(struct perf_session *session __maybe_unused,
402
+ union perf_event *event __maybe_unused)
308403 {
309404 if (dump_trace)
310405 perf_event__fprintf_thread_map(event, stdout);
....@@ -314,9 +409,8 @@
314409 }
315410
316411 static
317
-int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
318
- union perf_event *event __maybe_unused,
319
- struct perf_session *session __maybe_unused)
412
+int process_event_cpu_map_stub(struct perf_session *session __maybe_unused,
413
+ union perf_event *event __maybe_unused)
320414 {
321415 if (dump_trace)
322416 perf_event__fprintf_cpu_map(event, stdout);
....@@ -326,9 +420,8 @@
326420 }
327421
328422 static
329
-int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
330
- union perf_event *event __maybe_unused,
331
- struct perf_session *session __maybe_unused)
423
+int process_event_stat_config_stub(struct perf_session *session __maybe_unused,
424
+ union perf_event *event __maybe_unused)
332425 {
333426 if (dump_trace)
334427 perf_event__fprintf_stat_config(event, stdout);
....@@ -337,10 +430,8 @@
337430 return 0;
338431 }
339432
340
-static int process_stat_stub(struct perf_tool *tool __maybe_unused,
341
- union perf_event *event __maybe_unused,
342
- struct perf_session *perf_session
343
- __maybe_unused)
433
+static int process_stat_stub(struct perf_session *perf_session __maybe_unused,
434
+ union perf_event *event)
344435 {
345436 if (dump_trace)
346437 perf_event__fprintf_stat(event, stdout);
....@@ -349,16 +440,22 @@
349440 return 0;
350441 }
351442
352
-static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
353
- union perf_event *event __maybe_unused,
354
- struct perf_session *perf_session
355
- __maybe_unused)
443
+static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused,
444
+ union perf_event *event)
356445 {
357446 if (dump_trace)
358447 perf_event__fprintf_stat_round(event, stdout);
359448
360449 dump_printf(": unhandled!\n");
361450 return 0;
451
+}
452
+
453
+static int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused,
454
+ union perf_event *event __maybe_unused,
455
+ u64 file_offset __maybe_unused)
456
+{
457
+ dump_printf(": unhandled!\n");
458
+ return 0;
362459 }
363460
364461 void perf_tool__fill_defaults(struct perf_tool *tool)
....@@ -373,6 +470,8 @@
373470 tool->comm = process_event_stub;
374471 if (tool->namespaces == NULL)
375472 tool->namespaces = process_event_stub;
473
+ if (tool->cgroup == NULL)
474
+ tool->cgroup = process_event_stub;
376475 if (tool->fork == NULL)
377476 tool->fork = process_event_stub;
378477 if (tool->exit == NULL)
....@@ -387,6 +486,12 @@
387486 tool->itrace_start = perf_event__process_itrace_start;
388487 if (tool->context_switch == NULL)
389488 tool->context_switch = perf_event__process_switch;
489
+ if (tool->ksymbol == NULL)
490
+ tool->ksymbol = perf_event__process_ksymbol;
491
+ if (tool->bpf == NULL)
492
+ tool->bpf = perf_event__process_bpf;
493
+ if (tool->text_poke == NULL)
494
+ tool->text_poke = perf_event__process_text_poke;
390495 if (tool->read == NULL)
391496 tool->read = process_event_sample_stub;
392497 if (tool->throttle == NULL)
....@@ -429,6 +534,8 @@
429534 tool->time_conv = process_event_op2_stub;
430535 if (tool->feature == NULL)
431536 tool->feature = process_event_op2_stub;
537
+ if (tool->compressed == NULL)
538
+ tool->compressed = perf_session__process_compressed_event;
432539 }
433540
434541 static void swap_sample_id_all(union perf_event *event, void *data)
....@@ -555,6 +662,24 @@
555662 swap_sample_id_all(event, &event->context_switch + 1);
556663 }
557664
665
+static void perf_event__text_poke_swap(union perf_event *event, bool sample_id_all)
666
+{
667
+ event->text_poke.addr = bswap_64(event->text_poke.addr);
668
+ event->text_poke.old_len = bswap_16(event->text_poke.old_len);
669
+ event->text_poke.new_len = bswap_16(event->text_poke.new_len);
670
+
671
+ if (sample_id_all) {
672
+ size_t len = sizeof(event->text_poke.old_len) +
673
+ sizeof(event->text_poke.new_len) +
674
+ event->text_poke.old_len +
675
+ event->text_poke.new_len;
676
+ void *data = &event->text_poke.old_len;
677
+
678
+ data += PERF_ALIGN(len, sizeof(u64));
679
+ swap_sample_id_all(event, data);
680
+ }
681
+}
682
+
558683 static void perf_event__throttle_swap(union perf_event *event,
559684 bool sample_id_all)
560685 {
....@@ -564,6 +689,38 @@
564689
565690 if (sample_id_all)
566691 swap_sample_id_all(event, &event->throttle + 1);
692
+}
693
+
694
+static void perf_event__namespaces_swap(union perf_event *event,
695
+ bool sample_id_all)
696
+{
697
+ u64 i;
698
+
699
+ event->namespaces.pid = bswap_32(event->namespaces.pid);
700
+ event->namespaces.tid = bswap_32(event->namespaces.tid);
701
+ event->namespaces.nr_namespaces = bswap_64(event->namespaces.nr_namespaces);
702
+
703
+ for (i = 0; i < event->namespaces.nr_namespaces; i++) {
704
+ struct perf_ns_link_info *ns = &event->namespaces.link_info[i];
705
+
706
+ ns->dev = bswap_64(ns->dev);
707
+ ns->ino = bswap_64(ns->ino);
708
+ }
709
+
710
+ if (sample_id_all)
711
+ swap_sample_id_all(event, &event->namespaces.link_info[i]);
712
+}
713
+
714
+static void perf_event__cgroup_swap(union perf_event *event, bool sample_id_all)
715
+{
716
+ event->cgroup.id = bswap_64(event->cgroup.id);
717
+
718
+ if (sample_id_all) {
719
+ void *data = &event->cgroup.path;
720
+
721
+ data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
722
+ swap_sample_id_all(event, data);
723
+ }
567724 }
568725
569726 static u8 revbyte(u8 b)
....@@ -629,6 +786,7 @@
629786 bswap_field_32(sample_stack_user);
630787 bswap_field_32(aux_watermark);
631788 bswap_field_16(sample_max_stack);
789
+ bswap_field_32(aux_sample_size);
632790
633791 /*
634792 * After read_format are bitfields. Check read_format because
....@@ -706,7 +864,10 @@
706864 event->auxtrace_error.cpu = bswap_32(event->auxtrace_error.cpu);
707865 event->auxtrace_error.pid = bswap_32(event->auxtrace_error.pid);
708866 event->auxtrace_error.tid = bswap_32(event->auxtrace_error.tid);
867
+ event->auxtrace_error.fmt = bswap_32(event->auxtrace_error.fmt);
709868 event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip);
869
+ if (event->auxtrace_error.fmt)
870
+ event->auxtrace_error.time = bswap_64(event->auxtrace_error.time);
710871 }
711872
712873 static void perf_event__thread_map_swap(union perf_event *event,
....@@ -723,9 +884,9 @@
723884 static void perf_event__cpu_map_swap(union perf_event *event,
724885 bool sample_id_all __maybe_unused)
725886 {
726
- struct cpu_map_data *data = &event->cpu_map.data;
887
+ struct perf_record_cpu_map_data *data = &event->cpu_map.data;
727888 struct cpu_map_entries *cpus;
728
- struct cpu_map_mask *mask;
889
+ struct perf_record_record_cpu_map *mask;
729890 unsigned i;
730891
731892 data->type = bswap_64(data->type);
....@@ -740,7 +901,7 @@
740901 cpus->cpu[i] = bswap_16(cpus->cpu[i]);
741902 break;
742903 case PERF_CPU_MAP__MASK:
743
- mask = (struct cpu_map_mask *) data->data;
904
+ mask = (struct perf_record_record_cpu_map *)data->data;
744905
745906 mask->nr = bswap_16(mask->nr);
746907 mask->long_size = bswap_16(mask->long_size);
....@@ -784,6 +945,19 @@
784945 event->stat_round.time = bswap_64(event->stat_round.time);
785946 }
786947
948
+static void perf_event__time_conv_swap(union perf_event *event,
949
+ bool sample_id_all __maybe_unused)
950
+{
951
+ event->time_conv.time_shift = bswap_64(event->time_conv.time_shift);
952
+ event->time_conv.time_mult = bswap_64(event->time_conv.time_mult);
953
+ event->time_conv.time_zero = bswap_64(event->time_conv.time_zero);
954
+
955
+ if (event_contains(event->time_conv, time_cycles)) {
956
+ event->time_conv.time_cycles = bswap_64(event->time_conv.time_cycles);
957
+ event->time_conv.time_mask = bswap_64(event->time_conv.time_mask);
958
+ }
959
+}
960
+
787961 typedef void (*perf_event__swap_op)(union perf_event *event,
788962 bool sample_id_all);
789963
....@@ -803,6 +977,9 @@
803977 [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap,
804978 [PERF_RECORD_SWITCH] = perf_event__switch_swap,
805979 [PERF_RECORD_SWITCH_CPU_WIDE] = perf_event__switch_swap,
980
+ [PERF_RECORD_NAMESPACES] = perf_event__namespaces_swap,
981
+ [PERF_RECORD_CGROUP] = perf_event__cgroup_swap,
982
+ [PERF_RECORD_TEXT_POKE] = perf_event__text_poke_swap,
806983 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
807984 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
808985 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
....@@ -817,7 +994,7 @@
817994 [PERF_RECORD_STAT] = perf_event__stat_swap,
818995 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,
819996 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,
820
- [PERF_RECORD_TIME_CONV] = perf_event__all64_swap,
997
+ [PERF_RECORD_TIME_CONV] = perf_event__time_conv_swap,
821998 [PERF_RECORD_HEADER_MAX] = NULL,
822999 };
8231000
....@@ -879,6 +1056,7 @@
8791056 {
8801057 struct ip_callchain *callchain = sample->callchain;
8811058 struct branch_stack *lbr_stack = sample->branch_stack;
1059
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
8821060 u64 kernel_callchain_nr = callchain->nr;
8831061 unsigned int i;
8841062
....@@ -915,20 +1093,20 @@
9151093 i, callchain->ips[i]);
9161094
9171095 printf("..... %2d: %016" PRIx64 "\n",
918
- (int)(kernel_callchain_nr), lbr_stack->entries[0].to);
1096
+ (int)(kernel_callchain_nr), entries[0].to);
9191097 for (i = 0; i < lbr_stack->nr; i++)
9201098 printf("..... %2d: %016" PRIx64 "\n",
921
- (int)(i + kernel_callchain_nr + 1), lbr_stack->entries[i].from);
1099
+ (int)(i + kernel_callchain_nr + 1), entries[i].from);
9221100 }
9231101 }
9241102
925
-static void callchain__printf(struct perf_evsel *evsel,
1103
+static void callchain__printf(struct evsel *evsel,
9261104 struct perf_sample *sample)
9271105 {
9281106 unsigned int i;
9291107 struct ip_callchain *callchain = sample->callchain;
9301108
931
- if (perf_evsel__has_branch_callstack(evsel))
1109
+ if (evsel__has_branch_callstack(evsel))
9321110 callchain__lbr_callstack_printf(sample);
9331111
9341112 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
....@@ -938,23 +1116,31 @@
9381116 i, callchain->ips[i]);
9391117 }
9401118
941
-static void branch_stack__printf(struct perf_sample *sample)
1119
+static void branch_stack__printf(struct perf_sample *sample, bool callstack)
9421120 {
1121
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
9431122 uint64_t i;
9441123
945
- printf("... branch stack: nr:%" PRIu64 "\n", sample->branch_stack->nr);
1124
+ printf("%s: nr:%" PRIu64 "\n",
1125
+ !callstack ? "... branch stack" : "... branch callstack",
1126
+ sample->branch_stack->nr);
9461127
9471128 for (i = 0; i < sample->branch_stack->nr; i++) {
948
- struct branch_entry *e = &sample->branch_stack->entries[i];
1129
+ struct branch_entry *e = &entries[i];
9491130
950
- printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n",
951
- i, e->from, e->to,
952
- (unsigned short)e->flags.cycles,
953
- e->flags.mispred ? "M" : " ",
954
- e->flags.predicted ? "P" : " ",
955
- e->flags.abort ? "A" : " ",
956
- e->flags.in_tx ? "T" : " ",
957
- (unsigned)e->flags.reserved);
1131
+ if (!callstack) {
1132
+ printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n",
1133
+ i, e->from, e->to,
1134
+ (unsigned short)e->flags.cycles,
1135
+ e->flags.mispred ? "M" : " ",
1136
+ e->flags.predicted ? "P" : " ",
1137
+ e->flags.abort ? "A" : " ",
1138
+ e->flags.in_tx ? "T" : " ",
1139
+ (unsigned)e->flags.reserved);
1140
+ } else {
1141
+ printf("..... %2"PRIu64": %016" PRIx64 "\n",
1142
+ i, i > 0 ? e->from : e->to);
1143
+ }
9581144 }
9591145 }
9601146
....@@ -965,7 +1151,7 @@
9651151 for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) {
9661152 u64 val = regs[i++];
9671153
968
- printf(".... %-5s 0x%" PRIx64 "\n",
1154
+ printf(".... %-5s 0x%016" PRIx64 "\n",
9691155 perf_reg_name(rid), val);
9701156 }
9711157 }
....@@ -1018,14 +1204,14 @@
10181204 dump->size, dump->offset);
10191205 }
10201206
1021
-static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
1207
+static void perf_evlist__print_tstamp(struct evlist *evlist,
10221208 union perf_event *event,
10231209 struct perf_sample *sample)
10241210 {
1025
- u64 sample_type = __perf_evlist__combined_sample_type(evlist);
1211
+ u64 sample_type = __evlist__combined_sample_type(evlist);
10261212
10271213 if (event->header.type != PERF_RECORD_SAMPLE &&
1028
- !perf_evlist__sample_id_all(evlist)) {
1214
+ !evlist__sample_id_all(evlist)) {
10291215 fputs("-1 -1 ", stdout);
10301216 return;
10311217 }
....@@ -1067,7 +1253,7 @@
10671253 sample->read.one.id, sample->read.one.value);
10681254 }
10691255
1070
-static void dump_event(struct perf_evlist *evlist, union perf_event *event,
1256
+static void dump_event(struct evlist *evlist, union perf_event *event,
10711257 u64 file_offset, struct perf_sample *sample)
10721258 {
10731259 if (!dump_trace)
....@@ -1077,6 +1263,8 @@
10771263 file_offset, event->header.size, event->header.type);
10781264
10791265 trace_event(event);
1266
+ if (event->header.type == PERF_RECORD_SAMPLE && evlist->trace_event_sample_raw)
1267
+ evlist->trace_event_sample_raw(evlist, event, sample);
10801268
10811269 if (sample)
10821270 perf_evlist__print_tstamp(evlist, event, sample);
....@@ -1085,7 +1273,7 @@
10851273 event->header.size, perf_event__name(event->header.type));
10861274 }
10871275
1088
-static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1276
+static void dump_sample(struct evsel *evsel, union perf_event *event,
10891277 struct perf_sample *sample)
10901278 {
10911279 u64 sample_type;
....@@ -1097,13 +1285,13 @@
10971285 event->header.misc, sample->pid, sample->tid, sample->ip,
10981286 sample->period, sample->addr);
10991287
1100
- sample_type = evsel->attr.sample_type;
1288
+ sample_type = evsel->core.attr.sample_type;
11011289
11021290 if (evsel__has_callchain(evsel))
11031291 callchain__printf(evsel, sample);
11041292
1105
- if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel))
1106
- branch_stack__printf(sample);
1293
+ if (evsel__has_br_stack(evsel))
1294
+ branch_stack__printf(sample, evsel__has_branch_callstack(evsel));
11071295
11081296 if (sample_type & PERF_SAMPLE_REGS_USER)
11091297 regs_user__printf(sample);
....@@ -1127,34 +1315,33 @@
11271315 printf("... transaction: %" PRIx64 "\n", sample->transaction);
11281316
11291317 if (sample_type & PERF_SAMPLE_READ)
1130
- sample_read__printf(sample, evsel->attr.read_format);
1318
+ sample_read__printf(sample, evsel->core.attr.read_format);
11311319 }
11321320
1133
-static void dump_read(struct perf_evsel *evsel, union perf_event *event)
1321
+static void dump_read(struct evsel *evsel, union perf_event *event)
11341322 {
1135
- struct read_event *read_event = &event->read;
1323
+ struct perf_record_read *read_event = &event->read;
11361324 u64 read_format;
11371325
11381326 if (!dump_trace)
11391327 return;
11401328
1141
- printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
1142
- evsel ? perf_evsel__name(evsel) : "FAIL",
1143
- event->read.value);
1329
+ printf(": %d %d %s %" PRI_lu64 "\n", event->read.pid, event->read.tid,
1330
+ evsel__name(evsel), event->read.value);
11441331
11451332 if (!evsel)
11461333 return;
11471334
1148
- read_format = evsel->attr.read_format;
1335
+ read_format = evsel->core.attr.read_format;
11491336
11501337 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1151
- printf("... time enabled : %" PRIu64 "\n", read_event->time_enabled);
1338
+ printf("... time enabled : %" PRI_lu64 "\n", read_event->time_enabled);
11521339
11531340 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1154
- printf("... time running : %" PRIu64 "\n", read_event->time_running);
1341
+ printf("... time running : %" PRI_lu64 "\n", read_event->time_running);
11551342
11561343 if (read_format & PERF_FORMAT_ID)
1157
- printf("... id : %" PRIu64 "\n", read_event->id);
1344
+ printf("... id : %" PRI_lu64 "\n", read_event->id);
11581345 }
11591346
11601347 static struct machine *machines__find_for_cpumode(struct machines *machines,
....@@ -1183,7 +1370,7 @@
11831370 return &machines->host;
11841371 }
11851372
1186
-static int deliver_sample_value(struct perf_evlist *evlist,
1373
+static int deliver_sample_value(struct evlist *evlist,
11871374 struct perf_tool *tool,
11881375 union perf_event *event,
11891376 struct perf_sample *sample,
....@@ -1191,6 +1378,7 @@
11911378 struct machine *machine)
11921379 {
11931380 struct perf_sample_id *sid = perf_evlist__id2sid(evlist, v->id);
1381
+ struct evsel *evsel;
11941382
11951383 if (sid) {
11961384 sample->id = v->id;
....@@ -1203,10 +1391,18 @@
12031391 return 0;
12041392 }
12051393
1206
- return tool->sample(tool, event, sample, sid->evsel, machine);
1394
+ /*
1395
+ * There's no reason to deliver sample
1396
+ * for zero period, bail out.
1397
+ */
1398
+ if (!sample->period)
1399
+ return 0;
1400
+
1401
+ evsel = container_of(sid->evsel, struct evsel, core);
1402
+ return tool->sample(tool, event, sample, evsel, machine);
12071403 }
12081404
1209
-static int deliver_sample_group(struct perf_evlist *evlist,
1405
+static int deliver_sample_group(struct evlist *evlist,
12101406 struct perf_tool *tool,
12111407 union perf_event *event,
12121408 struct perf_sample *sample,
....@@ -1227,16 +1423,16 @@
12271423 }
12281424
12291425 static int
1230
- perf_evlist__deliver_sample(struct perf_evlist *evlist,
1426
+ perf_evlist__deliver_sample(struct evlist *evlist,
12311427 struct perf_tool *tool,
12321428 union perf_event *event,
12331429 struct perf_sample *sample,
1234
- struct perf_evsel *evsel,
1430
+ struct evsel *evsel,
12351431 struct machine *machine)
12361432 {
12371433 /* We know evsel != NULL. */
1238
- u64 sample_type = evsel->attr.sample_type;
1239
- u64 read_format = evsel->attr.read_format;
1434
+ u64 sample_type = evsel->core.attr.sample_type;
1435
+ u64 read_format = evsel->core.attr.read_format;
12401436
12411437 /* Standard sample delivery. */
12421438 if (!(sample_type & PERF_SAMPLE_READ))
....@@ -1252,12 +1448,12 @@
12521448 }
12531449
12541450 static int machines__deliver_event(struct machines *machines,
1255
- struct perf_evlist *evlist,
1451
+ struct evlist *evlist,
12561452 union perf_event *event,
12571453 struct perf_sample *sample,
12581454 struct perf_tool *tool, u64 file_offset)
12591455 {
1260
- struct perf_evsel *evsel;
1456
+ struct evsel *evsel;
12611457 struct machine *machine;
12621458
12631459 dump_event(evlist, event, file_offset, sample);
....@@ -1288,6 +1484,8 @@
12881484 return tool->comm(tool, event, sample, machine);
12891485 case PERF_RECORD_NAMESPACES:
12901486 return tool->namespaces(tool, event, sample, machine);
1487
+ case PERF_RECORD_CGROUP:
1488
+ return tool->cgroup(tool, event, sample, machine);
12911489 case PERF_RECORD_FORK:
12921490 return tool->fork(tool, event, sample, machine);
12931491 case PERF_RECORD_EXIT:
....@@ -1320,6 +1518,12 @@
13201518 case PERF_RECORD_SWITCH:
13211519 case PERF_RECORD_SWITCH_CPU_WIDE:
13221520 return tool->context_switch(tool, event, sample, machine);
1521
+ case PERF_RECORD_KSYMBOL:
1522
+ return tool->ksymbol(tool, event, sample, machine);
1523
+ case PERF_RECORD_BPF_EVENT:
1524
+ return tool->bpf(tool, event, sample, machine);
1525
+ case PERF_RECORD_TEXT_POKE:
1526
+ return tool->text_poke(tool, event, sample, machine);
13231527 default:
13241528 ++evlist->stats.nr_unknown_events;
13251529 return -1;
....@@ -1346,8 +1550,13 @@
13461550 if (ret > 0)
13471551 return 0;
13481552
1349
- return machines__deliver_event(&session->machines, session->evlist,
1350
- event, &sample, tool, file_offset);
1553
+ ret = machines__deliver_event(&session->machines, session->evlist,
1554
+ event, &sample, tool, file_offset);
1555
+
1556
+ if (dump_trace && sample.aux_sample.size)
1557
+ auxtrace__dump_auxtrace_sample(session, &sample);
1558
+
1559
+ return ret;
13511560 }
13521561
13531562 static s64 perf_session__process_user_event(struct perf_session *session,
....@@ -1360,7 +1569,9 @@
13601569 int fd = perf_data__fd(session->data);
13611570 int err;
13621571
1363
- dump_event(session->evlist, event, file_offset, &sample);
1572
+ if (event->header.type != PERF_RECORD_COMPRESSED ||
1573
+ tool->compressed == perf_session__process_compressed_event_stub)
1574
+ dump_event(session->evlist, event, file_offset, &sample);
13641575
13651576 /* These events are processed right away */
13661577 switch (event->header.type) {
....@@ -1380,39 +1591,49 @@
13801591 */
13811592 return 0;
13821593 case PERF_RECORD_HEADER_TRACING_DATA:
1383
- /* setup for reading amidst mmap */
1384
- lseek(fd, file_offset, SEEK_SET);
1385
- return tool->tracing_data(tool, event, session);
1594
+ /*
1595
+ * Setup for reading amidst mmap, but only when we
1596
+ * are in 'file' mode. The 'pipe' fd is in proper
1597
+ * place already.
1598
+ */
1599
+ if (!perf_data__is_pipe(session->data))
1600
+ lseek(fd, file_offset, SEEK_SET);
1601
+ return tool->tracing_data(session, event);
13861602 case PERF_RECORD_HEADER_BUILD_ID:
1387
- return tool->build_id(tool, event, session);
1603
+ return tool->build_id(session, event);
13881604 case PERF_RECORD_FINISHED_ROUND:
13891605 return tool->finished_round(tool, event, oe);
13901606 case PERF_RECORD_ID_INDEX:
1391
- return tool->id_index(tool, event, session);
1607
+ return tool->id_index(session, event);
13921608 case PERF_RECORD_AUXTRACE_INFO:
1393
- return tool->auxtrace_info(tool, event, session);
1609
+ return tool->auxtrace_info(session, event);
13941610 case PERF_RECORD_AUXTRACE:
13951611 /* setup for reading amidst mmap */
13961612 lseek(fd, file_offset + event->header.size, SEEK_SET);
1397
- return tool->auxtrace(tool, event, session);
1613
+ return tool->auxtrace(session, event);
13981614 case PERF_RECORD_AUXTRACE_ERROR:
13991615 perf_session__auxtrace_error_inc(session, event);
1400
- return tool->auxtrace_error(tool, event, session);
1616
+ return tool->auxtrace_error(session, event);
14011617 case PERF_RECORD_THREAD_MAP:
1402
- return tool->thread_map(tool, event, session);
1618
+ return tool->thread_map(session, event);
14031619 case PERF_RECORD_CPU_MAP:
1404
- return tool->cpu_map(tool, event, session);
1620
+ return tool->cpu_map(session, event);
14051621 case PERF_RECORD_STAT_CONFIG:
1406
- return tool->stat_config(tool, event, session);
1622
+ return tool->stat_config(session, event);
14071623 case PERF_RECORD_STAT:
1408
- return tool->stat(tool, event, session);
1624
+ return tool->stat(session, event);
14091625 case PERF_RECORD_STAT_ROUND:
1410
- return tool->stat_round(tool, event, session);
1626
+ return tool->stat_round(session, event);
14111627 case PERF_RECORD_TIME_CONV:
14121628 session->time_conv = event->time_conv;
1413
- return tool->time_conv(tool, event, session);
1629
+ return tool->time_conv(session, event);
14141630 case PERF_RECORD_HEADER_FEATURE:
1415
- return tool->feature(tool, event, session);
1631
+ return tool->feature(session, event);
1632
+ case PERF_RECORD_COMPRESSED:
1633
+ err = tool->compressed(session, event, file_offset);
1634
+ if (err)
1635
+ dump_event(session->evlist, event, file_offset, &sample);
1636
+ return err;
14161637 default:
14171638 return -EINVAL;
14181639 }
....@@ -1422,7 +1643,7 @@
14221643 union perf_event *event,
14231644 struct perf_sample *sample)
14241645 {
1425
- struct perf_evlist *evlist = session->evlist;
1646
+ struct evlist *evlist = session->evlist;
14261647 struct perf_tool *tool = session->tool;
14271648
14281649 events_stats__inc(&evlist->stats, event->header.type);
....@@ -1485,7 +1706,7 @@
14851706 return -1;
14861707
14871708 if (session->header.needs_swap)
1488
- event_swap(event, perf_evlist__sample_id_all(session->evlist));
1709
+ event_swap(event, evlist__sample_id_all(session->evlist));
14891710
14901711 out_parse_sample:
14911712
....@@ -1498,15 +1719,43 @@
14981719 return 0;
14991720 }
15001721
1722
+int perf_session__peek_events(struct perf_session *session, u64 offset,
1723
+ u64 size, peek_events_cb_t cb, void *data)
1724
+{
1725
+ u64 max_offset = offset + size;
1726
+ char buf[PERF_SAMPLE_MAX_SIZE];
1727
+ union perf_event *event;
1728
+ int err;
1729
+
1730
+ do {
1731
+ err = perf_session__peek_event(session, offset, buf,
1732
+ PERF_SAMPLE_MAX_SIZE, &event,
1733
+ NULL);
1734
+ if (err)
1735
+ return err;
1736
+
1737
+ err = cb(session, event, offset, data);
1738
+ if (err)
1739
+ return err;
1740
+
1741
+ offset += event->header.size;
1742
+ if (event->header.type == PERF_RECORD_AUXTRACE)
1743
+ offset += event->auxtrace.size;
1744
+
1745
+ } while (offset < max_offset);
1746
+
1747
+ return err;
1748
+}
1749
+
15011750 static s64 perf_session__process_event(struct perf_session *session,
15021751 union perf_event *event, u64 file_offset)
15031752 {
1504
- struct perf_evlist *evlist = session->evlist;
1753
+ struct evlist *evlist = session->evlist;
15051754 struct perf_tool *tool = session->tool;
15061755 int ret;
15071756
15081757 if (session->header.needs_swap)
1509
- event_swap(event, perf_evlist__sample_id_all(evlist));
1758
+ event_swap(event, evlist__sample_id_all(evlist));
15101759
15111760 if (event->header.type >= PERF_RECORD_HEADER_MAX)
15121761 return -EINVAL;
....@@ -1543,6 +1792,13 @@
15431792 return machine__findnew_thread(&session->machines.host, -1, pid);
15441793 }
15451794
1795
+/*
1796
+ * Threads are identified by pid and tid, and the idle task has pid == tid == 0.
1797
+ * So here a single thread is created for that, but actually there is a separate
1798
+ * idle task per cpu, so there should be one 'struct thread' per cpu, but there
1799
+ * is only 1. That causes problems for some tools, requiring workarounds. For
1800
+ * example get_idle_thread() in builtin-sched.c, or thread_stack__per_cpu().
1801
+ */
15461802 int perf_session__register_idle_thread(struct perf_session *session)
15471803 {
15481804 struct thread *thread;
....@@ -1568,11 +1824,11 @@
15681824 perf_session__warn_order(const struct perf_session *session)
15691825 {
15701826 const struct ordered_events *oe = &session->ordered_events;
1571
- struct perf_evsel *evsel;
1827
+ struct evsel *evsel;
15721828 bool should_warn = true;
15731829
15741830 evlist__for_each_entry(session->evlist, evsel) {
1575
- if (evsel->attr.write_backward)
1831
+ if (evsel->core.attr.write_backward)
15761832 should_warn = false;
15771833 }
15781834
....@@ -1689,6 +1945,8 @@
16891945
16901946 volatile int session_done;
16911947
1948
+static int __perf_session__process_decomp_events(struct perf_session *session);
1949
+
16921950 static int __perf_session__process_pipe_events(struct perf_session *session)
16931951 {
16941952 struct ordered_events *oe = &session->ordered_events;
....@@ -1769,6 +2027,10 @@
17692027 if (skip > 0)
17702028 head += skip;
17712029
2030
+ err = __perf_session__process_decomp_events(session);
2031
+ if (err)
2032
+ goto out_err;
2033
+
17722034 if (!session_done())
17732035 goto more;
17742036 done:
....@@ -1790,10 +2052,11 @@
17902052 }
17912053
17922054 static union perf_event *
1793
-fetch_mmaped_event(struct perf_session *session,
1794
- u64 head, size_t mmap_size, char *buf)
2055
+prefetch_event(char *buf, u64 head, size_t mmap_size,
2056
+ bool needs_swap, union perf_event *error)
17952057 {
17962058 union perf_event *event;
2059
+ u16 event_size;
17972060
17982061 /*
17992062 * Ensure we have enough space remaining to read
....@@ -1803,18 +2066,74 @@
18032066 return NULL;
18042067
18052068 event = (union perf_event *)(buf + head);
1806
-
1807
- if (session->header.needs_swap)
2069
+ if (needs_swap)
18082070 perf_event_header__bswap(&event->header);
18092071
1810
- if (head + event->header.size > mmap_size) {
1811
- /* We're not fetching the event so swap back again */
1812
- if (session->header.needs_swap)
1813
- perf_event_header__bswap(&event->header);
2072
+ event_size = event->header.size;
2073
+ if (head + event_size <= mmap_size)
2074
+ return event;
2075
+
2076
+ /* We're not fetching the event so swap back again */
2077
+ if (needs_swap)
2078
+ perf_event_header__bswap(&event->header);
2079
+
2080
+ /* Check if the event fits into the next mmapped buf. */
2081
+ if (event_size <= mmap_size - head % page_size) {
2082
+ /* Remap buf and fetch again. */
18142083 return NULL;
18152084 }
18162085
1817
- return event;
2086
+ /* Invalid input. Event size should never exceed mmap_size. */
2087
+ pr_debug("%s: head=%#" PRIx64 " event->header.size=%#x, mmap_size=%#zx:"
2088
+ " fuzzed or compressed perf.data?\n", __func__, head, event_size, mmap_size);
2089
+
2090
+ return error;
2091
+}
2092
+
2093
+static union perf_event *
2094
+fetch_mmaped_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)
2095
+{
2096
+ return prefetch_event(buf, head, mmap_size, needs_swap, ERR_PTR(-EINVAL));
2097
+}
2098
+
2099
+static union perf_event *
2100
+fetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)
2101
+{
2102
+ return prefetch_event(buf, head, mmap_size, needs_swap, NULL);
2103
+}
2104
+
2105
+static int __perf_session__process_decomp_events(struct perf_session *session)
2106
+{
2107
+ s64 skip;
2108
+ u64 size, file_pos = 0;
2109
+ struct decomp *decomp = session->decomp_last;
2110
+
2111
+ if (!decomp)
2112
+ return 0;
2113
+
2114
+ while (decomp->head < decomp->size && !session_done()) {
2115
+ union perf_event *event = fetch_decomp_event(decomp->head, decomp->size, decomp->data,
2116
+ session->header.needs_swap);
2117
+
2118
+ if (!event)
2119
+ break;
2120
+
2121
+ size = event->header.size;
2122
+
2123
+ if (size < sizeof(struct perf_event_header) ||
2124
+ (skip = perf_session__process_event(session, event, file_pos)) < 0) {
2125
+ pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
2126
+ decomp->file_pos + decomp->head, event->header.size, event->header.type);
2127
+ return -EINVAL;
2128
+ }
2129
+
2130
+ if (skip)
2131
+ size += skip;
2132
+
2133
+ decomp->head += size;
2134
+ }
2135
+
2136
+ return 0;
18182137 }
18192138
18202139 /*
....@@ -1829,38 +2148,42 @@
18292148 #define NUM_MMAPS 128
18302149 #endif
18312150
1832
-static int __perf_session__process_events(struct perf_session *session,
1833
- u64 data_offset, u64 data_size,
1834
- u64 file_size)
2151
+struct reader;
2152
+
2153
+typedef s64 (*reader_cb_t)(struct perf_session *session,
2154
+ union perf_event *event,
2155
+ u64 file_offset);
2156
+
2157
+struct reader {
2158
+ int fd;
2159
+ u64 data_size;
2160
+ u64 data_offset;
2161
+ reader_cb_t process;
2162
+};
2163
+
2164
+static int
2165
+reader__process_events(struct reader *rd, struct perf_session *session,
2166
+ struct ui_progress *prog)
18352167 {
1836
- struct ordered_events *oe = &session->ordered_events;
1837
- struct perf_tool *tool = session->tool;
1838
- int fd = perf_data__fd(session->data);
2168
+ u64 data_size = rd->data_size;
18392169 u64 head, page_offset, file_offset, file_pos, size;
1840
- int err, mmap_prot, mmap_flags, map_idx = 0;
2170
+ int err = 0, mmap_prot, mmap_flags, map_idx = 0;
18412171 size_t mmap_size;
18422172 char *buf, *mmaps[NUM_MMAPS];
18432173 union perf_event *event;
1844
- struct ui_progress prog;
18452174 s64 skip;
18462175
1847
- perf_tool__fill_defaults(tool);
1848
-
1849
- page_offset = page_size * (data_offset / page_size);
2176
+ page_offset = page_size * (rd->data_offset / page_size);
18502177 file_offset = page_offset;
1851
- head = data_offset - page_offset;
2178
+ head = rd->data_offset - page_offset;
18522179
1853
- if (data_size == 0)
1854
- goto out;
2180
+ ui_progress__init_size(prog, data_size, "Processing events...");
18552181
1856
- if (data_offset + data_size < file_size)
1857
- file_size = data_offset + data_size;
1858
-
1859
- ui_progress__init_size(&prog, file_size, "Processing events...");
2182
+ data_size += rd->data_offset;
18602183
18612184 mmap_size = MMAP_SIZE;
1862
- if (mmap_size > file_size) {
1863
- mmap_size = file_size;
2185
+ if (mmap_size > data_size) {
2186
+ mmap_size = data_size;
18642187 session->one_mmap = true;
18652188 }
18662189
....@@ -1874,12 +2197,12 @@
18742197 mmap_flags = MAP_PRIVATE;
18752198 }
18762199 remap:
1877
- buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd,
2200
+ buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, rd->fd,
18782201 file_offset);
18792202 if (buf == MAP_FAILED) {
18802203 pr_err("failed to mmap file\n");
18812204 err = -errno;
1882
- goto out_err;
2205
+ goto out;
18832206 }
18842207 mmaps[map_idx] = buf;
18852208 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
....@@ -1890,7 +2213,10 @@
18902213 }
18912214
18922215 more:
1893
- event = fetch_mmaped_event(session, head, mmap_size, buf);
2216
+ event = fetch_mmaped_event(head, mmap_size, buf, session->header.needs_swap);
2217
+ if (IS_ERR(event))
2218
+ return PTR_ERR(event);
2219
+
18942220 if (!event) {
18952221 if (mmaps[map_idx]) {
18962222 munmap(mmaps[map_idx], mmap_size);
....@@ -1905,13 +2231,15 @@
19052231
19062232 size = event->header.size;
19072233
2234
+ skip = -EINVAL;
2235
+
19082236 if (size < sizeof(struct perf_event_header) ||
1909
- (skip = perf_session__process_event(session, event, file_pos)) < 0) {
1910
- pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
2237
+ (skip = rd->process(session, event, file_pos)) < 0) {
2238
+ pr_err("%#" PRIx64 " [%#x]: failed to process type: %d [%s]\n",
19112239 file_offset + head, event->header.size,
1912
- event->header.type);
1913
- err = -EINVAL;
1914
- goto out_err;
2240
+ event->header.type, strerror(-skip));
2241
+ err = skip;
2242
+ goto out;
19152243 }
19162244
19172245 if (skip)
....@@ -1920,15 +2248,52 @@
19202248 head += size;
19212249 file_pos += size;
19222250
1923
- ui_progress__update(&prog, size);
2251
+ err = __perf_session__process_decomp_events(session);
2252
+ if (err)
2253
+ goto out;
2254
+
2255
+ ui_progress__update(prog, size);
19242256
19252257 if (session_done())
19262258 goto out;
19272259
1928
- if (file_pos < file_size)
2260
+ if (file_pos < data_size)
19292261 goto more;
19302262
19312263 out:
2264
+ return err;
2265
+}
2266
+
2267
+static s64 process_simple(struct perf_session *session,
2268
+ union perf_event *event,
2269
+ u64 file_offset)
2270
+{
2271
+ return perf_session__process_event(session, event, file_offset);
2272
+}
2273
+
2274
+static int __perf_session__process_events(struct perf_session *session)
2275
+{
2276
+ struct reader rd = {
2277
+ .fd = perf_data__fd(session->data),
2278
+ .data_size = session->header.data_size,
2279
+ .data_offset = session->header.data_offset,
2280
+ .process = process_simple,
2281
+ };
2282
+ struct ordered_events *oe = &session->ordered_events;
2283
+ struct perf_tool *tool = session->tool;
2284
+ struct ui_progress prog;
2285
+ int err;
2286
+
2287
+ perf_tool__fill_defaults(tool);
2288
+
2289
+ if (rd.data_size == 0)
2290
+ return -1;
2291
+
2292
+ ui_progress__init_size(&prog, rd.data_size, "Processing events...");
2293
+
2294
+ err = reader__process_events(&rd, session, &prog);
2295
+ if (err)
2296
+ goto out_err;
19322297 /* do the final flush for ordered samples */
19332298 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
19342299 if (err)
....@@ -1953,28 +2318,21 @@
19532318
19542319 int perf_session__process_events(struct perf_session *session)
19552320 {
1956
- u64 size = perf_data__size(session->data);
1957
- int err;
1958
-
19592321 if (perf_session__register_idle_thread(session) < 0)
19602322 return -ENOMEM;
19612323
1962
- if (!perf_data__is_pipe(session->data))
1963
- err = __perf_session__process_events(session,
1964
- session->header.data_offset,
1965
- session->header.data_size, size);
1966
- else
1967
- err = __perf_session__process_pipe_events(session);
2324
+ if (perf_data__is_pipe(session->data))
2325
+ return __perf_session__process_pipe_events(session);
19682326
1969
- return err;
2327
+ return __perf_session__process_events(session);
19702328 }
19712329
19722330 bool perf_session__has_traces(struct perf_session *session, const char *msg)
19732331 {
1974
- struct perf_evsel *evsel;
2332
+ struct evsel *evsel;
19752333
19762334 evlist__for_each_entry(session->evlist, evsel) {
1977
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
2335
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT)
19782336 return true;
19792337 }
19802338
....@@ -2045,13 +2403,13 @@
20452403 return machine__fprintf(&session->machines.host, fp);
20462404 }
20472405
2048
-struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
2406
+struct evsel *perf_session__find_first_evtype(struct perf_session *session,
20492407 unsigned int type)
20502408 {
2051
- struct perf_evsel *pos;
2409
+ struct evsel *pos;
20522410
20532411 evlist__for_each_entry(session->evlist, pos) {
2054
- if (pos->attr.type == type)
2412
+ if (pos->core.attr.type == type)
20552413 return pos;
20562414 }
20572415 return NULL;
....@@ -2061,23 +2419,24 @@
20612419 const char *cpu_list, unsigned long *cpu_bitmap)
20622420 {
20632421 int i, err = -1;
2064
- struct cpu_map *map;
2422
+ struct perf_cpu_map *map;
2423
+ int nr_cpus = min(session->header.env.nr_cpus_avail, MAX_NR_CPUS);
20652424
20662425 for (i = 0; i < PERF_TYPE_MAX; ++i) {
2067
- struct perf_evsel *evsel;
2426
+ struct evsel *evsel;
20682427
20692428 evsel = perf_session__find_first_evtype(session, i);
20702429 if (!evsel)
20712430 continue;
20722431
2073
- if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
2432
+ if (!(evsel->core.attr.sample_type & PERF_SAMPLE_CPU)) {
20742433 pr_err("File does not contain CPU events. "
20752434 "Remove -C option to proceed.\n");
20762435 return -1;
20772436 }
20782437 }
20792438
2080
- map = cpu_map__new(cpu_list);
2439
+ map = perf_cpu_map__new(cpu_list);
20812440 if (map == NULL) {
20822441 pr_err("Invalid cpu_list\n");
20832442 return -1;
....@@ -2086,7 +2445,7 @@
20862445 for (i = 0; i < map->nr; i++) {
20872446 int cpu = map->map[i];
20882447
2089
- if (cpu >= MAX_NR_CPUS) {
2448
+ if (cpu >= nr_cpus) {
20902449 pr_err("Requested CPU %d too large. "
20912450 "Consider raising MAX_NR_CPUS\n", cpu);
20922451 goto out_delete_map;
....@@ -2098,7 +2457,7 @@
20982457 err = 0;
20992458
21002459 out_delete_map:
2101
- cpu_map__put(map);
2460
+ perf_cpu_map__put(map);
21022461 return err;
21032462 }
21042463
....@@ -2113,44 +2472,14 @@
21132472 fprintf(fp, "# ========\n#\n");
21142473 }
21152474
2116
-
2117
-int __perf_session__set_tracepoints_handlers(struct perf_session *session,
2118
- const struct perf_evsel_str_handler *assocs,
2119
- size_t nr_assocs)
2475
+int perf_event__process_id_index(struct perf_session *session,
2476
+ union perf_event *event)
21202477 {
2121
- struct perf_evsel *evsel;
2122
- size_t i;
2123
- int err;
2124
-
2125
- for (i = 0; i < nr_assocs; i++) {
2126
- /*
2127
- * Adding a handler for an event not in the session,
2128
- * just ignore it.
2129
- */
2130
- evsel = perf_evlist__find_tracepoint_by_name(session->evlist, assocs[i].name);
2131
- if (evsel == NULL)
2132
- continue;
2133
-
2134
- err = -EEXIST;
2135
- if (evsel->handler != NULL)
2136
- goto out;
2137
- evsel->handler = assocs[i].handler;
2138
- }
2139
-
2140
- err = 0;
2141
-out:
2142
- return err;
2143
-}
2144
-
2145
-int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
2146
- union perf_event *event,
2147
- struct perf_session *session)
2148
-{
2149
- struct perf_evlist *evlist = session->evlist;
2150
- struct id_index_event *ie = &event->id_index;
2478
+ struct evlist *evlist = session->evlist;
2479
+ struct perf_record_id_index *ie = &event->id_index;
21512480 size_t i, nr, max_nr;
21522481
2153
- max_nr = (ie->header.size - sizeof(struct id_index_event)) /
2482
+ max_nr = (ie->header.size - sizeof(struct perf_record_id_index)) /
21542483 sizeof(struct id_index_entry);
21552484 nr = ie->nr;
21562485 if (nr > max_nr)
....@@ -2164,10 +2493,10 @@
21642493 struct perf_sample_id *sid;
21652494
21662495 if (dump_trace) {
2167
- fprintf(stdout, " ... id: %"PRIu64, e->id);
2168
- fprintf(stdout, " idx: %"PRIu64, e->idx);
2169
- fprintf(stdout, " cpu: %"PRId64, e->cpu);
2170
- fprintf(stdout, " tid: %"PRId64"\n", e->tid);
2496
+ fprintf(stdout, " ... id: %"PRI_lu64, e->id);
2497
+ fprintf(stdout, " idx: %"PRI_lu64, e->idx);
2498
+ fprintf(stdout, " cpu: %"PRI_ld64, e->cpu);
2499
+ fprintf(stdout, " tid: %"PRI_ld64"\n", e->tid);
21712500 }
21722501
21732502 sid = perf_evlist__id2sid(evlist, e->id);
....@@ -2178,74 +2507,4 @@
21782507 sid->tid = e->tid;
21792508 }
21802509 return 0;
2181
-}
2182
-
2183
-int perf_event__synthesize_id_index(struct perf_tool *tool,
2184
- perf_event__handler_t process,
2185
- struct perf_evlist *evlist,
2186
- struct machine *machine)
2187
-{
2188
- union perf_event *ev;
2189
- struct perf_evsel *evsel;
2190
- size_t nr = 0, i = 0, sz, max_nr, n;
2191
- int err;
2192
-
2193
- pr_debug2("Synthesizing id index\n");
2194
-
2195
- max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
2196
- sizeof(struct id_index_entry);
2197
-
2198
- evlist__for_each_entry(evlist, evsel)
2199
- nr += evsel->ids;
2200
-
2201
- n = nr > max_nr ? max_nr : nr;
2202
- sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
2203
- ev = zalloc(sz);
2204
- if (!ev)
2205
- return -ENOMEM;
2206
-
2207
- ev->id_index.header.type = PERF_RECORD_ID_INDEX;
2208
- ev->id_index.header.size = sz;
2209
- ev->id_index.nr = n;
2210
-
2211
- evlist__for_each_entry(evlist, evsel) {
2212
- u32 j;
2213
-
2214
- for (j = 0; j < evsel->ids; j++) {
2215
- struct id_index_entry *e;
2216
- struct perf_sample_id *sid;
2217
-
2218
- if (i >= n) {
2219
- err = process(tool, ev, NULL, machine);
2220
- if (err)
2221
- goto out_err;
2222
- nr -= n;
2223
- i = 0;
2224
- }
2225
-
2226
- e = &ev->id_index.entries[i++];
2227
-
2228
- e->id = evsel->id[j];
2229
-
2230
- sid = perf_evlist__id2sid(evlist, e->id);
2231
- if (!sid) {
2232
- free(ev);
2233
- return -ENOENT;
2234
- }
2235
-
2236
- e->idx = sid->idx;
2237
- e->cpu = sid->cpu;
2238
- e->tid = sid->tid;
2239
- }
2240
- }
2241
-
2242
- sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
2243
- ev->id_index.header.size = sz;
2244
- ev->id_index.nr = nr;
2245
-
2246
- err = process(tool, ev, NULL, machine);
2247
-out_err:
2248
- free(ev);
2249
-
2250
- return err;
22512510 }