]> Pileus Git - ~andy/linux/blob - tools/perf/util/header.c
perf session: Use evlist/evsel for managing perf.data attributes
[~andy/linux] / tools / perf / util / header.c
1 #define _FILE_OFFSET_BITS 64
2
3 #include <sys/types.h>
4 #include <byteswap.h>
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <linux/list.h>
9 #include <linux/kernel.h>
10
11 #include "evlist.h"
12 #include "evsel.h"
13 #include "util.h"
14 #include "header.h"
15 #include "../perf.h"
16 #include "trace-event.h"
17 #include "session.h"
18 #include "symbol.h"
19 #include "debug.h"
20
21 static bool no_buildid_cache = false;
22
23 static int event_count;
24 static struct perf_trace_event_type *events;
25
26 int perf_header__push_event(u64 id, const char *name)
27 {
28         if (strlen(name) > MAX_EVENT_NAME)
29                 pr_warning("Event %s will be truncated\n", name);
30
31         if (!events) {
32                 events = malloc(sizeof(struct perf_trace_event_type));
33                 if (events == NULL)
34                         return -ENOMEM;
35         } else {
36                 struct perf_trace_event_type *nevents;
37
38                 nevents = realloc(events, (event_count + 1) * sizeof(*events));
39                 if (nevents == NULL)
40                         return -ENOMEM;
41                 events = nevents;
42         }
43         memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
44         events[event_count].event_id = id;
45         strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
46         event_count++;
47         return 0;
48 }
49
50 char *perf_header__find_event(u64 id)
51 {
52         int i;
53         for (i = 0 ; i < event_count; i++) {
54                 if (events[i].event_id == id)
55                         return events[i].name;
56         }
57         return NULL;
58 }
59
60 static const char *__perf_magic = "PERFFILE";
61
62 #define PERF_MAGIC      (*(u64 *)__perf_magic)
63
64 struct perf_file_attr {
65         struct perf_event_attr  attr;
66         struct perf_file_section        ids;
67 };
68
69 void perf_header__set_feat(struct perf_header *self, int feat)
70 {
71         set_bit(feat, self->adds_features);
72 }
73
74 void perf_header__clear_feat(struct perf_header *self, int feat)
75 {
76         clear_bit(feat, self->adds_features);
77 }
78
79 bool perf_header__has_feat(const struct perf_header *self, int feat)
80 {
81         return test_bit(feat, self->adds_features);
82 }
83
84 static int do_write(int fd, const void *buf, size_t size)
85 {
86         while (size) {
87                 int ret = write(fd, buf, size);
88
89                 if (ret < 0)
90                         return -errno;
91
92                 size -= ret;
93                 buf += ret;
94         }
95
96         return 0;
97 }
98
99 #define NAME_ALIGN 64
100
101 static int write_padded(int fd, const void *bf, size_t count,
102                         size_t count_aligned)
103 {
104         static const char zero_buf[NAME_ALIGN];
105         int err = do_write(fd, bf, count);
106
107         if (!err)
108                 err = do_write(fd, zero_buf, count_aligned - count);
109
110         return err;
111 }
112
113 #define dsos__for_each_with_build_id(pos, head) \
114         list_for_each_entry(pos, head, node)    \
115                 if (!pos->has_build_id)         \
116                         continue;               \
117                 else
118
119 static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
120                                 u16 misc, int fd)
121 {
122         struct dso *pos;
123
124         dsos__for_each_with_build_id(pos, head) {
125                 int err;
126                 struct build_id_event b;
127                 size_t len;
128
129                 if (!pos->hit)
130                         continue;
131                 len = pos->long_name_len + 1;
132                 len = ALIGN(len, NAME_ALIGN);
133                 memset(&b, 0, sizeof(b));
134                 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
135                 b.pid = pid;
136                 b.header.misc = misc;
137                 b.header.size = sizeof(b) + len;
138                 err = do_write(fd, &b, sizeof(b));
139                 if (err < 0)
140                         return err;
141                 err = write_padded(fd, pos->long_name,
142                                    pos->long_name_len + 1, len);
143                 if (err < 0)
144                         return err;
145         }
146
147         return 0;
148 }
149
150 static int machine__write_buildid_table(struct machine *self, int fd)
151 {
152         int err;
153         u16 kmisc = PERF_RECORD_MISC_KERNEL,
154             umisc = PERF_RECORD_MISC_USER;
155
156         if (!machine__is_host(self)) {
157                 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
158                 umisc = PERF_RECORD_MISC_GUEST_USER;
159         }
160
161         err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid,
162                                           kmisc, fd);
163         if (err == 0)
164                 err = __dsos__write_buildid_table(&self->user_dsos,
165                                                   self->pid, umisc, fd);
166         return err;
167 }
168
169 static int dsos__write_buildid_table(struct perf_header *header, int fd)
170 {
171         struct perf_session *session = container_of(header,
172                         struct perf_session, header);
173         struct rb_node *nd;
174         int err = machine__write_buildid_table(&session->host_machine, fd);
175
176         if (err)
177                 return err;
178
179         for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
180                 struct machine *pos = rb_entry(nd, struct machine, rb_node);
181                 err = machine__write_buildid_table(pos, fd);
182                 if (err)
183                         break;
184         }
185         return err;
186 }
187
188 int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
189                           const char *name, bool is_kallsyms)
190 {
191         const size_t size = PATH_MAX;
192         char *realname = realpath(name, NULL),
193              *filename = malloc(size),
194              *linkname = malloc(size), *targetname;
195         int len, err = -1;
196
197         if (realname == NULL || filename == NULL || linkname == NULL)
198                 goto out_free;
199
200         len = snprintf(filename, size, "%s%s%s",
201                        debugdir, is_kallsyms ? "/" : "", realname);
202         if (mkdir_p(filename, 0755))
203                 goto out_free;
204
205         snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
206
207         if (access(filename, F_OK)) {
208                 if (is_kallsyms) {
209                          if (copyfile("/proc/kallsyms", filename))
210                                 goto out_free;
211                 } else if (link(realname, filename) && copyfile(name, filename))
212                         goto out_free;
213         }
214
215         len = snprintf(linkname, size, "%s/.build-id/%.2s",
216                        debugdir, sbuild_id);
217
218         if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
219                 goto out_free;
220
221         snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
222         targetname = filename + strlen(debugdir) - 5;
223         memcpy(targetname, "../..", 5);
224
225         if (symlink(targetname, linkname) == 0)
226                 err = 0;
227 out_free:
228         free(realname);
229         free(filename);
230         free(linkname);
231         return err;
232 }
233
234 static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
235                                  const char *name, const char *debugdir,
236                                  bool is_kallsyms)
237 {
238         char sbuild_id[BUILD_ID_SIZE * 2 + 1];
239
240         build_id__sprintf(build_id, build_id_size, sbuild_id);
241
242         return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
243 }
244
245 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
246 {
247         const size_t size = PATH_MAX;
248         char *filename = malloc(size),
249              *linkname = malloc(size);
250         int err = -1;
251
252         if (filename == NULL || linkname == NULL)
253                 goto out_free;
254
255         snprintf(linkname, size, "%s/.build-id/%.2s/%s",
256                  debugdir, sbuild_id, sbuild_id + 2);
257
258         if (access(linkname, F_OK))
259                 goto out_free;
260
261         if (readlink(linkname, filename, size) < 0)
262                 goto out_free;
263
264         if (unlink(linkname))
265                 goto out_free;
266
267         /*
268          * Since the link is relative, we must make it absolute:
269          */
270         snprintf(linkname, size, "%s/.build-id/%.2s/%s",
271                  debugdir, sbuild_id, filename);
272
273         if (unlink(linkname))
274                 goto out_free;
275
276         err = 0;
277 out_free:
278         free(filename);
279         free(linkname);
280         return err;
281 }
282
283 static int dso__cache_build_id(struct dso *self, const char *debugdir)
284 {
285         bool is_kallsyms = self->kernel && self->long_name[0] != '/';
286
287         return build_id_cache__add_b(self->build_id, sizeof(self->build_id),
288                                      self->long_name, debugdir, is_kallsyms);
289 }
290
291 static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
292 {
293         struct dso *pos;
294         int err = 0;
295
296         dsos__for_each_with_build_id(pos, head)
297                 if (dso__cache_build_id(pos, debugdir))
298                         err = -1;
299
300         return err;
301 }
302
303 static int machine__cache_build_ids(struct machine *self, const char *debugdir)
304 {
305         int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir);
306         ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir);
307         return ret;
308 }
309
310 static int perf_session__cache_build_ids(struct perf_session *self)
311 {
312         struct rb_node *nd;
313         int ret;
314         char debugdir[PATH_MAX];
315
316         snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
317
318         if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
319                 return -1;
320
321         ret = machine__cache_build_ids(&self->host_machine, debugdir);
322
323         for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) {
324                 struct machine *pos = rb_entry(nd, struct machine, rb_node);
325                 ret |= machine__cache_build_ids(pos, debugdir);
326         }
327         return ret ? -1 : 0;
328 }
329
330 static bool machine__read_build_ids(struct machine *self, bool with_hits)
331 {
332         bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits);
333         ret |= __dsos__read_build_ids(&self->user_dsos, with_hits);
334         return ret;
335 }
336
337 static bool perf_session__read_build_ids(struct perf_session *self, bool with_hits)
338 {
339         struct rb_node *nd;
340         bool ret = machine__read_build_ids(&self->host_machine, with_hits);
341
342         for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) {
343                 struct machine *pos = rb_entry(nd, struct machine, rb_node);
344                 ret |= machine__read_build_ids(pos, with_hits);
345         }
346
347         return ret;
348 }
349
350 static int perf_header__adds_write(struct perf_header *self,
351                                    struct perf_evlist *evlist, int fd)
352 {
353         int nr_sections;
354         struct perf_session *session;
355         struct perf_file_section *feat_sec;
356         int sec_size;
357         u64 sec_start;
358         int idx = 0, err;
359
360         session = container_of(self, struct perf_session, header);
361
362         if (perf_header__has_feat(self, HEADER_BUILD_ID &&
363             !perf_session__read_build_ids(session, true)))
364                 perf_header__clear_feat(self, HEADER_BUILD_ID);
365
366         nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
367         if (!nr_sections)
368                 return 0;
369
370         feat_sec = calloc(sizeof(*feat_sec), nr_sections);
371         if (feat_sec == NULL)
372                 return -ENOMEM;
373
374         sec_size = sizeof(*feat_sec) * nr_sections;
375
376         sec_start = self->data_offset + self->data_size;
377         lseek(fd, sec_start + sec_size, SEEK_SET);
378
379         if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
380                 struct perf_file_section *trace_sec;
381
382                 trace_sec = &feat_sec[idx++];
383
384                 /* Write trace info */
385                 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
386                 read_tracing_data(fd, &evlist->entries);
387                 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
388         }
389
390         if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
391                 struct perf_file_section *buildid_sec;
392
393                 buildid_sec = &feat_sec[idx++];
394
395                 /* Write build-ids */
396                 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
397                 err = dsos__write_buildid_table(self, fd);
398                 if (err < 0) {
399                         pr_debug("failed to write buildid table\n");
400                         goto out_free;
401                 }
402                 buildid_sec->size = lseek(fd, 0, SEEK_CUR) -
403                                           buildid_sec->offset;
404                 if (!no_buildid_cache)
405                         perf_session__cache_build_ids(session);
406         }
407
408         lseek(fd, sec_start, SEEK_SET);
409         err = do_write(fd, feat_sec, sec_size);
410         if (err < 0)
411                 pr_debug("failed to write feature section\n");
412 out_free:
413         free(feat_sec);
414         return err;
415 }
416
417 int perf_header__write_pipe(int fd)
418 {
419         struct perf_pipe_file_header f_header;
420         int err;
421
422         f_header = (struct perf_pipe_file_header){
423                 .magic     = PERF_MAGIC,
424                 .size      = sizeof(f_header),
425         };
426
427         err = do_write(fd, &f_header, sizeof(f_header));
428         if (err < 0) {
429                 pr_debug("failed to write perf pipe header\n");
430                 return err;
431         }
432
433         return 0;
434 }
435
436 int perf_session__write_header(struct perf_session *session,
437                                struct perf_evlist *evlist,
438                                int fd, bool at_exit)
439 {
440         struct perf_file_header f_header;
441         struct perf_file_attr   f_attr;
442         struct perf_header *self = &session->header;
443         struct perf_evsel *attr, *pair = NULL;
444         int err;
445
446         lseek(fd, sizeof(f_header), SEEK_SET);
447
448         if (session->evlist != evlist)
449                 pair = list_entry(session->evlist->entries.next, struct perf_evsel, node);
450
451         list_for_each_entry(attr, &evlist->entries, node) {
452                 attr->id_offset = lseek(fd, 0, SEEK_CUR);
453                 err = do_write(fd, attr->id, attr->ids * sizeof(u64));
454                 if (err < 0) {
455 out_err_write:
456                         pr_debug("failed to write perf header\n");
457                         return err;
458                 }
459                 if (session->evlist != evlist) {
460                         err = do_write(fd, pair->id, pair->ids * sizeof(u64));
461                         if (err < 0)
462                                 goto out_err_write;
463                         attr->ids += pair->ids;
464                         pair = list_entry(pair->node.next, struct perf_evsel, node);
465                 }
466         }
467
468         self->attr_offset = lseek(fd, 0, SEEK_CUR);
469
470         list_for_each_entry(attr, &evlist->entries, node) {
471                 f_attr = (struct perf_file_attr){
472                         .attr = attr->attr,
473                         .ids  = {
474                                 .offset = attr->id_offset,
475                                 .size   = attr->ids * sizeof(u64),
476                         }
477                 };
478                 err = do_write(fd, &f_attr, sizeof(f_attr));
479                 if (err < 0) {
480                         pr_debug("failed to write perf header attribute\n");
481                         return err;
482                 }
483         }
484
485         self->event_offset = lseek(fd, 0, SEEK_CUR);
486         self->event_size = event_count * sizeof(struct perf_trace_event_type);
487         if (events) {
488                 err = do_write(fd, events, self->event_size);
489                 if (err < 0) {
490                         pr_debug("failed to write perf header events\n");
491                         return err;
492                 }
493         }
494
495         self->data_offset = lseek(fd, 0, SEEK_CUR);
496
497         if (at_exit) {
498                 err = perf_header__adds_write(self, evlist, fd);
499                 if (err < 0)
500                         return err;
501         }
502
503         f_header = (struct perf_file_header){
504                 .magic     = PERF_MAGIC,
505                 .size      = sizeof(f_header),
506                 .attr_size = sizeof(f_attr),
507                 .attrs = {
508                         .offset = self->attr_offset,
509                         .size   = evlist->nr_entries * sizeof(f_attr),
510                 },
511                 .data = {
512                         .offset = self->data_offset,
513                         .size   = self->data_size,
514                 },
515                 .event_types = {
516                         .offset = self->event_offset,
517                         .size   = self->event_size,
518                 },
519         };
520
521         memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
522
523         lseek(fd, 0, SEEK_SET);
524         err = do_write(fd, &f_header, sizeof(f_header));
525         if (err < 0) {
526                 pr_debug("failed to write perf header\n");
527                 return err;
528         }
529         lseek(fd, self->data_offset + self->data_size, SEEK_SET);
530
531         self->frozen = 1;
532         return 0;
533 }
534
535 static int perf_header__getbuffer64(struct perf_header *self,
536                                     int fd, void *buf, size_t size)
537 {
538         if (readn(fd, buf, size) <= 0)
539                 return -1;
540
541         if (self->needs_swap)
542                 mem_bswap_64(buf, size);
543
544         return 0;
545 }
546
547 int perf_header__process_sections(struct perf_header *self, int fd,
548                                   int (*process)(struct perf_file_section *self,
549                                                  struct perf_header *ph,
550                                                  int feat, int fd))
551 {
552         struct perf_file_section *feat_sec;
553         int nr_sections;
554         int sec_size;
555         int idx = 0;
556         int err = -1, feat = 1;
557
558         nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
559         if (!nr_sections)
560                 return 0;
561
562         feat_sec = calloc(sizeof(*feat_sec), nr_sections);
563         if (!feat_sec)
564                 return -1;
565
566         sec_size = sizeof(*feat_sec) * nr_sections;
567
568         lseek(fd, self->data_offset + self->data_size, SEEK_SET);
569
570         if (perf_header__getbuffer64(self, fd, feat_sec, sec_size))
571                 goto out_free;
572
573         err = 0;
574         while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
575                 if (perf_header__has_feat(self, feat)) {
576                         struct perf_file_section *sec = &feat_sec[idx++];
577
578                         err = process(sec, self, feat, fd);
579                         if (err < 0)
580                                 break;
581                 }
582                 ++feat;
583         }
584 out_free:
585         free(feat_sec);
586         return err;
587 }
588
589 int perf_file_header__read(struct perf_file_header *self,
590                            struct perf_header *ph, int fd)
591 {
592         lseek(fd, 0, SEEK_SET);
593
594         if (readn(fd, self, sizeof(*self)) <= 0 ||
595             memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
596                 return -1;
597
598         if (self->attr_size != sizeof(struct perf_file_attr)) {
599                 u64 attr_size = bswap_64(self->attr_size);
600
601                 if (attr_size != sizeof(struct perf_file_attr))
602                         return -1;
603
604                 mem_bswap_64(self, offsetof(struct perf_file_header,
605                                             adds_features));
606                 ph->needs_swap = true;
607         }
608
609         if (self->size != sizeof(*self)) {
610                 /* Support the previous format */
611                 if (self->size == offsetof(typeof(*self), adds_features))
612                         bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
613                 else
614                         return -1;
615         }
616
617         memcpy(&ph->adds_features, &self->adds_features,
618                sizeof(ph->adds_features));
619         /*
620          * FIXME: hack that assumes that if we need swap the perf.data file
621          * may be coming from an arch with a different word-size, ergo different
622          * DEFINE_BITMAP format, investigate more later, but for now its mostly
623          * safe to assume that we have a build-id section. Trace files probably
624          * have several other issues in this realm anyway...
625          */
626         if (ph->needs_swap) {
627                 memset(&ph->adds_features, 0, sizeof(ph->adds_features));
628                 perf_header__set_feat(ph, HEADER_BUILD_ID);
629         }
630
631         ph->event_offset = self->event_types.offset;
632         ph->event_size   = self->event_types.size;
633         ph->data_offset  = self->data.offset;
634         ph->data_size    = self->data.size;
635         return 0;
636 }
637
638 static int __event_process_build_id(struct build_id_event *bev,
639                                     char *filename,
640                                     struct perf_session *session)
641 {
642         int err = -1;
643         struct list_head *head;
644         struct machine *machine;
645         u16 misc;
646         struct dso *dso;
647         enum dso_kernel_type dso_type;
648
649         machine = perf_session__findnew_machine(session, bev->pid);
650         if (!machine)
651                 goto out;
652
653         misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
654
655         switch (misc) {
656         case PERF_RECORD_MISC_KERNEL:
657                 dso_type = DSO_TYPE_KERNEL;
658                 head = &machine->kernel_dsos;
659                 break;
660         case PERF_RECORD_MISC_GUEST_KERNEL:
661                 dso_type = DSO_TYPE_GUEST_KERNEL;
662                 head = &machine->kernel_dsos;
663                 break;
664         case PERF_RECORD_MISC_USER:
665         case PERF_RECORD_MISC_GUEST_USER:
666                 dso_type = DSO_TYPE_USER;
667                 head = &machine->user_dsos;
668                 break;
669         default:
670                 goto out;
671         }
672
673         dso = __dsos__findnew(head, filename);
674         if (dso != NULL) {
675                 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
676
677                 dso__set_build_id(dso, &bev->build_id);
678
679                 if (filename[0] == '[')
680                         dso->kernel = dso_type;
681
682                 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
683                                   sbuild_id);
684                 pr_debug("build id event received for %s: %s\n",
685                          dso->long_name, sbuild_id);
686         }
687
688         err = 0;
689 out:
690         return err;
691 }
692
693 static int perf_header__read_build_ids(struct perf_header *self,
694                         int input, u64 offset, u64 size)
695 {
696         struct perf_session *session = container_of(self,
697                         struct perf_session, header);
698         struct build_id_event bev;
699         char filename[PATH_MAX];
700         u64 limit = offset + size;
701         int err = -1;
702
703         while (offset < limit) {
704                 ssize_t len;
705
706                 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
707                         goto out;
708
709                 if (self->needs_swap)
710                         perf_event_header__bswap(&bev.header);
711
712                 len = bev.header.size - sizeof(bev);
713                 if (read(input, filename, len) != len)
714                         goto out;
715
716                 __event_process_build_id(&bev, filename, session);
717
718                 offset += bev.header.size;
719         }
720         err = 0;
721 out:
722         return err;
723 }
724
725 static int perf_file_section__process(struct perf_file_section *self,
726                                       struct perf_header *ph,
727                                       int feat, int fd)
728 {
729         if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) {
730                 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
731                           "%d, continuing...\n", self->offset, feat);
732                 return 0;
733         }
734
735         switch (feat) {
736         case HEADER_TRACE_INFO:
737                 trace_report(fd, false);
738                 break;
739
740         case HEADER_BUILD_ID:
741                 if (perf_header__read_build_ids(ph, fd, self->offset, self->size))
742                         pr_debug("Failed to read buildids, continuing...\n");
743                 break;
744         default:
745                 pr_debug("unknown feature %d, continuing...\n", feat);
746         }
747
748         return 0;
749 }
750
751 static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
752                                        struct perf_header *ph, int fd,
753                                        bool repipe)
754 {
755         if (readn(fd, self, sizeof(*self)) <= 0 ||
756             memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
757                 return -1;
758
759         if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0)
760                 return -1;
761
762         if (self->size != sizeof(*self)) {
763                 u64 size = bswap_64(self->size);
764
765                 if (size != sizeof(*self))
766                         return -1;
767
768                 ph->needs_swap = true;
769         }
770
771         return 0;
772 }
773
774 static int perf_header__read_pipe(struct perf_session *session, int fd)
775 {
776         struct perf_header *self = &session->header;
777         struct perf_pipe_file_header f_header;
778
779         if (perf_file_header__read_pipe(&f_header, self, fd,
780                                         session->repipe) < 0) {
781                 pr_debug("incompatible file format\n");
782                 return -EINVAL;
783         }
784
785         session->fd = fd;
786
787         return 0;
788 }
789
790 int perf_session__read_header(struct perf_session *session, int fd)
791 {
792         struct perf_header *self = &session->header;
793         struct perf_file_header f_header;
794         struct perf_file_attr   f_attr;
795         u64                     f_id;
796         int nr_attrs, nr_ids, i, j;
797
798         session->evlist = perf_evlist__new(NULL, NULL);
799         if (session->evlist == NULL)
800                 return -ENOMEM;
801
802         if (session->fd_pipe)
803                 return perf_header__read_pipe(session, fd);
804
805         if (perf_file_header__read(&f_header, self, fd) < 0) {
806                 pr_debug("incompatible file format\n");
807                 return -EINVAL;
808         }
809
810         nr_attrs = f_header.attrs.size / sizeof(f_attr);
811         lseek(fd, f_header.attrs.offset, SEEK_SET);
812
813         for (i = 0; i < nr_attrs; i++) {
814                 struct perf_evsel *evsel;
815                 off_t tmp;
816
817                 if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr)))
818                         goto out_errno;
819
820                 tmp = lseek(fd, 0, SEEK_CUR);
821                 evsel = perf_evsel__new(&f_attr.attr, i);
822
823                 if (evsel == NULL)
824                         goto out_delete_evlist;
825                 /*
826                  * Do it before so that if perf_evsel__alloc_id fails, this
827                  * entry gets purged too at perf_evlist__delete().
828                  */
829                 perf_evlist__add(session->evlist, evsel);
830
831                 nr_ids = f_attr.ids.size / sizeof(u64);
832                 /*
833                  * We don't have the cpu and thread maps on the header, so
834                  * for allocating the perf_sample_id table we fake 1 cpu and
835                  * hattr->ids threads.
836                  */
837                 if (perf_evsel__alloc_id(evsel, 1, nr_ids))
838                         goto out_delete_evlist;
839
840                 lseek(fd, f_attr.ids.offset, SEEK_SET);
841
842                 for (j = 0; j < nr_ids; j++) {
843                         if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id)))
844                                 goto out_errno;
845
846                         perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
847                 }
848
849                 lseek(fd, tmp, SEEK_SET);
850         }
851
852         if (f_header.event_types.size) {
853                 lseek(fd, f_header.event_types.offset, SEEK_SET);
854                 events = malloc(f_header.event_types.size);
855                 if (events == NULL)
856                         return -ENOMEM;
857                 if (perf_header__getbuffer64(self, fd, events,
858                                              f_header.event_types.size))
859                         goto out_errno;
860                 event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
861         }
862
863         perf_header__process_sections(self, fd, perf_file_section__process);
864
865         lseek(fd, self->data_offset, SEEK_SET);
866
867         self->frozen = 1;
868         return 0;
869 out_errno:
870         return -errno;
871
872 out_delete_evlist:
873         perf_evlist__delete(session->evlist);
874         session->evlist = NULL;
875         return -ENOMEM;
876 }
877
878 u64 perf_evlist__sample_type(struct perf_evlist *evlist)
879 {
880         struct perf_evsel *pos;
881         u64 type = 0;
882
883         list_for_each_entry(pos, &evlist->entries, node) {
884                 if (!type)
885                         type = pos->attr.sample_type;
886                 else if (type != pos->attr.sample_type)
887                         die("non matching sample_type");
888         }
889
890         return type;
891 }
892
893 bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
894 {
895         bool value = false, first = true;
896         struct perf_evsel *pos;
897
898         list_for_each_entry(pos, &evlist->entries, node) {
899                 if (first) {
900                         value = pos->attr.sample_id_all;
901                         first = false;
902                 } else if (value != pos->attr.sample_id_all)
903                         die("non matching sample_id_all");
904         }
905
906         return value;
907 }
908
909 int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
910                                 perf_event__handler_t process,
911                                 struct perf_session *session)
912 {
913         union perf_event *ev;
914         size_t size;
915         int err;
916
917         size = sizeof(struct perf_event_attr);
918         size = ALIGN(size, sizeof(u64));
919         size += sizeof(struct perf_event_header);
920         size += ids * sizeof(u64);
921
922         ev = malloc(size);
923
924         if (ev == NULL)
925                 return -ENOMEM;
926
927         ev->attr.attr = *attr;
928         memcpy(ev->attr.id, id, ids * sizeof(u64));
929
930         ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
931         ev->attr.header.size = size;
932
933         err = process(ev, NULL, session);
934
935         free(ev);
936
937         return err;
938 }
939
940 int perf_session__synthesize_attrs(struct perf_session *session,
941                                    perf_event__handler_t process)
942 {
943         struct perf_evsel *attr;
944         int err = 0;
945
946         list_for_each_entry(attr, &session->evlist->entries, node) {
947                 err = perf_event__synthesize_attr(&attr->attr, attr->ids,
948                                                   attr->id, process, session);
949                 if (err) {
950                         pr_debug("failed to create perf header attribute\n");
951                         return err;
952                 }
953         }
954
955         return err;
956 }
957
958 int perf_event__process_attr(union perf_event *event,
959                              struct perf_session *session)
960 {
961         unsigned int i, ids, n_ids;
962         struct perf_evsel *evsel;
963
964         if (session->evlist == NULL) {
965                 session->evlist = perf_evlist__new(NULL, NULL);
966                 if (session->evlist == NULL)
967                         return -ENOMEM;
968         }
969
970         evsel = perf_evsel__new(&event->attr.attr,
971                                 session->evlist->nr_entries);
972         if (evsel == NULL)
973                 return -ENOMEM;
974
975         perf_evlist__add(session->evlist, evsel);
976
977         ids = event->header.size;
978         ids -= (void *)&event->attr.id - (void *)event;
979         n_ids = ids / sizeof(u64);
980         /*
981          * We don't have the cpu and thread maps on the header, so
982          * for allocating the perf_sample_id table we fake 1 cpu and
983          * hattr->ids threads.
984          */
985         if (perf_evsel__alloc_id(evsel, 1, n_ids))
986                 return -ENOMEM;
987
988         for (i = 0; i < n_ids; i++) {
989                 perf_evlist__id_add(session->evlist, evsel, 0, i,
990                                     event->attr.id[i]);
991         }
992
993         perf_session__update_sample_type(session);
994
995         return 0;
996 }
997
998 int perf_event__synthesize_event_type(u64 event_id, char *name,
999                                       perf_event__handler_t process,
1000                                       struct perf_session *session)
1001 {
1002         union perf_event ev;
1003         size_t size = 0;
1004         int err = 0;
1005
1006         memset(&ev, 0, sizeof(ev));
1007
1008         ev.event_type.event_type.event_id = event_id;
1009         memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME);
1010         strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
1011
1012         ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
1013         size = strlen(name);
1014         size = ALIGN(size, sizeof(u64));
1015         ev.event_type.header.size = sizeof(ev.event_type) -
1016                 (sizeof(ev.event_type.event_type.name) - size);
1017
1018         err = process(&ev, NULL, session);
1019
1020         return err;
1021 }
1022
1023 int perf_event__synthesize_event_types(perf_event__handler_t process,
1024                                        struct perf_session *session)
1025 {
1026         struct perf_trace_event_type *type;
1027         int i, err = 0;
1028
1029         for (i = 0; i < event_count; i++) {
1030                 type = &events[i];
1031
1032                 err = perf_event__synthesize_event_type(type->event_id,
1033                                                         type->name, process,
1034                                                         session);
1035                 if (err) {
1036                         pr_debug("failed to create perf header event type\n");
1037                         return err;
1038                 }
1039         }
1040
1041         return err;
1042 }
1043
1044 int perf_event__process_event_type(union perf_event *event,
1045                                    struct perf_session *session __unused)
1046 {
1047         if (perf_header__push_event(event->event_type.event_type.event_id,
1048                                     event->event_type.event_type.name) < 0)
1049                 return -ENOMEM;
1050
1051         return 0;
1052 }
1053
1054 int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
1055                                          perf_event__handler_t process,
1056                                    struct perf_session *session __unused)
1057 {
1058         union perf_event ev;
1059         ssize_t size = 0, aligned_size = 0, padding;
1060         int err __used = 0;
1061
1062         memset(&ev, 0, sizeof(ev));
1063
1064         ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1065         size = read_tracing_data_size(fd, &evlist->entries);
1066         if (size <= 0)
1067                 return size;
1068         aligned_size = ALIGN(size, sizeof(u64));
1069         padding = aligned_size - size;
1070         ev.tracing_data.header.size = sizeof(ev.tracing_data);
1071         ev.tracing_data.size = aligned_size;
1072
1073         process(&ev, NULL, session);
1074
1075         err = read_tracing_data(fd, &evlist->entries);
1076         write_padded(fd, NULL, 0, padding);
1077
1078         return aligned_size;
1079 }
1080
1081 int perf_event__process_tracing_data(union perf_event *event,
1082                                      struct perf_session *session)
1083 {
1084         ssize_t size_read, padding, size = event->tracing_data.size;
1085         off_t offset = lseek(session->fd, 0, SEEK_CUR);
1086         char buf[BUFSIZ];
1087
1088         /* setup for reading amidst mmap */
1089         lseek(session->fd, offset + sizeof(struct tracing_data_event),
1090               SEEK_SET);
1091
1092         size_read = trace_report(session->fd, session->repipe);
1093
1094         padding = ALIGN(size_read, sizeof(u64)) - size_read;
1095
1096         if (read(session->fd, buf, padding) < 0)
1097                 die("reading input file");
1098         if (session->repipe) {
1099                 int retw = write(STDOUT_FILENO, buf, padding);
1100                 if (retw <= 0 || retw != padding)
1101                         die("repiping tracing data padding");
1102         }
1103
1104         if (size_read + padding != size)
1105                 die("tracing data size mismatch");
1106
1107         return size_read + padding;
1108 }
1109
1110 int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
1111                                     perf_event__handler_t process,
1112                                     struct machine *machine,
1113                                     struct perf_session *session)
1114 {
1115         union perf_event ev;
1116         size_t len;
1117         int err = 0;
1118
1119         if (!pos->hit)
1120                 return err;
1121
1122         memset(&ev, 0, sizeof(ev));
1123
1124         len = pos->long_name_len + 1;
1125         len = ALIGN(len, NAME_ALIGN);
1126         memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
1127         ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
1128         ev.build_id.header.misc = misc;
1129         ev.build_id.pid = machine->pid;
1130         ev.build_id.header.size = sizeof(ev.build_id) + len;
1131         memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
1132
1133         err = process(&ev, NULL, session);
1134
1135         return err;
1136 }
1137
1138 int perf_event__process_build_id(union perf_event *event,
1139                                  struct perf_session *session)
1140 {
1141         __event_process_build_id(&event->build_id,
1142                                  event->build_id.filename,
1143                                  session);
1144         return 0;
1145 }
1146
1147 void disable_buildid_cache(void)
1148 {
1149         no_buildid_cache = true;
1150 }