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 "symbol.h" 12 #include "data_map.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 /* 62 * Create new perf.data header: 63 */ 64 struct perf_header *perf_header__new(void) 65 { 66 struct perf_header *self = zalloc(sizeof(*self)); 67 68 if (self != NULL) { 69 self->size = 1; 70 self->attr = malloc(sizeof(void *)); 71 72 if (self->attr == NULL) { 73 free(self); 74 self = NULL; 75 } 76 } 77 78 return self; 79 } 80 81 void perf_header__delete(struct perf_header *self) 82 { 83 int i; 84 85 for (i = 0; i < self->attrs; ++i) 86 perf_header_attr__delete(self->attr[i]); 87 88 free(self->attr); 89 free(self); 90 } 91 92 int perf_header__add_attr(struct perf_header *self, 93 struct perf_header_attr *attr) 94 { 95 if (self->frozen) 96 return -1; 97 98 if (self->attrs == self->size) { 99 int nsize = self->size * 2; 100 struct perf_header_attr **nattr; 101 102 nattr = realloc(self->attr, nsize * sizeof(void *)); 103 if (nattr == NULL) 104 return -1; 105 106 self->size = nsize; 107 self->attr = nattr; 108 } 109 110 self->attr[self->attrs++] = attr; 111 return 0; 112 } 113 114 #define MAX_EVENT_NAME 64 115 116 struct perf_trace_event_type { 117 u64 event_id; 118 char name[MAX_EVENT_NAME]; 119 }; 120 121 static int event_count; 122 static struct perf_trace_event_type *events; 123 124 void perf_header__push_event(u64 id, const char *name) 125 { 126 if (strlen(name) > MAX_EVENT_NAME) 127 pr_warning("Event %s will be truncated\n", name); 128 129 if (!events) { 130 events = malloc(sizeof(struct perf_trace_event_type)); 131 if (!events) 132 die("nomem"); 133 } else { 134 events = realloc(events, (event_count + 1) * sizeof(struct perf_trace_event_type)); 135 if (!events) 136 die("nomem"); 137 } 138 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); 139 events[event_count].event_id = id; 140 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); 141 event_count++; 142 } 143 144 char *perf_header__find_event(u64 id) 145 { 146 int i; 147 for (i = 0 ; i < event_count; i++) { 148 if (events[i].event_id == id) 149 return events[i].name; 150 } 151 return NULL; 152 } 153 154 static const char *__perf_magic = "PERFFILE"; 155 156 #define PERF_MAGIC (*(u64 *)__perf_magic) 157 158 struct perf_file_attr { 159 struct perf_event_attr attr; 160 struct perf_file_section ids; 161 }; 162 163 void perf_header__set_feat(struct perf_header *self, int feat) 164 { 165 set_bit(feat, self->adds_features); 166 } 167 168 bool perf_header__has_feat(const struct perf_header *self, int feat) 169 { 170 return test_bit(feat, self->adds_features); 171 } 172 173 static int do_write(int fd, const void *buf, size_t size) 174 { 175 while (size) { 176 int ret = write(fd, buf, size); 177 178 if (ret < 0) 179 return -errno; 180 181 size -= ret; 182 buf += ret; 183 } 184 185 return 0; 186 } 187 188 static int __dsos__write_buildid_table(struct list_head *head, int fd) 189 { 190 #define NAME_ALIGN 64 191 struct dso *pos; 192 static const char zero_buf[NAME_ALIGN]; 193 194 list_for_each_entry(pos, head, node) { 195 int err; 196 struct build_id_event b; 197 size_t len; 198 199 if (!pos->has_build_id) 200 continue; 201 len = pos->long_name_len + 1; 202 len = ALIGN(len, NAME_ALIGN); 203 memset(&b, 0, sizeof(b)); 204 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 205 b.header.size = sizeof(b) + len; 206 err = do_write(fd, &b, sizeof(b)); 207 if (err < 0) 208 return err; 209 err = do_write(fd, pos->long_name, pos->long_name_len + 1); 210 if (err < 0) 211 return err; 212 err = do_write(fd, zero_buf, len - pos->long_name_len - 1); 213 if (err < 0) 214 return err; 215 } 216 217 return 0; 218 } 219 220 static int dsos__write_buildid_table(int fd) 221 { 222 int err = __dsos__write_buildid_table(&dsos__kernel, fd); 223 if (err == 0) 224 err = __dsos__write_buildid_table(&dsos__user, fd); 225 return err; 226 } 227 228 static int perf_header__adds_write(struct perf_header *self, int fd) 229 { 230 int nr_sections; 231 struct perf_file_section *feat_sec; 232 int sec_size; 233 u64 sec_start; 234 int idx = 0, err; 235 236 if (dsos__read_build_ids()) 237 perf_header__set_feat(self, HEADER_BUILD_ID); 238 239 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 240 if (!nr_sections) 241 return 0; 242 243 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 244 if (feat_sec == NULL) 245 return -ENOMEM; 246 247 sec_size = sizeof(*feat_sec) * nr_sections; 248 249 sec_start = self->data_offset + self->data_size; 250 lseek(fd, sec_start + sec_size, SEEK_SET); 251 252 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { 253 struct perf_file_section *trace_sec; 254 255 trace_sec = &feat_sec[idx++]; 256 257 /* Write trace info */ 258 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 259 read_tracing_data(fd, attrs, nr_counters); 260 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 261 } 262 263 264 if (perf_header__has_feat(self, HEADER_BUILD_ID)) { 265 struct perf_file_section *buildid_sec; 266 267 buildid_sec = &feat_sec[idx++]; 268 269 /* Write build-ids */ 270 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 271 err = dsos__write_buildid_table(fd); 272 if (err < 0) { 273 pr_debug("failed to write buildid table\n"); 274 goto out_free; 275 } 276 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; 277 } 278 279 lseek(fd, sec_start, SEEK_SET); 280 err = do_write(fd, feat_sec, sec_size); 281 if (err < 0) 282 pr_debug("failed to write feature section\n"); 283 out_free: 284 free(feat_sec); 285 return err; 286 } 287 288 int perf_header__write(struct perf_header *self, int fd, bool at_exit) 289 { 290 struct perf_file_header f_header; 291 struct perf_file_attr f_attr; 292 struct perf_header_attr *attr; 293 int i, err; 294 295 lseek(fd, sizeof(f_header), SEEK_SET); 296 297 298 for (i = 0; i < self->attrs; i++) { 299 attr = self->attr[i]; 300 301 attr->id_offset = lseek(fd, 0, SEEK_CUR); 302 err = do_write(fd, attr->id, attr->ids * sizeof(u64)); 303 if (err < 0) { 304 pr_debug("failed to write perf header\n"); 305 return err; 306 } 307 } 308 309 310 self->attr_offset = lseek(fd, 0, SEEK_CUR); 311 312 for (i = 0; i < self->attrs; i++) { 313 attr = self->attr[i]; 314 315 f_attr = (struct perf_file_attr){ 316 .attr = attr->attr, 317 .ids = { 318 .offset = attr->id_offset, 319 .size = attr->ids * sizeof(u64), 320 } 321 }; 322 err = do_write(fd, &f_attr, sizeof(f_attr)); 323 if (err < 0) { 324 pr_debug("failed to write perf header attribute\n"); 325 return err; 326 } 327 } 328 329 self->event_offset = lseek(fd, 0, SEEK_CUR); 330 self->event_size = event_count * sizeof(struct perf_trace_event_type); 331 if (events) { 332 err = do_write(fd, events, self->event_size); 333 if (err < 0) { 334 pr_debug("failed to write perf header events\n"); 335 return err; 336 } 337 } 338 339 self->data_offset = lseek(fd, 0, SEEK_CUR); 340 341 if (at_exit) { 342 err = perf_header__adds_write(self, fd); 343 if (err < 0) 344 return err; 345 } 346 347 f_header = (struct perf_file_header){ 348 .magic = PERF_MAGIC, 349 .size = sizeof(f_header), 350 .attr_size = sizeof(f_attr), 351 .attrs = { 352 .offset = self->attr_offset, 353 .size = self->attrs * sizeof(f_attr), 354 }, 355 .data = { 356 .offset = self->data_offset, 357 .size = self->data_size, 358 }, 359 .event_types = { 360 .offset = self->event_offset, 361 .size = self->event_size, 362 }, 363 }; 364 365 memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); 366 367 lseek(fd, 0, SEEK_SET); 368 err = do_write(fd, &f_header, sizeof(f_header)); 369 if (err < 0) { 370 pr_debug("failed to write perf header\n"); 371 return err; 372 } 373 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 374 375 self->frozen = 1; 376 return 0; 377 } 378 379 static void do_read(int fd, void *buf, size_t size) 380 { 381 while (size) { 382 int ret = read(fd, buf, size); 383 384 if (ret < 0) 385 die("failed to read"); 386 if (ret == 0) 387 die("failed to read: missing data"); 388 389 size -= ret; 390 buf += ret; 391 } 392 } 393 394 int perf_header__process_sections(struct perf_header *self, int fd, 395 int (*process)(struct perf_file_section *self, 396 int feat, int fd)) 397 { 398 struct perf_file_section *feat_sec; 399 int nr_sections; 400 int sec_size; 401 int idx = 0; 402 int err = 0, feat = 1; 403 404 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 405 if (!nr_sections) 406 return 0; 407 408 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 409 if (!feat_sec) 410 return -1; 411 412 sec_size = sizeof(*feat_sec) * nr_sections; 413 414 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 415 416 do_read(fd, feat_sec, sec_size); 417 418 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 419 if (perf_header__has_feat(self, feat)) { 420 struct perf_file_section *sec = &feat_sec[idx++]; 421 422 err = process(sec, feat, fd); 423 if (err < 0) 424 break; 425 } 426 ++feat; 427 } 428 429 free(feat_sec); 430 return err; 431 }; 432 433 int perf_file_header__read(struct perf_file_header *self, 434 struct perf_header *ph, int fd) 435 { 436 lseek(fd, 0, SEEK_SET); 437 do_read(fd, self, sizeof(*self)); 438 439 if (self->magic != PERF_MAGIC || 440 self->attr_size != sizeof(struct perf_file_attr)) 441 return -1; 442 443 if (self->size != sizeof(*self)) { 444 /* Support the previous format */ 445 if (self->size == offsetof(typeof(*self), adds_features)) 446 bitmap_zero(self->adds_features, HEADER_FEAT_BITS); 447 else 448 return -1; 449 } 450 451 memcpy(&ph->adds_features, &self->adds_features, 452 sizeof(self->adds_features)); 453 454 ph->event_offset = self->event_types.offset; 455 ph->event_size = self->event_types.size; 456 ph->data_offset = self->data.offset; 457 ph->data_size = self->data.size; 458 return 0; 459 } 460 461 static int perf_file_section__process(struct perf_file_section *self, 462 int feat, int fd) 463 { 464 if (lseek(fd, self->offset, SEEK_SET) < 0) { 465 pr_debug("Failed to lseek to %Ld offset for feature %d, " 466 "continuing...\n", self->offset, feat); 467 return 0; 468 } 469 470 switch (feat) { 471 case HEADER_TRACE_INFO: 472 trace_report(fd); 473 break; 474 475 case HEADER_BUILD_ID: 476 if (perf_header__read_build_ids(fd, self->offset, self->size)) 477 pr_debug("Failed to read buildids, continuing...\n"); 478 break; 479 default: 480 pr_debug("unknown feature %d, continuing...\n", feat); 481 } 482 483 return 0; 484 } 485 486 int perf_header__read(struct perf_header *self, int fd) 487 { 488 struct perf_file_header f_header; 489 struct perf_file_attr f_attr; 490 u64 f_id; 491 int nr_attrs, nr_ids, i, j; 492 493 if (perf_file_header__read(&f_header, self, fd) < 0) { 494 pr_debug("incompatible file format\n"); 495 return -EINVAL; 496 } 497 498 nr_attrs = f_header.attrs.size / sizeof(f_attr); 499 lseek(fd, f_header.attrs.offset, SEEK_SET); 500 501 for (i = 0; i < nr_attrs; i++) { 502 struct perf_header_attr *attr; 503 off_t tmp; 504 505 do_read(fd, &f_attr, sizeof(f_attr)); 506 tmp = lseek(fd, 0, SEEK_CUR); 507 508 attr = perf_header_attr__new(&f_attr.attr); 509 if (attr == NULL) 510 return -ENOMEM; 511 512 nr_ids = f_attr.ids.size / sizeof(u64); 513 lseek(fd, f_attr.ids.offset, SEEK_SET); 514 515 for (j = 0; j < nr_ids; j++) { 516 do_read(fd, &f_id, sizeof(f_id)); 517 518 if (perf_header_attr__add_id(attr, f_id) < 0) { 519 perf_header_attr__delete(attr); 520 return -ENOMEM; 521 } 522 } 523 if (perf_header__add_attr(self, attr) < 0) { 524 perf_header_attr__delete(attr); 525 return -ENOMEM; 526 } 527 528 lseek(fd, tmp, SEEK_SET); 529 } 530 531 if (f_header.event_types.size) { 532 lseek(fd, f_header.event_types.offset, SEEK_SET); 533 events = malloc(f_header.event_types.size); 534 if (events == NULL) 535 return -ENOMEM; 536 do_read(fd, events, f_header.event_types.size); 537 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 538 } 539 540 perf_header__process_sections(self, fd, perf_file_section__process); 541 542 lseek(fd, self->data_offset, SEEK_SET); 543 544 self->frozen = 1; 545 return 0; 546 } 547 548 u64 perf_header__sample_type(struct perf_header *header) 549 { 550 u64 type = 0; 551 int i; 552 553 for (i = 0; i < header->attrs; i++) { 554 struct perf_header_attr *attr = header->attr[i]; 555 556 if (!type) 557 type = attr->attr.sample_type; 558 else if (type != attr->attr.sample_type) 559 die("non matching sample_type"); 560 } 561 562 return type; 563 } 564 565 struct perf_event_attr * 566 perf_header__find_attr(u64 id, struct perf_header *header) 567 { 568 int i; 569 570 for (i = 0; i < header->attrs; i++) { 571 struct perf_header_attr *attr = header->attr[i]; 572 int j; 573 574 for (j = 0; j < attr->ids; j++) { 575 if (attr->id[j] == id) 576 return &attr->attr; 577 } 578 } 579 580 return NULL; 581 } 582