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