1#include <linux/kernel.h>
2
3#include <byteswap.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/mman.h>
7
8#include "evlist.h"
9#include "evsel.h"
10#include "session.h"
11#include "tool.h"
12#include "sort.h"
13#include "util.h"
14#include "cpumap.h"
15#include "event-parse.h"
16#include "perf_regs.h"
17#include "vdso.h"
18
19static int perf_session__open(struct perf_session *self, bool force)
20{
21 struct stat input_stat;
22
23 if (!strcmp(self->filename, "-")) {
24 self->fd_pipe = true;
25 self->fd = STDIN_FILENO;
26
27 if (perf_session__read_header(self, self->fd) < 0)
28 pr_err("incompatible file format (rerun with -v to learn more)");
29
30 return 0;
31 }
32
33 self->fd = open(self->filename, O_RDONLY);
34 if (self->fd < 0) {
35 int err = errno;
36
37 pr_err("failed to open %s: %s", self->filename, strerror(err));
38 if (err == ENOENT && !strcmp(self->filename, "perf.data"))
39 pr_err(" (try 'perf record' first)");
40 pr_err("\n");
41 return -errno;
42 }
43
44 if (fstat(self->fd, &input_stat) < 0)
45 goto out_close;
46
47 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
48 pr_err("file %s not owned by current user or root\n",
49 self->filename);
50 goto out_close;
51 }
52
53 if (!input_stat.st_size) {
54 pr_info("zero-sized file (%s), nothing to do!\n",
55 self->filename);
56 goto out_close;
57 }
58
59 if (perf_session__read_header(self, self->fd) < 0) {
60 pr_err("incompatible file format (rerun with -v to learn more)");
61 goto out_close;
62 }
63
64 if (!perf_evlist__valid_sample_type(self->evlist)) {
65 pr_err("non matching sample_type");
66 goto out_close;
67 }
68
69 if (!perf_evlist__valid_sample_id_all(self->evlist)) {
70 pr_err("non matching sample_id_all");
71 goto out_close;
72 }
73
74 self->size = input_stat.st_size;
75 return 0;
76
77out_close:
78 close(self->fd);
79 self->fd = -1;
80 return -1;
81}
82
83void perf_session__set_id_hdr_size(struct perf_session *session)
84{
85 u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist);
86
87 machines__set_id_hdr_size(&session->machines, id_hdr_size);
88}
89
90int perf_session__create_kernel_maps(struct perf_session *self)
91{
92 int ret = machine__create_kernel_maps(&self->machines.host);
93
94 if (ret >= 0)
95 ret = machines__create_guest_kernel_maps(&self->machines);
96 return ret;
97}
98
99static void perf_session__destroy_kernel_maps(struct perf_session *self)
100{
101 machines__destroy_kernel_maps(&self->machines);
102}
103
104struct perf_session *perf_session__new(const char *filename, int mode,
105 bool force, bool repipe,
106 struct perf_tool *tool)
107{
108 struct perf_session *self;
109 struct stat st;
110 size_t len;
111
112 if (!filename || !strlen(filename)) {
113 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
114 filename = "-";
115 else
116 filename = "perf.data";
117 }
118
119 len = strlen(filename);
120 self = zalloc(sizeof(*self) + len);
121
122 if (self == NULL)
123 goto out;
124
125 memcpy(self->filename, filename, len);
126 self->repipe = repipe;
127 INIT_LIST_HEAD(&self->ordered_samples.samples);
128 INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
129 INIT_LIST_HEAD(&self->ordered_samples.to_free);
130 machines__init(&self->machines);
131
132 if (mode == O_RDONLY) {
133 if (perf_session__open(self, force) < 0)
134 goto out_delete;
135 perf_session__set_id_hdr_size(self);
136 } else if (mode == O_WRONLY) {
137
138
139
140
141 if (perf_session__create_kernel_maps(self) < 0)
142 goto out_delete;
143 }
144
145 if (tool && tool->ordering_requires_timestamps &&
146 tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {
147 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
148 tool->ordered_samples = false;
149 }
150
151out:
152 return self;
153out_delete:
154 perf_session__delete(self);
155 return NULL;
156}
157
158static void perf_session__delete_dead_threads(struct perf_session *session)
159{
160 machine__delete_dead_threads(&session->machines.host);
161}
162
163static void perf_session__delete_threads(struct perf_session *session)
164{
165 machine__delete_threads(&session->machines.host);
166}
167
168static void perf_session_env__delete(struct perf_session_env *env)
169{
170 free(env->hostname);
171 free(env->os_release);
172 free(env->version);
173 free(env->arch);
174 free(env->cpu_desc);
175 free(env->cpuid);
176
177 free(env->cmdline);
178 free(env->sibling_cores);
179 free(env->sibling_threads);
180 free(env->numa_nodes);
181 free(env->pmu_mappings);
182}
183
184void perf_session__delete(struct perf_session *self)
185{
186 perf_session__destroy_kernel_maps(self);
187 perf_session__delete_dead_threads(self);
188 perf_session__delete_threads(self);
189 perf_session_env__delete(&self->header.env);
190 machines__exit(&self->machines);
191 close(self->fd);
192 free(self);
193 vdso__exit();
194}
195
196static int process_event_synth_tracing_data_stub(union perf_event *event
197 __maybe_unused,
198 struct perf_session *session
199 __maybe_unused)
200{
201 dump_printf(": unhandled!\n");
202 return 0;
203}
204
205static int process_event_synth_attr_stub(union perf_event *event __maybe_unused,
206 struct perf_evlist **pevlist
207 __maybe_unused)
208{
209 dump_printf(": unhandled!\n");
210 return 0;
211}
212
213static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
214 union perf_event *event __maybe_unused,
215 struct perf_sample *sample __maybe_unused,
216 struct perf_evsel *evsel __maybe_unused,
217 struct machine *machine __maybe_unused)
218{
219 dump_printf(": unhandled!\n");
220 return 0;
221}
222
223static int process_event_stub(struct perf_tool *tool __maybe_unused,
224 union perf_event *event __maybe_unused,
225 struct perf_sample *sample __maybe_unused,
226 struct machine *machine __maybe_unused)
227{
228 dump_printf(": unhandled!\n");
229 return 0;
230}
231
232static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
233 union perf_event *event __maybe_unused,
234 struct perf_session *perf_session
235 __maybe_unused)
236{
237 dump_printf(": unhandled!\n");
238 return 0;
239}
240
241static int process_event_type_stub(struct perf_tool *tool __maybe_unused,
242 union perf_event *event __maybe_unused)
243{
244 dump_printf(": unhandled!\n");
245 return 0;
246}
247
248static int process_finished_round(struct perf_tool *tool,
249 union perf_event *event,
250 struct perf_session *session);
251
252static void perf_tool__fill_defaults(struct perf_tool *tool)
253{
254 if (tool->sample == NULL)
255 tool->sample = process_event_sample_stub;
256 if (tool->mmap == NULL)
257 tool->mmap = process_event_stub;
258 if (tool->comm == NULL)
259 tool->comm = process_event_stub;
260 if (tool->fork == NULL)
261 tool->fork = process_event_stub;
262 if (tool->exit == NULL)
263 tool->exit = process_event_stub;
264 if (tool->lost == NULL)
265 tool->lost = perf_event__process_lost;
266 if (tool->read == NULL)
267 tool->read = process_event_sample_stub;
268 if (tool->throttle == NULL)
269 tool->throttle = process_event_stub;
270 if (tool->unthrottle == NULL)
271 tool->unthrottle = process_event_stub;
272 if (tool->attr == NULL)
273 tool->attr = process_event_synth_attr_stub;
274 if (tool->event_type == NULL)
275 tool->event_type = process_event_type_stub;
276 if (tool->tracing_data == NULL)
277 tool->tracing_data = process_event_synth_tracing_data_stub;
278 if (tool->build_id == NULL)
279 tool->build_id = process_finished_round_stub;
280 if (tool->finished_round == NULL) {
281 if (tool->ordered_samples)
282 tool->finished_round = process_finished_round;
283 else
284 tool->finished_round = process_finished_round_stub;
285 }
286}
287
288void mem_bswap_32(void *src, int byte_size)
289{
290 u32 *m = src;
291 while (byte_size > 0) {
292 *m = bswap_32(*m);
293 byte_size -= sizeof(u32);
294 ++m;
295 }
296}
297
298void mem_bswap_64(void *src, int byte_size)
299{
300 u64 *m = src;
301
302 while (byte_size > 0) {
303 *m = bswap_64(*m);
304 byte_size -= sizeof(u64);
305 ++m;
306 }
307}
308
309static void swap_sample_id_all(union perf_event *event, void *data)
310{
311 void *end = (void *) event + event->header.size;
312 int size = end - data;
313
314 BUG_ON(size % sizeof(u64));
315 mem_bswap_64(data, size);
316}
317
318static void perf_event__all64_swap(union perf_event *event,
319 bool sample_id_all __maybe_unused)
320{
321 struct perf_event_header *hdr = &event->header;
322 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
323}
324
325static void perf_event__comm_swap(union perf_event *event, bool sample_id_all)
326{
327 event->comm.pid = bswap_32(event->comm.pid);
328 event->comm.tid = bswap_32(event->comm.tid);
329
330 if (sample_id_all) {
331 void *data = &event->comm.comm;
332
333 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
334 swap_sample_id_all(event, data);
335 }
336}
337
338static void perf_event__mmap_swap(union perf_event *event,
339 bool sample_id_all)
340{
341 event->mmap.pid = bswap_32(event->mmap.pid);
342 event->mmap.tid = bswap_32(event->mmap.tid);
343 event->mmap.start = bswap_64(event->mmap.start);
344 event->mmap.len = bswap_64(event->mmap.len);
345 event->mmap.pgoff = bswap_64(event->mmap.pgoff);
346
347 if (sample_id_all) {
348 void *data = &event->mmap.filename;
349
350 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
351 swap_sample_id_all(event, data);
352 }
353}
354
355static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
356{
357 event->fork.pid = bswap_32(event->fork.pid);
358 event->fork.tid = bswap_32(event->fork.tid);
359 event->fork.ppid = bswap_32(event->fork.ppid);
360 event->fork.ptid = bswap_32(event->fork.ptid);
361 event->fork.time = bswap_64(event->fork.time);
362
363 if (sample_id_all)
364 swap_sample_id_all(event, &event->fork + 1);
365}
366
367static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
368{
369 event->read.pid = bswap_32(event->read.pid);
370 event->read.tid = bswap_32(event->read.tid);
371 event->read.value = bswap_64(event->read.value);
372 event->read.time_enabled = bswap_64(event->read.time_enabled);
373 event->read.time_running = bswap_64(event->read.time_running);
374 event->read.id = bswap_64(event->read.id);
375
376 if (sample_id_all)
377 swap_sample_id_all(event, &event->read + 1);
378}
379
380static u8 revbyte(u8 b)
381{
382 int rev = (b >> 4) | ((b & 0xf) << 4);
383 rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2);
384 rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1);
385 return (u8) rev;
386}
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402static void swap_bitfield(u8 *p, unsigned len)
403{
404 unsigned i;
405
406 for (i = 0; i < len; i++) {
407 *p = revbyte(*p);
408 p++;
409 }
410}
411
412
413void perf_event__attr_swap(struct perf_event_attr *attr)
414{
415 attr->type = bswap_32(attr->type);
416 attr->size = bswap_32(attr->size);
417 attr->config = bswap_64(attr->config);
418 attr->sample_period = bswap_64(attr->sample_period);
419 attr->sample_type = bswap_64(attr->sample_type);
420 attr->read_format = bswap_64(attr->read_format);
421 attr->wakeup_events = bswap_32(attr->wakeup_events);
422 attr->bp_type = bswap_32(attr->bp_type);
423 attr->bp_addr = bswap_64(attr->bp_addr);
424 attr->bp_len = bswap_64(attr->bp_len);
425
426 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
427}
428
429static void perf_event__hdr_attr_swap(union perf_event *event,
430 bool sample_id_all __maybe_unused)
431{
432 size_t size;
433
434 perf_event__attr_swap(&event->attr.attr);
435
436 size = event->header.size;
437 size -= (void *)&event->attr.id - (void *)event;
438 mem_bswap_64(event->attr.id, size);
439}
440
441static void perf_event__event_type_swap(union perf_event *event,
442 bool sample_id_all __maybe_unused)
443{
444 event->event_type.event_type.event_id =
445 bswap_64(event->event_type.event_type.event_id);
446}
447
448static void perf_event__tracing_data_swap(union perf_event *event,
449 bool sample_id_all __maybe_unused)
450{
451 event->tracing_data.size = bswap_32(event->tracing_data.size);
452}
453
454typedef void (*perf_event__swap_op)(union perf_event *event,
455 bool sample_id_all);
456
457static perf_event__swap_op perf_event__swap_ops[] = {
458 [PERF_RECORD_MMAP] = perf_event__mmap_swap,
459 [PERF_RECORD_COMM] = perf_event__comm_swap,
460 [PERF_RECORD_FORK] = perf_event__task_swap,
461 [PERF_RECORD_EXIT] = perf_event__task_swap,
462 [PERF_RECORD_LOST] = perf_event__all64_swap,
463 [PERF_RECORD_READ] = perf_event__read_swap,
464 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
465 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
466 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
467 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
468 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
469 [PERF_RECORD_HEADER_MAX] = NULL,
470};
471
472struct sample_queue {
473 u64 timestamp;
474 u64 file_offset;
475 union perf_event *event;
476 struct list_head list;
477};
478
479static void perf_session_free_sample_buffers(struct perf_session *session)
480{
481 struct ordered_samples *os = &session->ordered_samples;
482
483 while (!list_empty(&os->to_free)) {
484 struct sample_queue *sq;
485
486 sq = list_entry(os->to_free.next, struct sample_queue, list);
487 list_del(&sq->list);
488 free(sq);
489 }
490}
491
492static int perf_session_deliver_event(struct perf_session *session,
493 union perf_event *event,
494 struct perf_sample *sample,
495 struct perf_tool *tool,
496 u64 file_offset);
497
498static int flush_sample_queue(struct perf_session *s,
499 struct perf_tool *tool)
500{
501 struct ordered_samples *os = &s->ordered_samples;
502 struct list_head *head = &os->samples;
503 struct sample_queue *tmp, *iter;
504 struct perf_sample sample;
505 u64 limit = os->next_flush;
506 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
507 unsigned idx = 0, progress_next = os->nr_samples / 16;
508 int ret;
509
510 if (!tool->ordered_samples || !limit)
511 return 0;
512
513 list_for_each_entry_safe(iter, tmp, head, list) {
514 if (iter->timestamp > limit)
515 break;
516
517 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
518 if (ret)
519 pr_err("Can't parse sample, err = %d\n", ret);
520 else {
521 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
522 iter->file_offset);
523 if (ret)
524 return ret;
525 }
526
527 os->last_flush = iter->timestamp;
528 list_del(&iter->list);
529 list_add(&iter->list, &os->sample_cache);
530 if (++idx >= progress_next) {
531 progress_next += os->nr_samples / 16;
532 ui_progress__update(idx, os->nr_samples,
533 "Processing time ordered events...");
534 }
535 }
536
537 if (list_empty(head)) {
538 os->last_sample = NULL;
539 } else if (last_ts <= limit) {
540 os->last_sample =
541 list_entry(head->prev, struct sample_queue, list);
542 }
543
544 os->nr_samples = 0;
545
546 return 0;
547}
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588static int process_finished_round(struct perf_tool *tool,
589 union perf_event *event __maybe_unused,
590 struct perf_session *session)
591{
592 int ret = flush_sample_queue(session, tool);
593 if (!ret)
594 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
595
596 return ret;
597}
598
599
600static void __queue_event(struct sample_queue *new, struct perf_session *s)
601{
602 struct ordered_samples *os = &s->ordered_samples;
603 struct sample_queue *sample = os->last_sample;
604 u64 timestamp = new->timestamp;
605 struct list_head *p;
606
607 ++os->nr_samples;
608 os->last_sample = new;
609
610 if (!sample) {
611 list_add(&new->list, &os->samples);
612 os->max_timestamp = timestamp;
613 return;
614 }
615
616
617
618
619
620
621 if (sample->timestamp <= timestamp) {
622 while (sample->timestamp <= timestamp) {
623 p = sample->list.next;
624 if (p == &os->samples) {
625 list_add_tail(&new->list, &os->samples);
626 os->max_timestamp = timestamp;
627 return;
628 }
629 sample = list_entry(p, struct sample_queue, list);
630 }
631 list_add_tail(&new->list, &sample->list);
632 } else {
633 while (sample->timestamp > timestamp) {
634 p = sample->list.prev;
635 if (p == &os->samples) {
636 list_add(&new->list, &os->samples);
637 return;
638 }
639 sample = list_entry(p, struct sample_queue, list);
640 }
641 list_add(&new->list, &sample->list);
642 }
643}
644
645#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
646
647static int perf_session_queue_event(struct perf_session *s, union perf_event *event,
648 struct perf_sample *sample, u64 file_offset)
649{
650 struct ordered_samples *os = &s->ordered_samples;
651 struct list_head *sc = &os->sample_cache;
652 u64 timestamp = sample->time;
653 struct sample_queue *new;
654
655 if (!timestamp || timestamp == ~0ULL)
656 return -ETIME;
657
658 if (timestamp < s->ordered_samples.last_flush) {
659 printf("Warning: Timestamp below last timeslice flush\n");
660 return -EINVAL;
661 }
662
663 if (!list_empty(sc)) {
664 new = list_entry(sc->next, struct sample_queue, list);
665 list_del(&new->list);
666 } else if (os->sample_buffer) {
667 new = os->sample_buffer + os->sample_buffer_idx;
668 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
669 os->sample_buffer = NULL;
670 } else {
671 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
672 if (!os->sample_buffer)
673 return -ENOMEM;
674 list_add(&os->sample_buffer->list, &os->to_free);
675 os->sample_buffer_idx = 2;
676 new = os->sample_buffer + 1;
677 }
678
679 new->timestamp = timestamp;
680 new->file_offset = file_offset;
681 new->event = event;
682
683 __queue_event(new, s);
684
685 return 0;
686}
687
688static void callchain__printf(struct perf_sample *sample)
689{
690 unsigned int i;
691
692 printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr);
693
694 for (i = 0; i < sample->callchain->nr; i++)
695 printf("..... %2d: %016" PRIx64 "\n",
696 i, sample->callchain->ips[i]);
697}
698
699static void branch_stack__printf(struct perf_sample *sample)
700{
701 uint64_t i;
702
703 printf("... branch stack: nr:%" PRIu64 "\n", sample->branch_stack->nr);
704
705 for (i = 0; i < sample->branch_stack->nr; i++)
706 printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 "\n",
707 i, sample->branch_stack->entries[i].from,
708 sample->branch_stack->entries[i].to);
709}
710
711static void regs_dump__printf(u64 mask, u64 *regs)
712{
713 unsigned rid, i = 0;
714
715 for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) {
716 u64 val = regs[i++];
717
718 printf(".... %-5s 0x%" PRIx64 "\n",
719 perf_reg_name(rid), val);
720 }
721}
722
723static void regs_user__printf(struct perf_sample *sample, u64 mask)
724{
725 struct regs_dump *user_regs = &sample->user_regs;
726
727 if (user_regs->regs) {
728 printf("... user regs: mask 0x%" PRIx64 "\n", mask);
729 regs_dump__printf(mask, user_regs->regs);
730 }
731}
732
733static void stack_user__printf(struct stack_dump *dump)
734{
735 printf("... ustack: size %" PRIu64 ", offset 0x%x\n",
736 dump->size, dump->offset);
737}
738
739static void perf_session__print_tstamp(struct perf_session *session,
740 union perf_event *event,
741 struct perf_sample *sample)
742{
743 u64 sample_type = perf_evlist__sample_type(session->evlist);
744
745 if (event->header.type != PERF_RECORD_SAMPLE &&
746 !perf_evlist__sample_id_all(session->evlist)) {
747 fputs("-1 -1 ", stdout);
748 return;
749 }
750
751 if ((sample_type & PERF_SAMPLE_CPU))
752 printf("%u ", sample->cpu);
753
754 if (sample_type & PERF_SAMPLE_TIME)
755 printf("%" PRIu64 " ", sample->time);
756}
757
758static void dump_event(struct perf_session *session, union perf_event *event,
759 u64 file_offset, struct perf_sample *sample)
760{
761 if (!dump_trace)
762 return;
763
764 printf("\n%#" PRIx64 " [%#x]: event: %d\n",
765 file_offset, event->header.size, event->header.type);
766
767 trace_event(event);
768
769 if (sample)
770 perf_session__print_tstamp(session, event, sample);
771
772 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
773 event->header.size, perf_event__name(event->header.type));
774}
775
776static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
777 struct perf_sample *sample)
778{
779 u64 sample_type;
780
781 if (!dump_trace)
782 return;
783
784 printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
785 event->header.misc, sample->pid, sample->tid, sample->ip,
786 sample->period, sample->addr);
787
788 sample_type = evsel->attr.sample_type;
789
790 if (sample_type & PERF_SAMPLE_CALLCHAIN)
791 callchain__printf(sample);
792
793 if (sample_type & PERF_SAMPLE_BRANCH_STACK)
794 branch_stack__printf(sample);
795
796 if (sample_type & PERF_SAMPLE_REGS_USER)
797 regs_user__printf(sample, evsel->attr.sample_regs_user);
798
799 if (sample_type & PERF_SAMPLE_STACK_USER)
800 stack_user__printf(&sample->user_stack);
801
802 if (sample_type & PERF_SAMPLE_WEIGHT)
803 printf("... weight: %" PRIu64 "\n", sample->weight);
804
805 if (sample_type & PERF_SAMPLE_DATA_SRC)
806 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
807}
808
809static struct machine *
810 perf_session__find_machine_for_cpumode(struct perf_session *session,
811 union perf_event *event)
812{
813 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
814
815 if (perf_guest &&
816 ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
817 (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
818 u32 pid;
819
820 if (event->header.type == PERF_RECORD_MMAP)
821 pid = event->mmap.pid;
822 else
823 pid = event->ip.pid;
824
825 return perf_session__findnew_machine(session, pid);
826 }
827
828 return &session->machines.host;
829}
830
831static int perf_session_deliver_event(struct perf_session *session,
832 union perf_event *event,
833 struct perf_sample *sample,
834 struct perf_tool *tool,
835 u64 file_offset)
836{
837 struct perf_evsel *evsel;
838 struct machine *machine;
839
840 dump_event(session, event, file_offset, sample);
841
842 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
843 if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
844
845
846
847
848
849
850
851
852
853
854
855
856
857 hists__inc_nr_events(&evsel->hists, event->header.type);
858 }
859
860 machine = perf_session__find_machine_for_cpumode(session, event);
861
862 switch (event->header.type) {
863 case PERF_RECORD_SAMPLE:
864 dump_sample(evsel, event, sample);
865 if (evsel == NULL) {
866 ++session->stats.nr_unknown_id;
867 return 0;
868 }
869 if (machine == NULL) {
870 ++session->stats.nr_unprocessable_samples;
871 return 0;
872 }
873 return tool->sample(tool, event, sample, evsel, machine);
874 case PERF_RECORD_MMAP:
875 return tool->mmap(tool, event, sample, machine);
876 case PERF_RECORD_COMM:
877 return tool->comm(tool, event, sample, machine);
878 case PERF_RECORD_FORK:
879 return tool->fork(tool, event, sample, machine);
880 case PERF_RECORD_EXIT:
881 return tool->exit(tool, event, sample, machine);
882 case PERF_RECORD_LOST:
883 if (tool->lost == perf_event__process_lost)
884 session->stats.total_lost += event->lost.lost;
885 return tool->lost(tool, event, sample, machine);
886 case PERF_RECORD_READ:
887 return tool->read(tool, event, sample, evsel, machine);
888 case PERF_RECORD_THROTTLE:
889 return tool->throttle(tool, event, sample, machine);
890 case PERF_RECORD_UNTHROTTLE:
891 return tool->unthrottle(tool, event, sample, machine);
892 default:
893 ++session->stats.nr_unknown_events;
894 return -1;
895 }
896}
897
898static int perf_session__preprocess_sample(struct perf_session *session,
899 union perf_event *event, struct perf_sample *sample)
900{
901 if (event->header.type != PERF_RECORD_SAMPLE ||
902 !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN))
903 return 0;
904
905 if (!ip_callchain__valid(sample->callchain, event)) {
906 pr_debug("call-chain problem with event, skipping it.\n");
907 ++session->stats.nr_invalid_chains;
908 session->stats.total_invalid_chains += sample->period;
909 return -EINVAL;
910 }
911 return 0;
912}
913
914static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
915 struct perf_tool *tool, u64 file_offset)
916{
917 int err;
918
919 dump_event(session, event, file_offset, NULL);
920
921
922 switch (event->header.type) {
923 case PERF_RECORD_HEADER_ATTR:
924 err = tool->attr(event, &session->evlist);
925 if (err == 0)
926 perf_session__set_id_hdr_size(session);
927 return err;
928 case PERF_RECORD_HEADER_EVENT_TYPE:
929 return tool->event_type(tool, event);
930 case PERF_RECORD_HEADER_TRACING_DATA:
931
932 lseek(session->fd, file_offset, SEEK_SET);
933 return tool->tracing_data(event, session);
934 case PERF_RECORD_HEADER_BUILD_ID:
935 return tool->build_id(tool, event, session);
936 case PERF_RECORD_FINISHED_ROUND:
937 return tool->finished_round(tool, event, session);
938 default:
939 return -EINVAL;
940 }
941}
942
943static void event_swap(union perf_event *event, bool sample_id_all)
944{
945 perf_event__swap_op swap;
946
947 swap = perf_event__swap_ops[event->header.type];
948 if (swap)
949 swap(event, sample_id_all);
950}
951
952static int perf_session__process_event(struct perf_session *session,
953 union perf_event *event,
954 struct perf_tool *tool,
955 u64 file_offset)
956{
957 struct perf_sample sample;
958 int ret;
959
960 if (session->header.needs_swap)
961 event_swap(event, perf_evlist__sample_id_all(session->evlist));
962
963 if (event->header.type >= PERF_RECORD_HEADER_MAX)
964 return -EINVAL;
965
966 events_stats__inc(&session->stats, event->header.type);
967
968 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
969 return perf_session__process_user_event(session, event, tool, file_offset);
970
971
972
973
974 ret = perf_evlist__parse_sample(session->evlist, event, &sample);
975 if (ret)
976 return ret;
977
978
979 if (perf_session__preprocess_sample(session, event, &sample))
980 return 0;
981
982 if (tool->ordered_samples) {
983 ret = perf_session_queue_event(session, event, &sample,
984 file_offset);
985 if (ret != -ETIME)
986 return ret;
987 }
988
989 return perf_session_deliver_event(session, event, &sample, tool,
990 file_offset);
991}
992
993void perf_event_header__bswap(struct perf_event_header *self)
994{
995 self->type = bswap_32(self->type);
996 self->misc = bswap_16(self->misc);
997 self->size = bswap_16(self->size);
998}
999
1000struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1001{
1002 return machine__findnew_thread(&session->machines.host, pid);
1003}
1004
1005static struct thread *perf_session__register_idle_thread(struct perf_session *self)
1006{
1007 struct thread *thread = perf_session__findnew(self, 0);
1008
1009 if (thread == NULL || thread__set_comm(thread, "swapper")) {
1010 pr_err("problem inserting idle task.\n");
1011 thread = NULL;
1012 }
1013
1014 return thread;
1015}
1016
1017static void perf_session__warn_about_errors(const struct perf_session *session,
1018 const struct perf_tool *tool)
1019{
1020 if (tool->lost == perf_event__process_lost &&
1021 session->stats.nr_events[PERF_RECORD_LOST] != 0) {
1022 ui__warning("Processed %d events and lost %d chunks!\n\n"
1023 "Check IO/CPU overload!\n\n",
1024 session->stats.nr_events[0],
1025 session->stats.nr_events[PERF_RECORD_LOST]);
1026 }
1027
1028 if (session->stats.nr_unknown_events != 0) {
1029 ui__warning("Found %u unknown events!\n\n"
1030 "Is this an older tool processing a perf.data "
1031 "file generated by a more recent tool?\n\n"
1032 "If that is not the case, consider "
1033 "reporting to linux-kernel@vger.kernel.org.\n\n",
1034 session->stats.nr_unknown_events);
1035 }
1036
1037 if (session->stats.nr_unknown_id != 0) {
1038 ui__warning("%u samples with id not present in the header\n",
1039 session->stats.nr_unknown_id);
1040 }
1041
1042 if (session->stats.nr_invalid_chains != 0) {
1043 ui__warning("Found invalid callchains!\n\n"
1044 "%u out of %u events were discarded for this reason.\n\n"
1045 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
1046 session->stats.nr_invalid_chains,
1047 session->stats.nr_events[PERF_RECORD_SAMPLE]);
1048 }
1049
1050 if (session->stats.nr_unprocessable_samples != 0) {
1051 ui__warning("%u unprocessable samples recorded.\n"
1052 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1053 session->stats.nr_unprocessable_samples);
1054 }
1055}
1056
1057#define session_done() (*(volatile int *)(&session_done))
1058volatile int session_done;
1059
1060static int __perf_session__process_pipe_events(struct perf_session *self,
1061 struct perf_tool *tool)
1062{
1063 union perf_event *event;
1064 uint32_t size, cur_size = 0;
1065 void *buf = NULL;
1066 int skip = 0;
1067 u64 head;
1068 int err;
1069 void *p;
1070
1071 perf_tool__fill_defaults(tool);
1072
1073 head = 0;
1074 cur_size = sizeof(union perf_event);
1075
1076 buf = malloc(cur_size);
1077 if (!buf)
1078 return -errno;
1079more:
1080 event = buf;
1081 err = readn(self->fd, event, sizeof(struct perf_event_header));
1082 if (err <= 0) {
1083 if (err == 0)
1084 goto done;
1085
1086 pr_err("failed to read event header\n");
1087 goto out_err;
1088 }
1089
1090 if (self->header.needs_swap)
1091 perf_event_header__bswap(&event->header);
1092
1093 size = event->header.size;
1094 if (size == 0)
1095 size = 8;
1096
1097 if (size > cur_size) {
1098 void *new = realloc(buf, size);
1099 if (!new) {
1100 pr_err("failed to allocate memory to read event\n");
1101 goto out_err;
1102 }
1103 buf = new;
1104 cur_size = size;
1105 event = buf;
1106 }
1107 p = event;
1108 p += sizeof(struct perf_event_header);
1109
1110 if (size - sizeof(struct perf_event_header)) {
1111 err = readn(self->fd, p, size - sizeof(struct perf_event_header));
1112 if (err <= 0) {
1113 if (err == 0) {
1114 pr_err("unexpected end of event stream\n");
1115 goto done;
1116 }
1117
1118 pr_err("failed to read event data\n");
1119 goto out_err;
1120 }
1121 }
1122
1123 if ((skip = perf_session__process_event(self, event, tool, head)) < 0) {
1124 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1125 head, event->header.size, event->header.type);
1126 err = -EINVAL;
1127 goto out_err;
1128 }
1129
1130 head += size;
1131
1132 if (skip > 0)
1133 head += skip;
1134
1135 if (!session_done())
1136 goto more;
1137done:
1138 err = 0;
1139out_err:
1140 free(buf);
1141 perf_session__warn_about_errors(self, tool);
1142 perf_session_free_sample_buffers(self);
1143 return err;
1144}
1145
1146static union perf_event *
1147fetch_mmaped_event(struct perf_session *session,
1148 u64 head, size_t mmap_size, char *buf)
1149{
1150 union perf_event *event;
1151
1152
1153
1154
1155
1156 if (head + sizeof(event->header) > mmap_size)
1157 return NULL;
1158
1159 event = (union perf_event *)(buf + head);
1160
1161 if (session->header.needs_swap)
1162 perf_event_header__bswap(&event->header);
1163
1164 if (head + event->header.size > mmap_size)
1165 return NULL;
1166
1167 return event;
1168}
1169
1170
1171
1172
1173
1174#if BITS_PER_LONG == 64
1175#define MMAP_SIZE ULLONG_MAX
1176#define NUM_MMAPS 1
1177#else
1178#define MMAP_SIZE (32 * 1024 * 1024ULL)
1179#define NUM_MMAPS 128
1180#endif
1181
1182int __perf_session__process_events(struct perf_session *session,
1183 u64 data_offset, u64 data_size,
1184 u64 file_size, struct perf_tool *tool)
1185{
1186 u64 head, page_offset, file_offset, file_pos, progress_next;
1187 int err, mmap_prot, mmap_flags, map_idx = 0;
1188 size_t mmap_size;
1189 char *buf, *mmaps[NUM_MMAPS];
1190 union perf_event *event;
1191 uint32_t size;
1192
1193 perf_tool__fill_defaults(tool);
1194
1195 page_offset = page_size * (data_offset / page_size);
1196 file_offset = page_offset;
1197 head = data_offset - page_offset;
1198
1199 if (data_offset + data_size < file_size)
1200 file_size = data_offset + data_size;
1201
1202 progress_next = file_size / 16;
1203
1204 mmap_size = MMAP_SIZE;
1205 if (mmap_size > file_size)
1206 mmap_size = file_size;
1207
1208 memset(mmaps, 0, sizeof(mmaps));
1209
1210 mmap_prot = PROT_READ;
1211 mmap_flags = MAP_SHARED;
1212
1213 if (session->header.needs_swap) {
1214 mmap_prot |= PROT_WRITE;
1215 mmap_flags = MAP_PRIVATE;
1216 }
1217remap:
1218 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
1219 file_offset);
1220 if (buf == MAP_FAILED) {
1221 pr_err("failed to mmap file\n");
1222 err = -errno;
1223 goto out_err;
1224 }
1225 mmaps[map_idx] = buf;
1226 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
1227 file_pos = file_offset + head;
1228
1229more:
1230 event = fetch_mmaped_event(session, head, mmap_size, buf);
1231 if (!event) {
1232 if (mmaps[map_idx]) {
1233 munmap(mmaps[map_idx], mmap_size);
1234 mmaps[map_idx] = NULL;
1235 }
1236
1237 page_offset = page_size * (head / page_size);
1238 file_offset += page_offset;
1239 head -= page_offset;
1240 goto remap;
1241 }
1242
1243 size = event->header.size;
1244
1245 if (size == 0 ||
1246 perf_session__process_event(session, event, tool, file_pos) < 0) {
1247 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1248 file_offset + head, event->header.size,
1249 event->header.type);
1250 err = -EINVAL;
1251 goto out_err;
1252 }
1253
1254 head += size;
1255 file_pos += size;
1256
1257 if (file_pos >= progress_next) {
1258 progress_next += file_size / 16;
1259 ui_progress__update(file_pos, file_size,
1260 "Processing events...");
1261 }
1262
1263 if (file_pos < file_size)
1264 goto more;
1265
1266 err = 0;
1267
1268 session->ordered_samples.next_flush = ULLONG_MAX;
1269 err = flush_sample_queue(session, tool);
1270out_err:
1271 ui_progress__finish();
1272 perf_session__warn_about_errors(session, tool);
1273 perf_session_free_sample_buffers(session);
1274 return err;
1275}
1276
1277int perf_session__process_events(struct perf_session *self,
1278 struct perf_tool *tool)
1279{
1280 int err;
1281
1282 if (perf_session__register_idle_thread(self) == NULL)
1283 return -ENOMEM;
1284
1285 if (!self->fd_pipe)
1286 err = __perf_session__process_events(self,
1287 self->header.data_offset,
1288 self->header.data_size,
1289 self->size, tool);
1290 else
1291 err = __perf_session__process_pipe_events(self, tool);
1292
1293 return err;
1294}
1295
1296bool perf_session__has_traces(struct perf_session *session, const char *msg)
1297{
1298 if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) {
1299 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
1300 return false;
1301 }
1302
1303 return true;
1304}
1305
1306int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1307 const char *symbol_name, u64 addr)
1308{
1309 char *bracket;
1310 enum map_type i;
1311 struct ref_reloc_sym *ref;
1312
1313 ref = zalloc(sizeof(struct ref_reloc_sym));
1314 if (ref == NULL)
1315 return -ENOMEM;
1316
1317 ref->name = strdup(symbol_name);
1318 if (ref->name == NULL) {
1319 free(ref);
1320 return -ENOMEM;
1321 }
1322
1323 bracket = strchr(ref->name, ']');
1324 if (bracket)
1325 *bracket = '\0';
1326
1327 ref->addr = addr;
1328
1329 for (i = 0; i < MAP__NR_TYPES; ++i) {
1330 struct kmap *kmap = map__kmap(maps[i]);
1331 kmap->ref_reloc_sym = ref;
1332 }
1333
1334 return 0;
1335}
1336
1337size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
1338{
1339 return machines__fprintf_dsos(&self->machines, fp);
1340}
1341
1342size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
1343 bool (skip)(struct dso *dso, int parm), int parm)
1344{
1345 return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
1346}
1347
1348size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1349{
1350 struct perf_evsel *pos;
1351 size_t ret = fprintf(fp, "Aggregated stats:\n");
1352
1353 ret += events_stats__fprintf(&session->stats, fp);
1354
1355 list_for_each_entry(pos, &session->evlist->entries, node) {
1356 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1357 ret += events_stats__fprintf(&pos->hists.stats, fp);
1358 }
1359
1360 return ret;
1361}
1362
1363size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
1364{
1365
1366
1367
1368
1369 return machine__fprintf(&session->machines.host, fp);
1370}
1371
1372struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1373 unsigned int type)
1374{
1375 struct perf_evsel *pos;
1376
1377 list_for_each_entry(pos, &session->evlist->entries, node) {
1378 if (pos->attr.type == type)
1379 return pos;
1380 }
1381 return NULL;
1382}
1383
1384void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1385 struct perf_sample *sample, struct machine *machine,
1386 int print_sym, int print_dso, int print_symoffset)
1387{
1388 struct addr_location al;
1389 struct callchain_cursor_node *node;
1390
1391 if (perf_event__preprocess_sample(event, machine, &al, sample,
1392 NULL) < 0) {
1393 error("problem processing %d event, skipping it.\n",
1394 event->header.type);
1395 return;
1396 }
1397
1398 if (symbol_conf.use_callchain && sample->callchain) {
1399
1400
1401 if (machine__resolve_callchain(machine, evsel, al.thread,
1402 sample, NULL) != 0) {
1403 if (verbose)
1404 error("Failed to resolve callchain. Skipping\n");
1405 return;
1406 }
1407 callchain_cursor_commit(&callchain_cursor);
1408
1409 while (1) {
1410 node = callchain_cursor_current(&callchain_cursor);
1411 if (!node)
1412 break;
1413
1414 printf("\t%16" PRIx64, node->ip);
1415 if (print_sym) {
1416 printf(" ");
1417 symbol__fprintf_symname(node->sym, stdout);
1418 }
1419 if (print_dso) {
1420 printf(" (");
1421 map__fprintf_dsoname(node->map, stdout);
1422 printf(")");
1423 }
1424 printf("\n");
1425
1426 callchain_cursor_advance(&callchain_cursor);
1427 }
1428
1429 } else {
1430 printf("%16" PRIx64, sample->ip);
1431 if (print_sym) {
1432 printf(" ");
1433 if (print_symoffset)
1434 symbol__fprintf_symname_offs(al.sym, &al,
1435 stdout);
1436 else
1437 symbol__fprintf_symname(al.sym, stdout);
1438 }
1439
1440 if (print_dso) {
1441 printf(" (");
1442 map__fprintf_dsoname(al.map, stdout);
1443 printf(")");
1444 }
1445 }
1446}
1447
1448int perf_session__cpu_bitmap(struct perf_session *session,
1449 const char *cpu_list, unsigned long *cpu_bitmap)
1450{
1451 int i;
1452 struct cpu_map *map;
1453
1454 for (i = 0; i < PERF_TYPE_MAX; ++i) {
1455 struct perf_evsel *evsel;
1456
1457 evsel = perf_session__find_first_evtype(session, i);
1458 if (!evsel)
1459 continue;
1460
1461 if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
1462 pr_err("File does not contain CPU events. "
1463 "Remove -c option to proceed.\n");
1464 return -1;
1465 }
1466 }
1467
1468 map = cpu_map__new(cpu_list);
1469 if (map == NULL) {
1470 pr_err("Invalid cpu_list\n");
1471 return -1;
1472 }
1473
1474 for (i = 0; i < map->nr; i++) {
1475 int cpu = map->map[i];
1476
1477 if (cpu >= MAX_NR_CPUS) {
1478 pr_err("Requested CPU %d too large. "
1479 "Consider raising MAX_NR_CPUS\n", cpu);
1480 return -1;
1481 }
1482
1483 set_bit(cpu, cpu_bitmap);
1484 }
1485
1486 return 0;
1487}
1488
1489void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1490 bool full)
1491{
1492 struct stat st;
1493 int ret;
1494
1495 if (session == NULL || fp == NULL)
1496 return;
1497
1498 ret = fstat(session->fd, &st);
1499 if (ret == -1)
1500 return;
1501
1502 fprintf(fp, "# ========\n");
1503 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
1504 perf_header__fprintf_info(session, fp, full);
1505 fprintf(fp, "# ========\n#\n");
1506}
1507
1508
1509int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1510 const struct perf_evsel_str_handler *assocs,
1511 size_t nr_assocs)
1512{
1513 struct perf_evlist *evlist = session->evlist;
1514 struct event_format *format;
1515 struct perf_evsel *evsel;
1516 char *tracepoint, *name;
1517 size_t i;
1518 int err;
1519
1520 for (i = 0; i < nr_assocs; i++) {
1521 err = -ENOMEM;
1522 tracepoint = strdup(assocs[i].name);
1523 if (tracepoint == NULL)
1524 goto out;
1525
1526 err = -ENOENT;
1527 name = strchr(tracepoint, ':');
1528 if (name == NULL)
1529 goto out_free;
1530
1531 *name++ = '\0';
1532 format = pevent_find_event_by_name(session->pevent,
1533 tracepoint, name);
1534 if (format == NULL) {
1535
1536
1537
1538
1539 goto next;
1540 }
1541
1542 evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
1543 if (evsel == NULL)
1544 goto next;
1545
1546 err = -EEXIST;
1547 if (evsel->handler.func != NULL)
1548 goto out_free;
1549 evsel->handler.func = assocs[i].handler;
1550next:
1551 free(tracepoint);
1552 }
1553
1554 err = 0;
1555out:
1556 return err;
1557
1558out_free:
1559 free(tracepoint);
1560 goto out;
1561}
1562