1#include <linux/kernel.h>
2#include <traceevent/event-parse.h>
3
4#include <byteswap.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/mman.h>
8
9#include "evlist.h"
10#include "evsel.h"
11#include "session.h"
12#include "tool.h"
13#include "sort.h"
14#include "util.h"
15#include "cpumap.h"
16#include "perf_regs.h"
17#include "asm/bug.h"
18#include "auxtrace.h"
19#include "thread-stack.h"
20#include "stat.h"
21
22static int perf_session__deliver_event(struct perf_session *session,
23 union perf_event *event,
24 struct perf_sample *sample,
25 struct perf_tool *tool,
26 u64 file_offset);
27
28static int perf_session__open(struct perf_session *session)
29{
30 struct perf_data_file *file = session->file;
31
32 if (perf_session__read_header(session) < 0) {
33 pr_err("incompatible file format (rerun with -v to learn more)\n");
34 return -1;
35 }
36
37 if (perf_data_file__is_pipe(file))
38 return 0;
39
40 if (perf_header__has_feat(&session->header, HEADER_STAT))
41 return 0;
42
43 if (!perf_evlist__valid_sample_type(session->evlist)) {
44 pr_err("non matching sample_type\n");
45 return -1;
46 }
47
48 if (!perf_evlist__valid_sample_id_all(session->evlist)) {
49 pr_err("non matching sample_id_all\n");
50 return -1;
51 }
52
53 if (!perf_evlist__valid_read_format(session->evlist)) {
54 pr_err("non matching read_format\n");
55 return -1;
56 }
57
58 return 0;
59}
60
61void perf_session__set_id_hdr_size(struct perf_session *session)
62{
63 u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist);
64
65 machines__set_id_hdr_size(&session->machines, id_hdr_size);
66}
67
68int perf_session__create_kernel_maps(struct perf_session *session)
69{
70 int ret = machine__create_kernel_maps(&session->machines.host);
71
72 if (ret >= 0)
73 ret = machines__create_guest_kernel_maps(&session->machines);
74 return ret;
75}
76
77static void perf_session__destroy_kernel_maps(struct perf_session *session)
78{
79 machines__destroy_kernel_maps(&session->machines);
80}
81
82static bool perf_session__has_comm_exec(struct perf_session *session)
83{
84 struct perf_evsel *evsel;
85
86 evlist__for_each(session->evlist, evsel) {
87 if (evsel->attr.comm_exec)
88 return true;
89 }
90
91 return false;
92}
93
94static void perf_session__set_comm_exec(struct perf_session *session)
95{
96 bool comm_exec = perf_session__has_comm_exec(session);
97
98 machines__set_comm_exec(&session->machines, comm_exec);
99}
100
101static int ordered_events__deliver_event(struct ordered_events *oe,
102 struct ordered_event *event)
103{
104 struct perf_sample sample;
105 struct perf_session *session = container_of(oe, struct perf_session,
106 ordered_events);
107 int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample);
108
109 if (ret) {
110 pr_err("Can't parse sample, err = %d\n", ret);
111 return ret;
112 }
113
114 return perf_session__deliver_event(session, event->event, &sample,
115 session->tool, event->file_offset);
116}
117
118struct perf_session *perf_session__new(struct perf_data_file *file,
119 bool repipe, struct perf_tool *tool)
120{
121 struct perf_session *session = zalloc(sizeof(*session));
122
123 if (!session)
124 goto out;
125
126 session->repipe = repipe;
127 session->tool = tool;
128 INIT_LIST_HEAD(&session->auxtrace_index);
129 machines__init(&session->machines);
130 ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
131
132 if (file) {
133 if (perf_data_file__open(file))
134 goto out_delete;
135
136 session->file = file;
137
138 if (perf_data_file__is_read(file)) {
139 if (perf_session__open(session) < 0)
140 goto out_close;
141
142 perf_session__set_id_hdr_size(session);
143 perf_session__set_comm_exec(session);
144 }
145 } else {
146 session->machines.host.env = &perf_env;
147 }
148
149 if (!file || perf_data_file__is_write(file)) {
150
151
152
153
154 if (perf_session__create_kernel_maps(session) < 0)
155 pr_warning("Cannot read kernel map\n");
156 }
157
158 if (tool && tool->ordering_requires_timestamps &&
159 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
160 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
161 tool->ordered_events = false;
162 }
163
164 return session;
165
166 out_close:
167 perf_data_file__close(file);
168 out_delete:
169 perf_session__delete(session);
170 out:
171 return NULL;
172}
173
174static void perf_session__delete_threads(struct perf_session *session)
175{
176 machine__delete_threads(&session->machines.host);
177}
178
179void perf_session__delete(struct perf_session *session)
180{
181 auxtrace__free(session);
182 auxtrace_index__free(&session->auxtrace_index);
183 perf_session__destroy_kernel_maps(session);
184 perf_session__delete_threads(session);
185 perf_env__exit(&session->header.env);
186 machines__exit(&session->machines);
187 if (session->file)
188 perf_data_file__close(session->file);
189 free(session);
190}
191
192static int process_event_synth_tracing_data_stub(struct perf_tool *tool
193 __maybe_unused,
194 union perf_event *event
195 __maybe_unused,
196 struct perf_session *session
197 __maybe_unused)
198{
199 dump_printf(": unhandled!\n");
200 return 0;
201}
202
203static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
204 union perf_event *event __maybe_unused,
205 struct perf_evlist **pevlist
206 __maybe_unused)
207{
208 dump_printf(": unhandled!\n");
209 return 0;
210}
211
212static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused,
213 union perf_event *event __maybe_unused,
214 struct perf_evlist **pevlist
215 __maybe_unused)
216{
217 if (dump_trace)
218 perf_event__fprintf_event_update(event, stdout);
219
220 dump_printf(": unhandled!\n");
221 return 0;
222}
223
224static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
225 union perf_event *event __maybe_unused,
226 struct perf_sample *sample __maybe_unused,
227 struct perf_evsel *evsel __maybe_unused,
228 struct machine *machine __maybe_unused)
229{
230 dump_printf(": unhandled!\n");
231 return 0;
232}
233
234static int process_event_stub(struct perf_tool *tool __maybe_unused,
235 union perf_event *event __maybe_unused,
236 struct perf_sample *sample __maybe_unused,
237 struct machine *machine __maybe_unused)
238{
239 dump_printf(": unhandled!\n");
240 return 0;
241}
242
243static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
244 union perf_event *event __maybe_unused,
245 struct ordered_events *oe __maybe_unused)
246{
247 dump_printf(": unhandled!\n");
248 return 0;
249}
250
251static int process_finished_round(struct perf_tool *tool,
252 union perf_event *event,
253 struct ordered_events *oe);
254
255static int skipn(int fd, off_t n)
256{
257 char buf[4096];
258 ssize_t ret;
259
260 while (n > 0) {
261 ret = read(fd, buf, min(n, (off_t)sizeof(buf)));
262 if (ret <= 0)
263 return ret;
264 n -= ret;
265 }
266
267 return 0;
268}
269
270static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
271 union perf_event *event,
272 struct perf_session *session
273 __maybe_unused)
274{
275 dump_printf(": unhandled!\n");
276 if (perf_data_file__is_pipe(session->file))
277 skipn(perf_data_file__fd(session->file), event->auxtrace.size);
278 return event->auxtrace.size;
279}
280
281static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
282 union perf_event *event __maybe_unused,
283 struct perf_session *session __maybe_unused)
284{
285 dump_printf(": unhandled!\n");
286 return 0;
287}
288
289
290static
291int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
292 union perf_event *event __maybe_unused,
293 struct perf_session *session __maybe_unused)
294{
295 if (dump_trace)
296 perf_event__fprintf_thread_map(event, stdout);
297
298 dump_printf(": unhandled!\n");
299 return 0;
300}
301
302static
303int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
304 union perf_event *event __maybe_unused,
305 struct perf_session *session __maybe_unused)
306{
307 if (dump_trace)
308 perf_event__fprintf_cpu_map(event, stdout);
309
310 dump_printf(": unhandled!\n");
311 return 0;
312}
313
314static
315int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
316 union perf_event *event __maybe_unused,
317 struct perf_session *session __maybe_unused)
318{
319 if (dump_trace)
320 perf_event__fprintf_stat_config(event, stdout);
321
322 dump_printf(": unhandled!\n");
323 return 0;
324}
325
326static int process_stat_stub(struct perf_tool *tool __maybe_unused,
327 union perf_event *event __maybe_unused,
328 struct perf_session *perf_session
329 __maybe_unused)
330{
331 if (dump_trace)
332 perf_event__fprintf_stat(event, stdout);
333
334 dump_printf(": unhandled!\n");
335 return 0;
336}
337
338static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
339 union perf_event *event __maybe_unused,
340 struct perf_session *perf_session
341 __maybe_unused)
342{
343 if (dump_trace)
344 perf_event__fprintf_stat_round(event, stdout);
345
346 dump_printf(": unhandled!\n");
347 return 0;
348}
349
350void perf_tool__fill_defaults(struct perf_tool *tool)
351{
352 if (tool->sample == NULL)
353 tool->sample = process_event_sample_stub;
354 if (tool->mmap == NULL)
355 tool->mmap = process_event_stub;
356 if (tool->mmap2 == NULL)
357 tool->mmap2 = process_event_stub;
358 if (tool->comm == NULL)
359 tool->comm = process_event_stub;
360 if (tool->fork == NULL)
361 tool->fork = process_event_stub;
362 if (tool->exit == NULL)
363 tool->exit = process_event_stub;
364 if (tool->lost == NULL)
365 tool->lost = perf_event__process_lost;
366 if (tool->lost_samples == NULL)
367 tool->lost_samples = perf_event__process_lost_samples;
368 if (tool->aux == NULL)
369 tool->aux = perf_event__process_aux;
370 if (tool->itrace_start == NULL)
371 tool->itrace_start = perf_event__process_itrace_start;
372 if (tool->context_switch == NULL)
373 tool->context_switch = perf_event__process_switch;
374 if (tool->read == NULL)
375 tool->read = process_event_sample_stub;
376 if (tool->throttle == NULL)
377 tool->throttle = process_event_stub;
378 if (tool->unthrottle == NULL)
379 tool->unthrottle = process_event_stub;
380 if (tool->attr == NULL)
381 tool->attr = process_event_synth_attr_stub;
382 if (tool->event_update == NULL)
383 tool->event_update = process_event_synth_event_update_stub;
384 if (tool->tracing_data == NULL)
385 tool->tracing_data = process_event_synth_tracing_data_stub;
386 if (tool->build_id == NULL)
387 tool->build_id = process_event_op2_stub;
388 if (tool->finished_round == NULL) {
389 if (tool->ordered_events)
390 tool->finished_round = process_finished_round;
391 else
392 tool->finished_round = process_finished_round_stub;
393 }
394 if (tool->id_index == NULL)
395 tool->id_index = process_event_op2_stub;
396 if (tool->auxtrace_info == NULL)
397 tool->auxtrace_info = process_event_op2_stub;
398 if (tool->auxtrace == NULL)
399 tool->auxtrace = process_event_auxtrace_stub;
400 if (tool->auxtrace_error == NULL)
401 tool->auxtrace_error = process_event_op2_stub;
402 if (tool->thread_map == NULL)
403 tool->thread_map = process_event_thread_map_stub;
404 if (tool->cpu_map == NULL)
405 tool->cpu_map = process_event_cpu_map_stub;
406 if (tool->stat_config == NULL)
407 tool->stat_config = process_event_stat_config_stub;
408 if (tool->stat == NULL)
409 tool->stat = process_stat_stub;
410 if (tool->stat_round == NULL)
411 tool->stat_round = process_stat_round_stub;
412}
413
414static void swap_sample_id_all(union perf_event *event, void *data)
415{
416 void *end = (void *) event + event->header.size;
417 int size = end - data;
418
419 BUG_ON(size % sizeof(u64));
420 mem_bswap_64(data, size);
421}
422
423static void perf_event__all64_swap(union perf_event *event,
424 bool sample_id_all __maybe_unused)
425{
426 struct perf_event_header *hdr = &event->header;
427 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
428}
429
430static void perf_event__comm_swap(union perf_event *event, bool sample_id_all)
431{
432 event->comm.pid = bswap_32(event->comm.pid);
433 event->comm.tid = bswap_32(event->comm.tid);
434
435 if (sample_id_all) {
436 void *data = &event->comm.comm;
437
438 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
439 swap_sample_id_all(event, data);
440 }
441}
442
443static void perf_event__mmap_swap(union perf_event *event,
444 bool sample_id_all)
445{
446 event->mmap.pid = bswap_32(event->mmap.pid);
447 event->mmap.tid = bswap_32(event->mmap.tid);
448 event->mmap.start = bswap_64(event->mmap.start);
449 event->mmap.len = bswap_64(event->mmap.len);
450 event->mmap.pgoff = bswap_64(event->mmap.pgoff);
451
452 if (sample_id_all) {
453 void *data = &event->mmap.filename;
454
455 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
456 swap_sample_id_all(event, data);
457 }
458}
459
460static void perf_event__mmap2_swap(union perf_event *event,
461 bool sample_id_all)
462{
463 event->mmap2.pid = bswap_32(event->mmap2.pid);
464 event->mmap2.tid = bswap_32(event->mmap2.tid);
465 event->mmap2.start = bswap_64(event->mmap2.start);
466 event->mmap2.len = bswap_64(event->mmap2.len);
467 event->mmap2.pgoff = bswap_64(event->mmap2.pgoff);
468 event->mmap2.maj = bswap_32(event->mmap2.maj);
469 event->mmap2.min = bswap_32(event->mmap2.min);
470 event->mmap2.ino = bswap_64(event->mmap2.ino);
471
472 if (sample_id_all) {
473 void *data = &event->mmap2.filename;
474
475 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
476 swap_sample_id_all(event, data);
477 }
478}
479static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
480{
481 event->fork.pid = bswap_32(event->fork.pid);
482 event->fork.tid = bswap_32(event->fork.tid);
483 event->fork.ppid = bswap_32(event->fork.ppid);
484 event->fork.ptid = bswap_32(event->fork.ptid);
485 event->fork.time = bswap_64(event->fork.time);
486
487 if (sample_id_all)
488 swap_sample_id_all(event, &event->fork + 1);
489}
490
491static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
492{
493 event->read.pid = bswap_32(event->read.pid);
494 event->read.tid = bswap_32(event->read.tid);
495 event->read.value = bswap_64(event->read.value);
496 event->read.time_enabled = bswap_64(event->read.time_enabled);
497 event->read.time_running = bswap_64(event->read.time_running);
498 event->read.id = bswap_64(event->read.id);
499
500 if (sample_id_all)
501 swap_sample_id_all(event, &event->read + 1);
502}
503
504static void perf_event__aux_swap(union perf_event *event, bool sample_id_all)
505{
506 event->aux.aux_offset = bswap_64(event->aux.aux_offset);
507 event->aux.aux_size = bswap_64(event->aux.aux_size);
508 event->aux.flags = bswap_64(event->aux.flags);
509
510 if (sample_id_all)
511 swap_sample_id_all(event, &event->aux + 1);
512}
513
514static void perf_event__itrace_start_swap(union perf_event *event,
515 bool sample_id_all)
516{
517 event->itrace_start.pid = bswap_32(event->itrace_start.pid);
518 event->itrace_start.tid = bswap_32(event->itrace_start.tid);
519
520 if (sample_id_all)
521 swap_sample_id_all(event, &event->itrace_start + 1);
522}
523
524static void perf_event__switch_swap(union perf_event *event, bool sample_id_all)
525{
526 if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
527 event->context_switch.next_prev_pid =
528 bswap_32(event->context_switch.next_prev_pid);
529 event->context_switch.next_prev_tid =
530 bswap_32(event->context_switch.next_prev_tid);
531 }
532
533 if (sample_id_all)
534 swap_sample_id_all(event, &event->context_switch + 1);
535}
536
537static void perf_event__throttle_swap(union perf_event *event,
538 bool sample_id_all)
539{
540 event->throttle.time = bswap_64(event->throttle.time);
541 event->throttle.id = bswap_64(event->throttle.id);
542 event->throttle.stream_id = bswap_64(event->throttle.stream_id);
543
544 if (sample_id_all)
545 swap_sample_id_all(event, &event->throttle + 1);
546}
547
548static u8 revbyte(u8 b)
549{
550 int rev = (b >> 4) | ((b & 0xf) << 4);
551 rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2);
552 rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1);
553 return (u8) rev;
554}
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570static void swap_bitfield(u8 *p, unsigned len)
571{
572 unsigned i;
573
574 for (i = 0; i < len; i++) {
575 *p = revbyte(*p);
576 p++;
577 }
578}
579
580
581void perf_event__attr_swap(struct perf_event_attr *attr)
582{
583 attr->type = bswap_32(attr->type);
584 attr->size = bswap_32(attr->size);
585
586#define bswap_safe(f, n) \
587 (attr->size > (offsetof(struct perf_event_attr, f) + \
588 sizeof(attr->f) * (n)))
589#define bswap_field(f, sz) \
590do { \
591 if (bswap_safe(f, 0)) \
592 attr->f = bswap_##sz(attr->f); \
593} while(0)
594#define bswap_field_32(f) bswap_field(f, 32)
595#define bswap_field_64(f) bswap_field(f, 64)
596
597 bswap_field_64(config);
598 bswap_field_64(sample_period);
599 bswap_field_64(sample_type);
600 bswap_field_64(read_format);
601 bswap_field_32(wakeup_events);
602 bswap_field_32(bp_type);
603 bswap_field_64(bp_addr);
604 bswap_field_64(bp_len);
605 bswap_field_64(branch_sample_type);
606 bswap_field_64(sample_regs_user);
607 bswap_field_32(sample_stack_user);
608 bswap_field_32(aux_watermark);
609
610
611
612
613
614 if (bswap_safe(read_format, 1))
615 swap_bitfield((u8 *) (&attr->read_format + 1),
616 sizeof(u64));
617#undef bswap_field_64
618#undef bswap_field_32
619#undef bswap_field
620#undef bswap_safe
621}
622
623static void perf_event__hdr_attr_swap(union perf_event *event,
624 bool sample_id_all __maybe_unused)
625{
626 size_t size;
627
628 perf_event__attr_swap(&event->attr.attr);
629
630 size = event->header.size;
631 size -= (void *)&event->attr.id - (void *)event;
632 mem_bswap_64(event->attr.id, size);
633}
634
635static void perf_event__event_update_swap(union perf_event *event,
636 bool sample_id_all __maybe_unused)
637{
638 event->event_update.type = bswap_64(event->event_update.type);
639 event->event_update.id = bswap_64(event->event_update.id);
640}
641
642static void perf_event__event_type_swap(union perf_event *event,
643 bool sample_id_all __maybe_unused)
644{
645 event->event_type.event_type.event_id =
646 bswap_64(event->event_type.event_type.event_id);
647}
648
649static void perf_event__tracing_data_swap(union perf_event *event,
650 bool sample_id_all __maybe_unused)
651{
652 event->tracing_data.size = bswap_32(event->tracing_data.size);
653}
654
655static void perf_event__auxtrace_info_swap(union perf_event *event,
656 bool sample_id_all __maybe_unused)
657{
658 size_t size;
659
660 event->auxtrace_info.type = bswap_32(event->auxtrace_info.type);
661
662 size = event->header.size;
663 size -= (void *)&event->auxtrace_info.priv - (void *)event;
664 mem_bswap_64(event->auxtrace_info.priv, size);
665}
666
667static void perf_event__auxtrace_swap(union perf_event *event,
668 bool sample_id_all __maybe_unused)
669{
670 event->auxtrace.size = bswap_64(event->auxtrace.size);
671 event->auxtrace.offset = bswap_64(event->auxtrace.offset);
672 event->auxtrace.reference = bswap_64(event->auxtrace.reference);
673 event->auxtrace.idx = bswap_32(event->auxtrace.idx);
674 event->auxtrace.tid = bswap_32(event->auxtrace.tid);
675 event->auxtrace.cpu = bswap_32(event->auxtrace.cpu);
676}
677
678static void perf_event__auxtrace_error_swap(union perf_event *event,
679 bool sample_id_all __maybe_unused)
680{
681 event->auxtrace_error.type = bswap_32(event->auxtrace_error.type);
682 event->auxtrace_error.code = bswap_32(event->auxtrace_error.code);
683 event->auxtrace_error.cpu = bswap_32(event->auxtrace_error.cpu);
684 event->auxtrace_error.pid = bswap_32(event->auxtrace_error.pid);
685 event->auxtrace_error.tid = bswap_32(event->auxtrace_error.tid);
686 event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip);
687}
688
689static void perf_event__thread_map_swap(union perf_event *event,
690 bool sample_id_all __maybe_unused)
691{
692 unsigned i;
693
694 event->thread_map.nr = bswap_64(event->thread_map.nr);
695
696 for (i = 0; i < event->thread_map.nr; i++)
697 event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);
698}
699
700static void perf_event__cpu_map_swap(union perf_event *event,
701 bool sample_id_all __maybe_unused)
702{
703 struct cpu_map_data *data = &event->cpu_map.data;
704 struct cpu_map_entries *cpus;
705 struct cpu_map_mask *mask;
706 unsigned i;
707
708 data->type = bswap_64(data->type);
709
710 switch (data->type) {
711 case PERF_CPU_MAP__CPUS:
712 cpus = (struct cpu_map_entries *)data->data;
713
714 cpus->nr = bswap_16(cpus->nr);
715
716 for (i = 0; i < cpus->nr; i++)
717 cpus->cpu[i] = bswap_16(cpus->cpu[i]);
718 break;
719 case PERF_CPU_MAP__MASK:
720 mask = (struct cpu_map_mask *) data->data;
721
722 mask->nr = bswap_16(mask->nr);
723 mask->long_size = bswap_16(mask->long_size);
724
725 switch (mask->long_size) {
726 case 4: mem_bswap_32(&mask->mask, mask->nr); break;
727 case 8: mem_bswap_64(&mask->mask, mask->nr); break;
728 default:
729 pr_err("cpu_map swap: unsupported long size\n");
730 }
731 default:
732 break;
733 }
734}
735
736static void perf_event__stat_config_swap(union perf_event *event,
737 bool sample_id_all __maybe_unused)
738{
739 u64 size;
740
741 size = event->stat_config.nr * sizeof(event->stat_config.data[0]);
742 size += 1;
743 mem_bswap_64(&event->stat_config.nr, size);
744}
745
746static void perf_event__stat_swap(union perf_event *event,
747 bool sample_id_all __maybe_unused)
748{
749 event->stat.id = bswap_64(event->stat.id);
750 event->stat.thread = bswap_32(event->stat.thread);
751 event->stat.cpu = bswap_32(event->stat.cpu);
752 event->stat.val = bswap_64(event->stat.val);
753 event->stat.ena = bswap_64(event->stat.ena);
754 event->stat.run = bswap_64(event->stat.run);
755}
756
757static void perf_event__stat_round_swap(union perf_event *event,
758 bool sample_id_all __maybe_unused)
759{
760 event->stat_round.type = bswap_64(event->stat_round.type);
761 event->stat_round.time = bswap_64(event->stat_round.time);
762}
763
764typedef void (*perf_event__swap_op)(union perf_event *event,
765 bool sample_id_all);
766
767static perf_event__swap_op perf_event__swap_ops[] = {
768 [PERF_RECORD_MMAP] = perf_event__mmap_swap,
769 [PERF_RECORD_MMAP2] = perf_event__mmap2_swap,
770 [PERF_RECORD_COMM] = perf_event__comm_swap,
771 [PERF_RECORD_FORK] = perf_event__task_swap,
772 [PERF_RECORD_EXIT] = perf_event__task_swap,
773 [PERF_RECORD_LOST] = perf_event__all64_swap,
774 [PERF_RECORD_READ] = perf_event__read_swap,
775 [PERF_RECORD_THROTTLE] = perf_event__throttle_swap,
776 [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
777 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
778 [PERF_RECORD_AUX] = perf_event__aux_swap,
779 [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap,
780 [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap,
781 [PERF_RECORD_SWITCH] = perf_event__switch_swap,
782 [PERF_RECORD_SWITCH_CPU_WIDE] = perf_event__switch_swap,
783 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
784 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
785 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
786 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
787 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap,
788 [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap,
789 [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap,
790 [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap,
791 [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap,
792 [PERF_RECORD_CPU_MAP] = perf_event__cpu_map_swap,
793 [PERF_RECORD_STAT_CONFIG] = perf_event__stat_config_swap,
794 [PERF_RECORD_STAT] = perf_event__stat_swap,
795 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,
796 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,
797 [PERF_RECORD_HEADER_MAX] = NULL,
798};
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839static int process_finished_round(struct perf_tool *tool __maybe_unused,
840 union perf_event *event __maybe_unused,
841 struct ordered_events *oe)
842{
843 if (dump_trace)
844 fprintf(stdout, "\n");
845 return ordered_events__flush(oe, OE_FLUSH__ROUND);
846}
847
848int perf_session__queue_event(struct perf_session *s, union perf_event *event,
849 struct perf_sample *sample, u64 file_offset)
850{
851 return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
852}
853
854static void callchain__lbr_callstack_printf(struct perf_sample *sample)
855{
856 struct ip_callchain *callchain = sample->callchain;
857 struct branch_stack *lbr_stack = sample->branch_stack;
858 u64 kernel_callchain_nr = callchain->nr;
859 unsigned int i;
860
861 for (i = 0; i < kernel_callchain_nr; i++) {
862 if (callchain->ips[i] == PERF_CONTEXT_USER)
863 break;
864 }
865
866 if ((i != kernel_callchain_nr) && lbr_stack->nr) {
867 u64 total_nr;
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884 total_nr = i + 1 + lbr_stack->nr + 1;
885 kernel_callchain_nr = i + 1;
886
887 printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr);
888
889 for (i = 0; i < kernel_callchain_nr; i++)
890 printf("..... %2d: %016" PRIx64 "\n",
891 i, callchain->ips[i]);
892
893 printf("..... %2d: %016" PRIx64 "\n",
894 (int)(kernel_callchain_nr), lbr_stack->entries[0].to);
895 for (i = 0; i < lbr_stack->nr; i++)
896 printf("..... %2d: %016" PRIx64 "\n",
897 (int)(i + kernel_callchain_nr + 1), lbr_stack->entries[i].from);
898 }
899}
900
901static void callchain__printf(struct perf_evsel *evsel,
902 struct perf_sample *sample)
903{
904 unsigned int i;
905 struct ip_callchain *callchain = sample->callchain;
906
907 if (has_branch_callstack(evsel))
908 callchain__lbr_callstack_printf(sample);
909
910 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
911
912 for (i = 0; i < callchain->nr; i++)
913 printf("..... %2d: %016" PRIx64 "\n",
914 i, callchain->ips[i]);
915}
916
917static void branch_stack__printf(struct perf_sample *sample)
918{
919 uint64_t i;
920
921 printf("... branch stack: nr:%" PRIu64 "\n", sample->branch_stack->nr);
922
923 for (i = 0; i < sample->branch_stack->nr; i++) {
924 struct branch_entry *e = &sample->branch_stack->entries[i];
925
926 printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n",
927 i, e->from, e->to,
928 e->flags.cycles,
929 e->flags.mispred ? "M" : " ",
930 e->flags.predicted ? "P" : " ",
931 e->flags.abort ? "A" : " ",
932 e->flags.in_tx ? "T" : " ",
933 (unsigned)e->flags.reserved);
934 }
935}
936
937static void regs_dump__printf(u64 mask, u64 *regs)
938{
939 unsigned rid, i = 0;
940
941 for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) {
942 u64 val = regs[i++];
943
944 printf(".... %-5s 0x%" PRIx64 "\n",
945 perf_reg_name(rid), val);
946 }
947}
948
949static const char *regs_abi[] = {
950 [PERF_SAMPLE_REGS_ABI_NONE] = "none",
951 [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
952 [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
953};
954
955static inline const char *regs_dump_abi(struct regs_dump *d)
956{
957 if (d->abi > PERF_SAMPLE_REGS_ABI_64)
958 return "unknown";
959
960 return regs_abi[d->abi];
961}
962
963static void regs__printf(const char *type, struct regs_dump *regs)
964{
965 u64 mask = regs->mask;
966
967 printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",
968 type,
969 mask,
970 regs_dump_abi(regs));
971
972 regs_dump__printf(mask, regs->regs);
973}
974
975static void regs_user__printf(struct perf_sample *sample)
976{
977 struct regs_dump *user_regs = &sample->user_regs;
978
979 if (user_regs->regs)
980 regs__printf("user", user_regs);
981}
982
983static void regs_intr__printf(struct perf_sample *sample)
984{
985 struct regs_dump *intr_regs = &sample->intr_regs;
986
987 if (intr_regs->regs)
988 regs__printf("intr", intr_regs);
989}
990
991static void stack_user__printf(struct stack_dump *dump)
992{
993 printf("... ustack: size %" PRIu64 ", offset 0x%x\n",
994 dump->size, dump->offset);
995}
996
997static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
998 union perf_event *event,
999 struct perf_sample *sample)
1000{
1001 u64 sample_type = __perf_evlist__combined_sample_type(evlist);
1002
1003 if (event->header.type != PERF_RECORD_SAMPLE &&
1004 !perf_evlist__sample_id_all(evlist)) {
1005 fputs("-1 -1 ", stdout);
1006 return;
1007 }
1008
1009 if ((sample_type & PERF_SAMPLE_CPU))
1010 printf("%u ", sample->cpu);
1011
1012 if (sample_type & PERF_SAMPLE_TIME)
1013 printf("%" PRIu64 " ", sample->time);
1014}
1015
1016static void sample_read__printf(struct perf_sample *sample, u64 read_format)
1017{
1018 printf("... sample_read:\n");
1019
1020 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1021 printf("...... time enabled %016" PRIx64 "\n",
1022 sample->read.time_enabled);
1023
1024 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1025 printf("...... time running %016" PRIx64 "\n",
1026 sample->read.time_running);
1027
1028 if (read_format & PERF_FORMAT_GROUP) {
1029 u64 i;
1030
1031 printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);
1032
1033 for (i = 0; i < sample->read.group.nr; i++) {
1034 struct sample_read_value *value;
1035
1036 value = &sample->read.group.values[i];
1037 printf("..... id %016" PRIx64
1038 ", value %016" PRIx64 "\n",
1039 value->id, value->value);
1040 }
1041 } else
1042 printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
1043 sample->read.one.id, sample->read.one.value);
1044}
1045
1046static void dump_event(struct perf_evlist *evlist, union perf_event *event,
1047 u64 file_offset, struct perf_sample *sample)
1048{
1049 if (!dump_trace)
1050 return;
1051
1052 printf("\n%#" PRIx64 " [%#x]: event: %d\n",
1053 file_offset, event->header.size, event->header.type);
1054
1055 trace_event(event);
1056
1057 if (sample)
1058 perf_evlist__print_tstamp(evlist, event, sample);
1059
1060 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
1061 event->header.size, perf_event__name(event->header.type));
1062}
1063
1064static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1065 struct perf_sample *sample)
1066{
1067 u64 sample_type;
1068
1069 if (!dump_trace)
1070 return;
1071
1072 printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
1073 event->header.misc, sample->pid, sample->tid, sample->ip,
1074 sample->period, sample->addr);
1075
1076 sample_type = evsel->attr.sample_type;
1077
1078 if (sample_type & PERF_SAMPLE_CALLCHAIN)
1079 callchain__printf(evsel, sample);
1080
1081 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel))
1082 branch_stack__printf(sample);
1083
1084 if (sample_type & PERF_SAMPLE_REGS_USER)
1085 regs_user__printf(sample);
1086
1087 if (sample_type & PERF_SAMPLE_REGS_INTR)
1088 regs_intr__printf(sample);
1089
1090 if (sample_type & PERF_SAMPLE_STACK_USER)
1091 stack_user__printf(&sample->user_stack);
1092
1093 if (sample_type & PERF_SAMPLE_WEIGHT)
1094 printf("... weight: %" PRIu64 "\n", sample->weight);
1095
1096 if (sample_type & PERF_SAMPLE_DATA_SRC)
1097 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
1098
1099 if (sample_type & PERF_SAMPLE_TRANSACTION)
1100 printf("... transaction: %" PRIx64 "\n", sample->transaction);
1101
1102 if (sample_type & PERF_SAMPLE_READ)
1103 sample_read__printf(sample, evsel->attr.read_format);
1104}
1105
1106static struct machine *machines__find_for_cpumode(struct machines *machines,
1107 union perf_event *event,
1108 struct perf_sample *sample)
1109{
1110 struct machine *machine;
1111
1112 if (perf_guest &&
1113 ((sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
1114 (sample->cpumode == PERF_RECORD_MISC_GUEST_USER))) {
1115 u32 pid;
1116
1117 if (event->header.type == PERF_RECORD_MMAP
1118 || event->header.type == PERF_RECORD_MMAP2)
1119 pid = event->mmap.pid;
1120 else
1121 pid = sample->pid;
1122
1123 machine = machines__find(machines, pid);
1124 if (!machine)
1125 machine = machines__findnew(machines, DEFAULT_GUEST_KERNEL_ID);
1126 return machine;
1127 }
1128
1129 return &machines->host;
1130}
1131
1132static int deliver_sample_value(struct perf_evlist *evlist,
1133 struct perf_tool *tool,
1134 union perf_event *event,
1135 struct perf_sample *sample,
1136 struct sample_read_value *v,
1137 struct machine *machine)
1138{
1139 struct perf_sample_id *sid = perf_evlist__id2sid(evlist, v->id);
1140
1141 if (sid) {
1142 sample->id = v->id;
1143 sample->period = v->value - sid->period;
1144 sid->period = v->value;
1145 }
1146
1147 if (!sid || sid->evsel == NULL) {
1148 ++evlist->stats.nr_unknown_id;
1149 return 0;
1150 }
1151
1152 return tool->sample(tool, event, sample, sid->evsel, machine);
1153}
1154
1155static int deliver_sample_group(struct perf_evlist *evlist,
1156 struct perf_tool *tool,
1157 union perf_event *event,
1158 struct perf_sample *sample,
1159 struct machine *machine)
1160{
1161 int ret = -EINVAL;
1162 u64 i;
1163
1164 for (i = 0; i < sample->read.group.nr; i++) {
1165 ret = deliver_sample_value(evlist, tool, event, sample,
1166 &sample->read.group.values[i],
1167 machine);
1168 if (ret)
1169 break;
1170 }
1171
1172 return ret;
1173}
1174
1175static int
1176 perf_evlist__deliver_sample(struct perf_evlist *evlist,
1177 struct perf_tool *tool,
1178 union perf_event *event,
1179 struct perf_sample *sample,
1180 struct perf_evsel *evsel,
1181 struct machine *machine)
1182{
1183
1184 u64 sample_type = evsel->attr.sample_type;
1185 u64 read_format = evsel->attr.read_format;
1186
1187
1188 if (!(sample_type & PERF_SAMPLE_READ))
1189 return tool->sample(tool, event, sample, evsel, machine);
1190
1191
1192 if (read_format & PERF_FORMAT_GROUP)
1193 return deliver_sample_group(evlist, tool, event, sample,
1194 machine);
1195 else
1196 return deliver_sample_value(evlist, tool, event, sample,
1197 &sample->read.one, machine);
1198}
1199
1200static int machines__deliver_event(struct machines *machines,
1201 struct perf_evlist *evlist,
1202 union perf_event *event,
1203 struct perf_sample *sample,
1204 struct perf_tool *tool, u64 file_offset)
1205{
1206 struct perf_evsel *evsel;
1207 struct machine *machine;
1208
1209 dump_event(evlist, event, file_offset, sample);
1210
1211 evsel = perf_evlist__id2evsel(evlist, sample->id);
1212
1213 machine = machines__find_for_cpumode(machines, event, sample);
1214
1215 switch (event->header.type) {
1216 case PERF_RECORD_SAMPLE:
1217 if (evsel == NULL) {
1218 ++evlist->stats.nr_unknown_id;
1219 return 0;
1220 }
1221 dump_sample(evsel, event, sample);
1222 if (machine == NULL) {
1223 ++evlist->stats.nr_unprocessable_samples;
1224 return 0;
1225 }
1226 return perf_evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);
1227 case PERF_RECORD_MMAP:
1228 return tool->mmap(tool, event, sample, machine);
1229 case PERF_RECORD_MMAP2:
1230 if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT)
1231 ++evlist->stats.nr_proc_map_timeout;
1232 return tool->mmap2(tool, event, sample, machine);
1233 case PERF_RECORD_COMM:
1234 return tool->comm(tool, event, sample, machine);
1235 case PERF_RECORD_FORK:
1236 return tool->fork(tool, event, sample, machine);
1237 case PERF_RECORD_EXIT:
1238 return tool->exit(tool, event, sample, machine);
1239 case PERF_RECORD_LOST:
1240 if (tool->lost == perf_event__process_lost)
1241 evlist->stats.total_lost += event->lost.lost;
1242 return tool->lost(tool, event, sample, machine);
1243 case PERF_RECORD_LOST_SAMPLES:
1244 if (tool->lost_samples == perf_event__process_lost_samples)
1245 evlist->stats.total_lost_samples += event->lost_samples.lost;
1246 return tool->lost_samples(tool, event, sample, machine);
1247 case PERF_RECORD_READ:
1248 return tool->read(tool, event, sample, evsel, machine);
1249 case PERF_RECORD_THROTTLE:
1250 return tool->throttle(tool, event, sample, machine);
1251 case PERF_RECORD_UNTHROTTLE:
1252 return tool->unthrottle(tool, event, sample, machine);
1253 case PERF_RECORD_AUX:
1254 if (tool->aux == perf_event__process_aux &&
1255 (event->aux.flags & PERF_AUX_FLAG_TRUNCATED))
1256 evlist->stats.total_aux_lost += 1;
1257 return tool->aux(tool, event, sample, machine);
1258 case PERF_RECORD_ITRACE_START:
1259 return tool->itrace_start(tool, event, sample, machine);
1260 case PERF_RECORD_SWITCH:
1261 case PERF_RECORD_SWITCH_CPU_WIDE:
1262 return tool->context_switch(tool, event, sample, machine);
1263 default:
1264 ++evlist->stats.nr_unknown_events;
1265 return -1;
1266 }
1267}
1268
1269static int perf_session__deliver_event(struct perf_session *session,
1270 union perf_event *event,
1271 struct perf_sample *sample,
1272 struct perf_tool *tool,
1273 u64 file_offset)
1274{
1275 int ret;
1276
1277 ret = auxtrace__process_event(session, event, sample, tool);
1278 if (ret < 0)
1279 return ret;
1280 if (ret > 0)
1281 return 0;
1282
1283 return machines__deliver_event(&session->machines, session->evlist,
1284 event, sample, tool, file_offset);
1285}
1286
1287static s64 perf_session__process_user_event(struct perf_session *session,
1288 union perf_event *event,
1289 u64 file_offset)
1290{
1291 struct ordered_events *oe = &session->ordered_events;
1292 struct perf_tool *tool = session->tool;
1293 int fd = perf_data_file__fd(session->file);
1294 int err;
1295
1296 dump_event(session->evlist, event, file_offset, NULL);
1297
1298
1299 switch (event->header.type) {
1300 case PERF_RECORD_HEADER_ATTR:
1301 err = tool->attr(tool, event, &session->evlist);
1302 if (err == 0) {
1303 perf_session__set_id_hdr_size(session);
1304 perf_session__set_comm_exec(session);
1305 }
1306 return err;
1307 case PERF_RECORD_EVENT_UPDATE:
1308 return tool->event_update(tool, event, &session->evlist);
1309 case PERF_RECORD_HEADER_EVENT_TYPE:
1310
1311
1312
1313
1314 return 0;
1315 case PERF_RECORD_HEADER_TRACING_DATA:
1316
1317 lseek(fd, file_offset, SEEK_SET);
1318 return tool->tracing_data(tool, event, session);
1319 case PERF_RECORD_HEADER_BUILD_ID:
1320 return tool->build_id(tool, event, session);
1321 case PERF_RECORD_FINISHED_ROUND:
1322 return tool->finished_round(tool, event, oe);
1323 case PERF_RECORD_ID_INDEX:
1324 return tool->id_index(tool, event, session);
1325 case PERF_RECORD_AUXTRACE_INFO:
1326 return tool->auxtrace_info(tool, event, session);
1327 case PERF_RECORD_AUXTRACE:
1328
1329 lseek(fd, file_offset + event->header.size, SEEK_SET);
1330 return tool->auxtrace(tool, event, session);
1331 case PERF_RECORD_AUXTRACE_ERROR:
1332 perf_session__auxtrace_error_inc(session, event);
1333 return tool->auxtrace_error(tool, event, session);
1334 case PERF_RECORD_THREAD_MAP:
1335 return tool->thread_map(tool, event, session);
1336 case PERF_RECORD_CPU_MAP:
1337 return tool->cpu_map(tool, event, session);
1338 case PERF_RECORD_STAT_CONFIG:
1339 return tool->stat_config(tool, event, session);
1340 case PERF_RECORD_STAT:
1341 return tool->stat(tool, event, session);
1342 case PERF_RECORD_STAT_ROUND:
1343 return tool->stat_round(tool, event, session);
1344 default:
1345 return -EINVAL;
1346 }
1347}
1348
1349int perf_session__deliver_synth_event(struct perf_session *session,
1350 union perf_event *event,
1351 struct perf_sample *sample)
1352{
1353 struct perf_evlist *evlist = session->evlist;
1354 struct perf_tool *tool = session->tool;
1355
1356 events_stats__inc(&evlist->stats, event->header.type);
1357
1358 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
1359 return perf_session__process_user_event(session, event, 0);
1360
1361 return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
1362}
1363
1364static void event_swap(union perf_event *event, bool sample_id_all)
1365{
1366 perf_event__swap_op swap;
1367
1368 swap = perf_event__swap_ops[event->header.type];
1369 if (swap)
1370 swap(event, sample_id_all);
1371}
1372
1373int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1374 void *buf, size_t buf_sz,
1375 union perf_event **event_ptr,
1376 struct perf_sample *sample)
1377{
1378 union perf_event *event;
1379 size_t hdr_sz, rest;
1380 int fd;
1381
1382 if (session->one_mmap && !session->header.needs_swap) {
1383 event = file_offset - session->one_mmap_offset +
1384 session->one_mmap_addr;
1385 goto out_parse_sample;
1386 }
1387
1388 if (perf_data_file__is_pipe(session->file))
1389 return -1;
1390
1391 fd = perf_data_file__fd(session->file);
1392 hdr_sz = sizeof(struct perf_event_header);
1393
1394 if (buf_sz < hdr_sz)
1395 return -1;
1396
1397 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
1398 readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz)
1399 return -1;
1400
1401 event = (union perf_event *)buf;
1402
1403 if (session->header.needs_swap)
1404 perf_event_header__bswap(&event->header);
1405
1406 if (event->header.size < hdr_sz || event->header.size > buf_sz)
1407 return -1;
1408
1409 rest = event->header.size - hdr_sz;
1410
1411 if (readn(fd, buf, rest) != (ssize_t)rest)
1412 return -1;
1413
1414 if (session->header.needs_swap)
1415 event_swap(event, perf_evlist__sample_id_all(session->evlist));
1416
1417out_parse_sample:
1418
1419 if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&
1420 perf_evlist__parse_sample(session->evlist, event, sample))
1421 return -1;
1422
1423 *event_ptr = event;
1424
1425 return 0;
1426}
1427
1428static s64 perf_session__process_event(struct perf_session *session,
1429 union perf_event *event, u64 file_offset)
1430{
1431 struct perf_evlist *evlist = session->evlist;
1432 struct perf_tool *tool = session->tool;
1433 struct perf_sample sample;
1434 int ret;
1435
1436 if (session->header.needs_swap)
1437 event_swap(event, perf_evlist__sample_id_all(evlist));
1438
1439 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1440 return -EINVAL;
1441
1442 events_stats__inc(&evlist->stats, event->header.type);
1443
1444 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
1445 return perf_session__process_user_event(session, event, file_offset);
1446
1447
1448
1449
1450 ret = perf_evlist__parse_sample(evlist, event, &sample);
1451 if (ret)
1452 return ret;
1453
1454 if (tool->ordered_events) {
1455 ret = perf_session__queue_event(session, event, &sample, file_offset);
1456 if (ret != -ETIME)
1457 return ret;
1458 }
1459
1460 return perf_session__deliver_event(session, event, &sample, tool,
1461 file_offset);
1462}
1463
1464void perf_event_header__bswap(struct perf_event_header *hdr)
1465{
1466 hdr->type = bswap_32(hdr->type);
1467 hdr->misc = bswap_16(hdr->misc);
1468 hdr->size = bswap_16(hdr->size);
1469}
1470
1471struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1472{
1473 return machine__findnew_thread(&session->machines.host, -1, pid);
1474}
1475
1476int perf_session__register_idle_thread(struct perf_session *session)
1477{
1478 struct thread *thread;
1479 int err = 0;
1480
1481 thread = machine__findnew_thread(&session->machines.host, 0, 0);
1482 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
1483 pr_err("problem inserting idle task.\n");
1484 err = -1;
1485 }
1486
1487
1488 thread__put(thread);
1489 return err;
1490}
1491
1492static void perf_session__warn_about_errors(const struct perf_session *session)
1493{
1494 const struct events_stats *stats = &session->evlist->stats;
1495 const struct ordered_events *oe = &session->ordered_events;
1496
1497 if (session->tool->lost == perf_event__process_lost &&
1498 stats->nr_events[PERF_RECORD_LOST] != 0) {
1499 ui__warning("Processed %d events and lost %d chunks!\n\n"
1500 "Check IO/CPU overload!\n\n",
1501 stats->nr_events[0],
1502 stats->nr_events[PERF_RECORD_LOST]);
1503 }
1504
1505 if (session->tool->lost_samples == perf_event__process_lost_samples) {
1506 double drop_rate;
1507
1508 drop_rate = (double)stats->total_lost_samples /
1509 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);
1510 if (drop_rate > 0.05) {
1511 ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n",
1512 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,
1513 drop_rate * 100.0);
1514 }
1515 }
1516
1517 if (session->tool->aux == perf_event__process_aux &&
1518 stats->total_aux_lost != 0) {
1519 ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n",
1520 stats->total_aux_lost,
1521 stats->nr_events[PERF_RECORD_AUX]);
1522 }
1523
1524 if (stats->nr_unknown_events != 0) {
1525 ui__warning("Found %u unknown events!\n\n"
1526 "Is this an older tool processing a perf.data "
1527 "file generated by a more recent tool?\n\n"
1528 "If that is not the case, consider "
1529 "reporting to linux-kernel@vger.kernel.org.\n\n",
1530 stats->nr_unknown_events);
1531 }
1532
1533 if (stats->nr_unknown_id != 0) {
1534 ui__warning("%u samples with id not present in the header\n",
1535 stats->nr_unknown_id);
1536 }
1537
1538 if (stats->nr_invalid_chains != 0) {
1539 ui__warning("Found invalid callchains!\n\n"
1540 "%u out of %u events were discarded for this reason.\n\n"
1541 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
1542 stats->nr_invalid_chains,
1543 stats->nr_events[PERF_RECORD_SAMPLE]);
1544 }
1545
1546 if (stats->nr_unprocessable_samples != 0) {
1547 ui__warning("%u unprocessable samples recorded.\n"
1548 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1549 stats->nr_unprocessable_samples);
1550 }
1551
1552 if (oe->nr_unordered_events != 0)
1553 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1554
1555 events_stats__auxtrace_error_warn(stats);
1556
1557 if (stats->nr_proc_map_timeout != 0) {
1558 ui__warning("%d map information files for pre-existing threads were\n"
1559 "not processed, if there are samples for addresses they\n"
1560 "will not be resolved, you may find out which are these\n"
1561 "threads by running with -v and redirecting the output\n"
1562 "to a file.\n"
1563 "The time limit to process proc map is too short?\n"
1564 "Increase it by --proc-map-timeout\n",
1565 stats->nr_proc_map_timeout);
1566 }
1567}
1568
1569static int perf_session__flush_thread_stack(struct thread *thread,
1570 void *p __maybe_unused)
1571{
1572 return thread_stack__flush(thread);
1573}
1574
1575static int perf_session__flush_thread_stacks(struct perf_session *session)
1576{
1577 return machines__for_each_thread(&session->machines,
1578 perf_session__flush_thread_stack,
1579 NULL);
1580}
1581
1582volatile int session_done;
1583
1584static int __perf_session__process_pipe_events(struct perf_session *session)
1585{
1586 struct ordered_events *oe = &session->ordered_events;
1587 struct perf_tool *tool = session->tool;
1588 int fd = perf_data_file__fd(session->file);
1589 union perf_event *event;
1590 uint32_t size, cur_size = 0;
1591 void *buf = NULL;
1592 s64 skip = 0;
1593 u64 head;
1594 ssize_t err;
1595 void *p;
1596
1597 perf_tool__fill_defaults(tool);
1598
1599 head = 0;
1600 cur_size = sizeof(union perf_event);
1601
1602 buf = malloc(cur_size);
1603 if (!buf)
1604 return -errno;
1605more:
1606 event = buf;
1607 err = readn(fd, event, sizeof(struct perf_event_header));
1608 if (err <= 0) {
1609 if (err == 0)
1610 goto done;
1611
1612 pr_err("failed to read event header\n");
1613 goto out_err;
1614 }
1615
1616 if (session->header.needs_swap)
1617 perf_event_header__bswap(&event->header);
1618
1619 size = event->header.size;
1620 if (size < sizeof(struct perf_event_header)) {
1621 pr_err("bad event header size\n");
1622 goto out_err;
1623 }
1624
1625 if (size > cur_size) {
1626 void *new = realloc(buf, size);
1627 if (!new) {
1628 pr_err("failed to allocate memory to read event\n");
1629 goto out_err;
1630 }
1631 buf = new;
1632 cur_size = size;
1633 event = buf;
1634 }
1635 p = event;
1636 p += sizeof(struct perf_event_header);
1637
1638 if (size - sizeof(struct perf_event_header)) {
1639 err = readn(fd, p, size - sizeof(struct perf_event_header));
1640 if (err <= 0) {
1641 if (err == 0) {
1642 pr_err("unexpected end of event stream\n");
1643 goto done;
1644 }
1645
1646 pr_err("failed to read event data\n");
1647 goto out_err;
1648 }
1649 }
1650
1651 if ((skip = perf_session__process_event(session, event, head)) < 0) {
1652 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1653 head, event->header.size, event->header.type);
1654 err = -EINVAL;
1655 goto out_err;
1656 }
1657
1658 head += size;
1659
1660 if (skip > 0)
1661 head += skip;
1662
1663 if (!session_done())
1664 goto more;
1665done:
1666
1667 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1668 if (err)
1669 goto out_err;
1670 err = auxtrace__flush_events(session, tool);
1671 if (err)
1672 goto out_err;
1673 err = perf_session__flush_thread_stacks(session);
1674out_err:
1675 free(buf);
1676 perf_session__warn_about_errors(session);
1677 ordered_events__free(&session->ordered_events);
1678 auxtrace__free_events(session);
1679 return err;
1680}
1681
1682static union perf_event *
1683fetch_mmaped_event(struct perf_session *session,
1684 u64 head, size_t mmap_size, char *buf)
1685{
1686 union perf_event *event;
1687
1688
1689
1690
1691
1692 if (head + sizeof(event->header) > mmap_size)
1693 return NULL;
1694
1695 event = (union perf_event *)(buf + head);
1696
1697 if (session->header.needs_swap)
1698 perf_event_header__bswap(&event->header);
1699
1700 if (head + event->header.size > mmap_size) {
1701
1702 if (session->header.needs_swap)
1703 perf_event_header__bswap(&event->header);
1704 return NULL;
1705 }
1706
1707 return event;
1708}
1709
1710
1711
1712
1713
1714#if BITS_PER_LONG == 64
1715#define MMAP_SIZE ULLONG_MAX
1716#define NUM_MMAPS 1
1717#else
1718#define MMAP_SIZE (32 * 1024 * 1024ULL)
1719#define NUM_MMAPS 128
1720#endif
1721
1722static int __perf_session__process_events(struct perf_session *session,
1723 u64 data_offset, u64 data_size,
1724 u64 file_size)
1725{
1726 struct ordered_events *oe = &session->ordered_events;
1727 struct perf_tool *tool = session->tool;
1728 int fd = perf_data_file__fd(session->file);
1729 u64 head, page_offset, file_offset, file_pos, size;
1730 int err, mmap_prot, mmap_flags, map_idx = 0;
1731 size_t mmap_size;
1732 char *buf, *mmaps[NUM_MMAPS];
1733 union perf_event *event;
1734 struct ui_progress prog;
1735 s64 skip;
1736
1737 perf_tool__fill_defaults(tool);
1738
1739 page_offset = page_size * (data_offset / page_size);
1740 file_offset = page_offset;
1741 head = data_offset - page_offset;
1742
1743 if (data_size == 0)
1744 goto out;
1745
1746 if (data_offset + data_size < file_size)
1747 file_size = data_offset + data_size;
1748
1749 ui_progress__init(&prog, file_size, "Processing events...");
1750
1751 mmap_size = MMAP_SIZE;
1752 if (mmap_size > file_size) {
1753 mmap_size = file_size;
1754 session->one_mmap = true;
1755 }
1756
1757 memset(mmaps, 0, sizeof(mmaps));
1758
1759 mmap_prot = PROT_READ;
1760 mmap_flags = MAP_SHARED;
1761
1762 if (session->header.needs_swap) {
1763 mmap_prot |= PROT_WRITE;
1764 mmap_flags = MAP_PRIVATE;
1765 }
1766remap:
1767 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd,
1768 file_offset);
1769 if (buf == MAP_FAILED) {
1770 pr_err("failed to mmap file\n");
1771 err = -errno;
1772 goto out_err;
1773 }
1774 mmaps[map_idx] = buf;
1775 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
1776 file_pos = file_offset + head;
1777 if (session->one_mmap) {
1778 session->one_mmap_addr = buf;
1779 session->one_mmap_offset = file_offset;
1780 }
1781
1782more:
1783 event = fetch_mmaped_event(session, head, mmap_size, buf);
1784 if (!event) {
1785 if (mmaps[map_idx]) {
1786 munmap(mmaps[map_idx], mmap_size);
1787 mmaps[map_idx] = NULL;
1788 }
1789
1790 page_offset = page_size * (head / page_size);
1791 file_offset += page_offset;
1792 head -= page_offset;
1793 goto remap;
1794 }
1795
1796 size = event->header.size;
1797
1798 if (size < sizeof(struct perf_event_header) ||
1799 (skip = perf_session__process_event(session, event, file_pos)) < 0) {
1800 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1801 file_offset + head, event->header.size,
1802 event->header.type);
1803 err = -EINVAL;
1804 goto out_err;
1805 }
1806
1807 if (skip)
1808 size += skip;
1809
1810 head += size;
1811 file_pos += size;
1812
1813 ui_progress__update(&prog, size);
1814
1815 if (session_done())
1816 goto out;
1817
1818 if (file_pos < file_size)
1819 goto more;
1820
1821out:
1822
1823 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1824 if (err)
1825 goto out_err;
1826 err = auxtrace__flush_events(session, tool);
1827 if (err)
1828 goto out_err;
1829 err = perf_session__flush_thread_stacks(session);
1830out_err:
1831 ui_progress__finish();
1832 perf_session__warn_about_errors(session);
1833 ordered_events__free(&session->ordered_events);
1834 auxtrace__free_events(session);
1835 session->one_mmap = false;
1836 return err;
1837}
1838
1839int perf_session__process_events(struct perf_session *session)
1840{
1841 u64 size = perf_data_file__size(session->file);
1842 int err;
1843
1844 if (perf_session__register_idle_thread(session) < 0)
1845 return -ENOMEM;
1846
1847 if (!perf_data_file__is_pipe(session->file))
1848 err = __perf_session__process_events(session,
1849 session->header.data_offset,
1850 session->header.data_size, size);
1851 else
1852 err = __perf_session__process_pipe_events(session);
1853
1854 return err;
1855}
1856
1857bool perf_session__has_traces(struct perf_session *session, const char *msg)
1858{
1859 struct perf_evsel *evsel;
1860
1861 evlist__for_each(session->evlist, evsel) {
1862 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1863 return true;
1864 }
1865
1866 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
1867 return false;
1868}
1869
1870int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1871 const char *symbol_name, u64 addr)
1872{
1873 char *bracket;
1874 enum map_type i;
1875 struct ref_reloc_sym *ref;
1876
1877 ref = zalloc(sizeof(struct ref_reloc_sym));
1878 if (ref == NULL)
1879 return -ENOMEM;
1880
1881 ref->name = strdup(symbol_name);
1882 if (ref->name == NULL) {
1883 free(ref);
1884 return -ENOMEM;
1885 }
1886
1887 bracket = strchr(ref->name, ']');
1888 if (bracket)
1889 *bracket = '\0';
1890
1891 ref->addr = addr;
1892
1893 for (i = 0; i < MAP__NR_TYPES; ++i) {
1894 struct kmap *kmap = map__kmap(maps[i]);
1895
1896 if (!kmap)
1897 continue;
1898 kmap->ref_reloc_sym = ref;
1899 }
1900
1901 return 0;
1902}
1903
1904size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp)
1905{
1906 return machines__fprintf_dsos(&session->machines, fp);
1907}
1908
1909size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
1910 bool (skip)(struct dso *dso, int parm), int parm)
1911{
1912 return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm);
1913}
1914
1915size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1916{
1917 size_t ret;
1918 const char *msg = "";
1919
1920 if (perf_header__has_feat(&session->header, HEADER_AUXTRACE))
1921 msg = " (excludes AUX area (e.g. instruction trace) decoded / synthesized events)";
1922
1923 ret = fprintf(fp, "\nAggregated stats:%s\n", msg);
1924
1925 ret += events_stats__fprintf(&session->evlist->stats, fp);
1926 return ret;
1927}
1928
1929size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
1930{
1931
1932
1933
1934
1935 return machine__fprintf(&session->machines.host, fp);
1936}
1937
1938struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1939 unsigned int type)
1940{
1941 struct perf_evsel *pos;
1942
1943 evlist__for_each(session->evlist, pos) {
1944 if (pos->attr.type == type)
1945 return pos;
1946 }
1947 return NULL;
1948}
1949
1950void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1951 struct addr_location *al,
1952 unsigned int print_opts, unsigned int stack_depth)
1953{
1954 struct callchain_cursor_node *node;
1955 int print_ip = print_opts & PRINT_IP_OPT_IP;
1956 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1957 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1958 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1959 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1960 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
1961 char s = print_oneline ? ' ' : '\t';
1962
1963 if (symbol_conf.use_callchain && sample->callchain) {
1964 struct addr_location node_al;
1965
1966 if (thread__resolve_callchain(al->thread, evsel,
1967 sample, NULL, NULL,
1968 stack_depth) != 0) {
1969 if (verbose)
1970 error("Failed to resolve callchain. Skipping\n");
1971 return;
1972 }
1973 callchain_cursor_commit(&callchain_cursor);
1974
1975 if (print_symoffset)
1976 node_al = *al;
1977
1978 while (stack_depth) {
1979 u64 addr = 0;
1980
1981 node = callchain_cursor_current(&callchain_cursor);
1982 if (!node)
1983 break;
1984
1985 if (node->sym && node->sym->ignore)
1986 goto next;
1987
1988 if (print_ip)
1989 printf("%c%16" PRIx64, s, node->ip);
1990
1991 if (node->map)
1992 addr = node->map->map_ip(node->map, node->ip);
1993
1994 if (print_sym) {
1995 printf(" ");
1996 if (print_symoffset) {
1997 node_al.addr = addr;
1998 node_al.map = node->map;
1999 symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
2000 } else
2001 symbol__fprintf_symname(node->sym, stdout);
2002 }
2003
2004 if (print_dso) {
2005 printf(" (");
2006 map__fprintf_dsoname(node->map, stdout);
2007 printf(")");
2008 }
2009
2010 if (print_srcline)
2011 map__fprintf_srcline(node->map, addr, "\n ",
2012 stdout);
2013
2014 if (!print_oneline)
2015 printf("\n");
2016
2017 stack_depth--;
2018next:
2019 callchain_cursor_advance(&callchain_cursor);
2020 }
2021
2022 } else {
2023 if (al->sym && al->sym->ignore)
2024 return;
2025
2026 if (print_ip)
2027 printf("%16" PRIx64, sample->ip);
2028
2029 if (print_sym) {
2030 printf(" ");
2031 if (print_symoffset)
2032 symbol__fprintf_symname_offs(al->sym, al,
2033 stdout);
2034 else
2035 symbol__fprintf_symname(al->sym, stdout);
2036 }
2037
2038 if (print_dso) {
2039 printf(" (");
2040 map__fprintf_dsoname(al->map, stdout);
2041 printf(")");
2042 }
2043
2044 if (print_srcline)
2045 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
2046 }
2047}
2048
2049int perf_session__cpu_bitmap(struct perf_session *session,
2050 const char *cpu_list, unsigned long *cpu_bitmap)
2051{
2052 int i, err = -1;
2053 struct cpu_map *map;
2054
2055 for (i = 0; i < PERF_TYPE_MAX; ++i) {
2056 struct perf_evsel *evsel;
2057
2058 evsel = perf_session__find_first_evtype(session, i);
2059 if (!evsel)
2060 continue;
2061
2062 if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
2063 pr_err("File does not contain CPU events. "
2064 "Remove -c option to proceed.\n");
2065 return -1;
2066 }
2067 }
2068
2069 map = cpu_map__new(cpu_list);
2070 if (map == NULL) {
2071 pr_err("Invalid cpu_list\n");
2072 return -1;
2073 }
2074
2075 for (i = 0; i < map->nr; i++) {
2076 int cpu = map->map[i];
2077
2078 if (cpu >= MAX_NR_CPUS) {
2079 pr_err("Requested CPU %d too large. "
2080 "Consider raising MAX_NR_CPUS\n", cpu);
2081 goto out_delete_map;
2082 }
2083
2084 set_bit(cpu, cpu_bitmap);
2085 }
2086
2087 err = 0;
2088
2089out_delete_map:
2090 cpu_map__put(map);
2091 return err;
2092}
2093
2094void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
2095 bool full)
2096{
2097 struct stat st;
2098 int fd, ret;
2099
2100 if (session == NULL || fp == NULL)
2101 return;
2102
2103 fd = perf_data_file__fd(session->file);
2104
2105 ret = fstat(fd, &st);
2106 if (ret == -1)
2107 return;
2108
2109 fprintf(fp, "# ========\n");
2110 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
2111 perf_header__fprintf_info(session, fp, full);
2112 fprintf(fp, "# ========\n#\n");
2113}
2114
2115
2116int __perf_session__set_tracepoints_handlers(struct perf_session *session,
2117 const struct perf_evsel_str_handler *assocs,
2118 size_t nr_assocs)
2119{
2120 struct perf_evsel *evsel;
2121 size_t i;
2122 int err;
2123
2124 for (i = 0; i < nr_assocs; i++) {
2125
2126
2127
2128
2129 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, assocs[i].name);
2130 if (evsel == NULL)
2131 continue;
2132
2133 err = -EEXIST;
2134 if (evsel->handler != NULL)
2135 goto out;
2136 evsel->handler = assocs[i].handler;
2137 }
2138
2139 err = 0;
2140out:
2141 return err;
2142}
2143
2144int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
2145 union perf_event *event,
2146 struct perf_session *session)
2147{
2148 struct perf_evlist *evlist = session->evlist;
2149 struct id_index_event *ie = &event->id_index;
2150 size_t i, nr, max_nr;
2151
2152 max_nr = (ie->header.size - sizeof(struct id_index_event)) /
2153 sizeof(struct id_index_entry);
2154 nr = ie->nr;
2155 if (nr > max_nr)
2156 return -EINVAL;
2157
2158 if (dump_trace)
2159 fprintf(stdout, " nr: %zu\n", nr);
2160
2161 for (i = 0; i < nr; i++) {
2162 struct id_index_entry *e = &ie->entries[i];
2163 struct perf_sample_id *sid;
2164
2165 if (dump_trace) {
2166 fprintf(stdout, " ... id: %"PRIu64, e->id);
2167 fprintf(stdout, " idx: %"PRIu64, e->idx);
2168 fprintf(stdout, " cpu: %"PRId64, e->cpu);
2169 fprintf(stdout, " tid: %"PRId64"\n", e->tid);
2170 }
2171
2172 sid = perf_evlist__id2sid(evlist, e->id);
2173 if (!sid)
2174 return -ENOENT;
2175 sid->idx = e->idx;
2176 sid->cpu = e->cpu;
2177 sid->tid = e->tid;
2178 }
2179 return 0;
2180}
2181
2182int perf_event__synthesize_id_index(struct perf_tool *tool,
2183 perf_event__handler_t process,
2184 struct perf_evlist *evlist,
2185 struct machine *machine)
2186{
2187 union perf_event *ev;
2188 struct perf_evsel *evsel;
2189 size_t nr = 0, i = 0, sz, max_nr, n;
2190 int err;
2191
2192 pr_debug2("Synthesizing id index\n");
2193
2194 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
2195 sizeof(struct id_index_entry);
2196
2197 evlist__for_each(evlist, evsel)
2198 nr += evsel->ids;
2199
2200 n = nr > max_nr ? max_nr : nr;
2201 sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
2202 ev = zalloc(sz);
2203 if (!ev)
2204 return -ENOMEM;
2205
2206 ev->id_index.header.type = PERF_RECORD_ID_INDEX;
2207 ev->id_index.header.size = sz;
2208 ev->id_index.nr = n;
2209
2210 evlist__for_each(evlist, evsel) {
2211 u32 j;
2212
2213 for (j = 0; j < evsel->ids; j++) {
2214 struct id_index_entry *e;
2215 struct perf_sample_id *sid;
2216
2217 if (i >= n) {
2218 err = process(tool, ev, NULL, machine);
2219 if (err)
2220 goto out_err;
2221 nr -= n;
2222 i = 0;
2223 }
2224
2225 e = &ev->id_index.entries[i++];
2226
2227 e->id = evsel->id[j];
2228
2229 sid = perf_evlist__id2sid(evlist, e->id);
2230 if (!sid) {
2231 free(ev);
2232 return -ENOENT;
2233 }
2234
2235 e->idx = sid->idx;
2236 e->cpu = sid->cpu;
2237 e->tid = sid->tid;
2238 }
2239 }
2240
2241 sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
2242 ev->id_index.header.size = sz;
2243 ev->id_index.nr = nr;
2244
2245 err = process(tool, ev, NULL, machine);
2246out_err:
2247 free(ev);
2248
2249 return err;
2250}
2251