b31e0ae4b8db5b01f3131b1c7fefb9c6c344836e
[firefly-linux-kernel-4.4.55.git] / tools / perf / util / header.c
1 #include <sys/types.h>
2 #include <byteswap.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <linux/list.h>
7 #include <linux/kernel.h>
8
9 #include "util.h"
10 #include "header.h"
11 #include "../perf.h"
12 #include "trace-event.h"
13 #include "session.h"
14 #include "symbol.h"
15 #include "debug.h"
16
17 /*
18  * Create new perf.data header attribute:
19  */
20 struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr)
21 {
22         struct perf_header_attr *self = malloc(sizeof(*self));
23
24         if (self != NULL) {
25                 self->attr = *attr;
26                 self->ids  = 0;
27                 self->size = 1;
28                 self->id   = malloc(sizeof(u64));
29                 if (self->id == NULL) {
30                         free(self);
31                         self = NULL;
32                 }
33         }
34
35         return self;
36 }
37
38 void perf_header_attr__delete(struct perf_header_attr *self)
39 {
40         free(self->id);
41         free(self);
42 }
43
44 int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
45 {
46         int pos = self->ids;
47
48         self->ids++;
49         if (self->ids > self->size) {
50                 int nsize = self->size * 2;
51                 u64 *nid = realloc(self->id, nsize * sizeof(u64));
52
53                 if (nid == NULL)
54                         return -1;
55
56                 self->size = nsize;
57                 self->id = nid;
58         }
59         self->id[pos] = id;
60         return 0;
61 }
62
63 int perf_header__init(struct perf_header *self)
64 {
65         self->size = 1;
66         self->attr = malloc(sizeof(void *));
67         return self->attr == NULL ? -ENOMEM : 0;
68 }
69
70 void perf_header__exit(struct perf_header *self)
71 {
72         int i;
73         for (i = 0; i < self->attrs; ++i)
74                 perf_header_attr__delete(self->attr[i]);
75         free(self->attr);
76 }
77
78 int perf_header__add_attr(struct perf_header *self,
79                           struct perf_header_attr *attr)
80 {
81         if (self->frozen)
82                 return -1;
83
84         if (self->attrs == self->size) {
85                 int nsize = self->size * 2;
86                 struct perf_header_attr **nattr;
87
88                 nattr = realloc(self->attr, nsize * sizeof(void *));
89                 if (nattr == NULL)
90                         return -1;
91
92                 self->size = nsize;
93                 self->attr = nattr;
94         }
95
96         self->attr[self->attrs++] = attr;
97         return 0;
98 }
99
100 #define MAX_EVENT_NAME 64
101
102 struct perf_trace_event_type {
103         u64     event_id;
104         char    name[MAX_EVENT_NAME];
105 };
106
107 static int event_count;
108 static struct perf_trace_event_type *events;
109
110 int perf_header__push_event(u64 id, const char *name)
111 {
112         if (strlen(name) > MAX_EVENT_NAME)
113                 pr_warning("Event %s will be truncated\n", name);
114
115         if (!events) {
116                 events = malloc(sizeof(struct perf_trace_event_type));
117                 if (events == NULL)
118                         return -ENOMEM;
119         } else {
120                 struct perf_trace_event_type *nevents;
121
122                 nevents = realloc(events, (event_count + 1) * sizeof(*events));
123                 if (nevents == NULL)
124                         return -ENOMEM;
125                 events = nevents;
126         }
127         memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
128         events[event_count].event_id = id;
129         strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
130         event_count++;
131         return 0;
132 }
133
134 char *perf_header__find_event(u64 id)
135 {
136         int i;
137         for (i = 0 ; i < event_count; i++) {
138                 if (events[i].event_id == id)
139                         return events[i].name;
140         }
141         return NULL;
142 }
143
144 static const char *__perf_magic = "PERFFILE";
145
146 #define PERF_MAGIC      (*(u64 *)__perf_magic)
147
148 struct perf_file_attr {
149         struct perf_event_attr  attr;
150         struct perf_file_section        ids;
151 };
152
153 void perf_header__set_feat(struct perf_header *self, int feat)
154 {
155         set_bit(feat, self->adds_features);
156 }
157
158 bool perf_header__has_feat(const struct perf_header *self, int feat)
159 {
160         return test_bit(feat, self->adds_features);
161 }
162
163 static int do_write(int fd, const void *buf, size_t size)
164 {
165         while (size) {
166                 int ret = write(fd, buf, size);
167
168                 if (ret < 0)
169                         return -errno;
170
171                 size -= ret;
172                 buf += ret;
173         }
174
175         return 0;
176 }
177
178 #define NAME_ALIGN 64
179
180 static int write_padded(int fd, const void *bf, size_t count,
181                         size_t count_aligned)
182 {
183         static const char zero_buf[NAME_ALIGN];
184         int err = do_write(fd, bf, count);
185
186         if (!err)
187                 err = do_write(fd, zero_buf, count_aligned - count);
188
189         return err;
190 }
191
192 #define dsos__for_each_with_build_id(pos, head) \
193         list_for_each_entry(pos, head, node)    \
194                 if (!pos->has_build_id)         \
195                         continue;               \
196                 else
197
198 static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd)
199 {
200         struct dso *pos;
201
202         dsos__for_each_with_build_id(pos, head) {
203                 int err;
204                 struct build_id_event b;
205                 size_t len = pos->long_name_len + 1;
206
207                 len = ALIGN(len, NAME_ALIGN);
208                 memset(&b, 0, sizeof(b));
209                 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
210                 b.header.misc = misc;
211                 b.header.size = sizeof(b) + len;
212                 err = do_write(fd, &b, sizeof(b));
213                 if (err < 0)
214                         return err;
215                 err = write_padded(fd, pos->long_name,
216                                    pos->long_name_len + 1, len);
217                 if (err < 0)
218                         return err;
219         }
220
221         return 0;
222 }
223
224 static int dsos__write_buildid_table(int fd)
225 {
226         int err = __dsos__write_buildid_table(&dsos__kernel,
227                                               PERF_RECORD_MISC_KERNEL, fd);
228         if (err == 0)
229                 err = __dsos__write_buildid_table(&dsos__user,
230                                                   PERF_RECORD_MISC_USER, fd);
231         return err;
232 }
233
234 static int dso__cache_build_id(struct dso *self, const char *debugdir)
235 {
236         const size_t size = PATH_MAX;
237         char *filename = malloc(size),
238              *linkname = malloc(size), *targetname, *sbuild_id;
239         int len, err = -1;
240
241         if (filename == NULL || linkname == NULL)
242                 goto out_free;
243
244         len = snprintf(filename, size, "%s%s", debugdir, self->long_name);
245         if (mkdir_p(filename, 0755))
246                 goto out_free;
247
248         len += snprintf(filename + len, sizeof(filename) - len, "/");
249         sbuild_id = filename + len;
250         build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
251
252         if (access(filename, F_OK) && link(self->long_name, filename) &&
253             copyfile(self->long_name, filename))
254                 goto out_free;
255
256         len = snprintf(linkname, size, "%s/.build-id/%.2s",
257                        debugdir, sbuild_id);
258
259         if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
260                 goto out_free;
261
262         snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
263         targetname = filename + strlen(debugdir) - 5;
264         memcpy(targetname, "../..", 5);
265
266         if (symlink(targetname, linkname) == 0)
267                 err = 0;
268 out_free:
269         free(filename);
270         free(linkname);
271         return err;
272 }
273
274 static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
275 {
276         struct dso *pos;
277         int err = 0;
278
279         dsos__for_each_with_build_id(pos, head)
280                 if (dso__cache_build_id(pos, debugdir))
281                         err = -1;
282
283         return err;
284 }
285
286 static int dsos__cache_build_ids(void)
287 {
288         int err_kernel, err_user;
289         char debugdir[PATH_MAX];
290
291         snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"),
292                  DEBUG_CACHE_DIR);
293
294         if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
295                 return -1;
296
297         err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir);
298         err_user   = __dsos__cache_build_ids(&dsos__user, debugdir);
299         return err_kernel || err_user ? -1 : 0;
300 }
301
302 static int perf_header__adds_write(struct perf_header *self, int fd)
303 {
304         int nr_sections;
305         struct perf_file_section *feat_sec;
306         int sec_size;
307         u64 sec_start;
308         int idx = 0, err;
309
310         if (dsos__read_build_ids())
311                 perf_header__set_feat(self, HEADER_BUILD_ID);
312
313         nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
314         if (!nr_sections)
315                 return 0;
316
317         feat_sec = calloc(sizeof(*feat_sec), nr_sections);
318         if (feat_sec == NULL)
319                 return -ENOMEM;
320
321         sec_size = sizeof(*feat_sec) * nr_sections;
322
323         sec_start = self->data_offset + self->data_size;
324         lseek(fd, sec_start + sec_size, SEEK_SET);
325
326         if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
327                 struct perf_file_section *trace_sec;
328
329                 trace_sec = &feat_sec[idx++];
330
331                 /* Write trace info */
332                 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
333                 read_tracing_data(fd, attrs, nr_counters);
334                 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
335         }
336
337
338         if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
339                 struct perf_file_section *buildid_sec;
340
341                 buildid_sec = &feat_sec[idx++];
342
343                 /* Write build-ids */
344                 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
345                 err = dsos__write_buildid_table(fd);
346                 if (err < 0) {
347                         pr_debug("failed to write buildid table\n");
348                         goto out_free;
349                 }
350                 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset;
351                 dsos__cache_build_ids();
352         }
353
354         lseek(fd, sec_start, SEEK_SET);
355         err = do_write(fd, feat_sec, sec_size);
356         if (err < 0)
357                 pr_debug("failed to write feature section\n");
358 out_free:
359         free(feat_sec);
360         return err;
361 }
362
363 int perf_header__write(struct perf_header *self, int fd, bool at_exit)
364 {
365         struct perf_file_header f_header;
366         struct perf_file_attr   f_attr;
367         struct perf_header_attr *attr;
368         int i, err;
369
370         lseek(fd, sizeof(f_header), SEEK_SET);
371
372
373         for (i = 0; i < self->attrs; i++) {
374                 attr = self->attr[i];
375
376                 attr->id_offset = lseek(fd, 0, SEEK_CUR);
377                 err = do_write(fd, attr->id, attr->ids * sizeof(u64));
378                 if (err < 0) {
379                         pr_debug("failed to write perf header\n");
380                         return err;
381                 }
382         }
383
384
385         self->attr_offset = lseek(fd, 0, SEEK_CUR);
386
387         for (i = 0; i < self->attrs; i++) {
388                 attr = self->attr[i];
389
390                 f_attr = (struct perf_file_attr){
391                         .attr = attr->attr,
392                         .ids  = {
393                                 .offset = attr->id_offset,
394                                 .size   = attr->ids * sizeof(u64),
395                         }
396                 };
397                 err = do_write(fd, &f_attr, sizeof(f_attr));
398                 if (err < 0) {
399                         pr_debug("failed to write perf header attribute\n");
400                         return err;
401                 }
402         }
403
404         self->event_offset = lseek(fd, 0, SEEK_CUR);
405         self->event_size = event_count * sizeof(struct perf_trace_event_type);
406         if (events) {
407                 err = do_write(fd, events, self->event_size);
408                 if (err < 0) {
409                         pr_debug("failed to write perf header events\n");
410                         return err;
411                 }
412         }
413
414         self->data_offset = lseek(fd, 0, SEEK_CUR);
415
416         if (at_exit) {
417                 err = perf_header__adds_write(self, fd);
418                 if (err < 0)
419                         return err;
420         }
421
422         f_header = (struct perf_file_header){
423                 .magic     = PERF_MAGIC,
424                 .size      = sizeof(f_header),
425                 .attr_size = sizeof(f_attr),
426                 .attrs = {
427                         .offset = self->attr_offset,
428                         .size   = self->attrs * sizeof(f_attr),
429                 },
430                 .data = {
431                         .offset = self->data_offset,
432                         .size   = self->data_size,
433                 },
434                 .event_types = {
435                         .offset = self->event_offset,
436                         .size   = self->event_size,
437                 },
438         };
439
440         memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
441
442         lseek(fd, 0, SEEK_SET);
443         err = do_write(fd, &f_header, sizeof(f_header));
444         if (err < 0) {
445                 pr_debug("failed to write perf header\n");
446                 return err;
447         }
448         lseek(fd, self->data_offset + self->data_size, SEEK_SET);
449
450         self->frozen = 1;
451         return 0;
452 }
453
454 static int do_read(int fd, void *buf, size_t size)
455 {
456         while (size) {
457                 int ret = read(fd, buf, size);
458
459                 if (ret <= 0)
460                         return -1;
461
462                 size -= ret;
463                 buf += ret;
464         }
465
466         return 0;
467 }
468
469 static int perf_header__getbuffer64(struct perf_header *self,
470                                     int fd, void *buf, size_t size)
471 {
472         if (do_read(fd, buf, size))
473                 return -1;
474
475         if (self->needs_swap)
476                 mem_bswap_64(buf, size);
477
478         return 0;
479 }
480
481 int perf_header__process_sections(struct perf_header *self, int fd,
482                                   int (*process)(struct perf_file_section *self,
483                                                  struct perf_header *ph,
484                                                  int feat, int fd))
485 {
486         struct perf_file_section *feat_sec;
487         int nr_sections;
488         int sec_size;
489         int idx = 0;
490         int err = -1, feat = 1;
491
492         nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
493         if (!nr_sections)
494                 return 0;
495
496         feat_sec = calloc(sizeof(*feat_sec), nr_sections);
497         if (!feat_sec)
498                 return -1;
499
500         sec_size = sizeof(*feat_sec) * nr_sections;
501
502         lseek(fd, self->data_offset + self->data_size, SEEK_SET);
503
504         if (perf_header__getbuffer64(self, fd, feat_sec, sec_size))
505                 goto out_free;
506
507         err = 0;
508         while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
509                 if (perf_header__has_feat(self, feat)) {
510                         struct perf_file_section *sec = &feat_sec[idx++];
511
512                         err = process(sec, self, feat, fd);
513                         if (err < 0)
514                                 break;
515                 }
516                 ++feat;
517         }
518 out_free:
519         free(feat_sec);
520         return err;
521 }
522
523 int perf_file_header__read(struct perf_file_header *self,
524                            struct perf_header *ph, int fd)
525 {
526         lseek(fd, 0, SEEK_SET);
527
528         if (do_read(fd, self, sizeof(*self)) ||
529             memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
530                 return -1;
531
532         if (self->attr_size != sizeof(struct perf_file_attr)) {
533                 u64 attr_size = bswap_64(self->attr_size);
534
535                 if (attr_size != sizeof(struct perf_file_attr))
536                         return -1;
537
538                 mem_bswap_64(self, offsetof(struct perf_file_header,
539                                             adds_features));
540                 ph->needs_swap = true;
541         }
542
543         if (self->size != sizeof(*self)) {
544                 /* Support the previous format */
545                 if (self->size == offsetof(typeof(*self), adds_features))
546                         bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
547                 else
548                         return -1;
549         }
550
551         memcpy(&ph->adds_features, &self->adds_features,
552                sizeof(ph->adds_features));
553         /*
554          * FIXME: hack that assumes that if we need swap the perf.data file
555          * may be coming from an arch with a different word-size, ergo different
556          * DEFINE_BITMAP format, investigate more later, but for now its mostly
557          * safe to assume that we have a build-id section. Trace files probably
558          * have several other issues in this realm anyway...
559          */
560         if (ph->needs_swap) {
561                 memset(&ph->adds_features, 0, sizeof(ph->adds_features));
562                 perf_header__set_feat(ph, HEADER_BUILD_ID);
563         }
564
565         ph->event_offset = self->event_types.offset;
566         ph->event_size   = self->event_types.size;
567         ph->data_offset  = self->data.offset;
568         ph->data_size    = self->data.size;
569         return 0;
570 }
571
572 static int perf_file_section__process(struct perf_file_section *self,
573                                       struct perf_header *ph,
574                                       int feat, int fd)
575 {
576         if (lseek(fd, self->offset, SEEK_SET) < 0) {
577                 pr_debug("Failed to lseek to %Ld offset for feature %d, "
578                          "continuing...\n", self->offset, feat);
579                 return 0;
580         }
581
582         switch (feat) {
583         case HEADER_TRACE_INFO:
584                 trace_report(fd);
585                 break;
586
587         case HEADER_BUILD_ID:
588                 if (perf_header__read_build_ids(ph, fd, self->offset, self->size))
589                         pr_debug("Failed to read buildids, continuing...\n");
590                 break;
591         default:
592                 pr_debug("unknown feature %d, continuing...\n", feat);
593         }
594
595         return 0;
596 }
597
598 int perf_header__read(struct perf_header *self, int fd)
599 {
600         struct perf_file_header f_header;
601         struct perf_file_attr   f_attr;
602         u64                     f_id;
603         int nr_attrs, nr_ids, i, j;
604
605         if (perf_file_header__read(&f_header, self, fd) < 0) {
606                 pr_debug("incompatible file format\n");
607                 return -EINVAL;
608         }
609
610         nr_attrs = f_header.attrs.size / sizeof(f_attr);
611         lseek(fd, f_header.attrs.offset, SEEK_SET);
612
613         for (i = 0; i < nr_attrs; i++) {
614                 struct perf_header_attr *attr;
615                 off_t tmp;
616
617                 if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr)))
618                         goto out_errno;
619
620                 tmp = lseek(fd, 0, SEEK_CUR);
621
622                 attr = perf_header_attr__new(&f_attr.attr);
623                 if (attr == NULL)
624                          return -ENOMEM;
625
626                 nr_ids = f_attr.ids.size / sizeof(u64);
627                 lseek(fd, f_attr.ids.offset, SEEK_SET);
628
629                 for (j = 0; j < nr_ids; j++) {
630                         if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id)))
631                                 goto out_errno;
632
633                         if (perf_header_attr__add_id(attr, f_id) < 0) {
634                                 perf_header_attr__delete(attr);
635                                 return -ENOMEM;
636                         }
637                 }
638                 if (perf_header__add_attr(self, attr) < 0) {
639                         perf_header_attr__delete(attr);
640                         return -ENOMEM;
641                 }
642
643                 lseek(fd, tmp, SEEK_SET);
644         }
645
646         if (f_header.event_types.size) {
647                 lseek(fd, f_header.event_types.offset, SEEK_SET);
648                 events = malloc(f_header.event_types.size);
649                 if (events == NULL)
650                         return -ENOMEM;
651                 if (perf_header__getbuffer64(self, fd, events,
652                                              f_header.event_types.size))
653                         goto out_errno;
654                 event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
655         }
656
657         perf_header__process_sections(self, fd, perf_file_section__process);
658
659         lseek(fd, self->data_offset, SEEK_SET);
660
661         self->frozen = 1;
662         return 0;
663 out_errno:
664         return -errno;
665 }
666
667 u64 perf_header__sample_type(struct perf_header *header)
668 {
669         u64 type = 0;
670         int i;
671
672         for (i = 0; i < header->attrs; i++) {
673                 struct perf_header_attr *attr = header->attr[i];
674
675                 if (!type)
676                         type = attr->attr.sample_type;
677                 else if (type != attr->attr.sample_type)
678                         die("non matching sample_type");
679         }
680
681         return type;
682 }
683
684 struct perf_event_attr *
685 perf_header__find_attr(u64 id, struct perf_header *header)
686 {
687         int i;
688
689         for (i = 0; i < header->attrs; i++) {
690                 struct perf_header_attr *attr = header->attr[i];
691                 int j;
692
693                 for (j = 0; j < attr->ids; j++) {
694                         if (attr->id[j] == id)
695                                 return &attr->attr;
696                 }
697         }
698
699         return NULL;
700 }