header.c 26.8 KB
Newer Older
1 2
#define _FILE_OFFSET_BITS 64

3
#include <sys/types.h>
4
#include <byteswap.h>
5 6 7
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
8
#include <linux/list.h>
9
#include <linux/kernel.h>
10

11
#include "evlist.h"
12
#include "evsel.h"
13 14
#include "util.h"
#include "header.h"
15 16
#include "../perf.h"
#include "trace-event.h"
17
#include "session.h"
18
#include "symbol.h"
19
#include "debug.h"
20

21 22
static bool no_buildid_cache = false;

23 24 25
static int event_count;
static struct perf_trace_event_type *events;

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 32

	if (!events) {
		events = malloc(sizeof(struct perf_trace_event_type));
33 34
		if (events == NULL)
			return -ENOMEM;
35
	} else {
36 37 38 39 40 41
		struct perf_trace_event_type *nevents;

		nevents = realloc(events, (event_count + 1) * sizeof(*events));
		if (nevents == NULL)
			return -ENOMEM;
		events = nevents;
42 43 44
	}
	memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
	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 51 52 53 54 55 56 57 58 59
}

char *perf_header__find_event(u64 id)
{
	int i;
	for (i = 0 ; i < event_count; i++) {
		if (events[i].event_id == id)
			return events[i].name;
	}
	return NULL;
}

60 61 62 63 64
static const char *__perf_magic = "PERFFILE";

#define PERF_MAGIC	(*(u64 *)__perf_magic)

struct perf_file_attr {
65
	struct perf_event_attr	attr;
66 67 68
	struct perf_file_section	ids;
};

69 70 71 72 73
void perf_header__set_feat(struct perf_header *self, int feat)
{
	set_bit(feat, self->adds_features);
}

74 75 76 77 78
void perf_header__clear_feat(struct perf_header *self, int feat)
{
	clear_bit(feat, self->adds_features);
}

79 80 81 82 83
bool perf_header__has_feat(const struct perf_header *self, int feat)
{
	return test_bit(feat, self->adds_features);
}

84
static int do_write(int fd, const void *buf, size_t size)
85 86 87 88 89
{
	while (size) {
		int ret = write(fd, buf, size);

		if (ret < 0)
90
			return -errno;
91 92 93 94

		size -= ret;
		buf += ret;
	}
95 96

	return 0;
97 98
}

99 100 101 102 103 104 105 106 107 108 109 110 111 112
#define NAME_ALIGN 64

static int write_padded(int fd, const void *bf, size_t count,
			size_t count_aligned)
{
	static const char zero_buf[NAME_ALIGN];
	int err = do_write(fd, bf, count);

	if (!err)
		err = do_write(fd, zero_buf, count_aligned - count);

	return err;
}

113 114 115 116 117 118
#define dsos__for_each_with_build_id(pos, head)	\
	list_for_each_entry(pos, head, node)	\
		if (!pos->has_build_id)		\
			continue;		\
		else

119 120
static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
				u16 misc, int fd)
121
{
122 123
	struct dso *pos;

124
	dsos__for_each_with_build_id(pos, head) {
125
		int err;
126
		struct build_id_event b;
127
		size_t len;
128

129 130 131
		if (!pos->hit)
			continue;
		len = pos->long_name_len + 1;
O
OGAWA Hirofumi 已提交
132
		len = ALIGN(len, NAME_ALIGN);
133 134
		memset(&b, 0, sizeof(b));
		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 139 140
		err = do_write(fd, &b, sizeof(b));
		if (err < 0)
			return err;
141 142
		err = write_padded(fd, pos->long_name,
				   pos->long_name_len + 1, len);
143 144
		if (err < 0)
			return err;
145
	}
146 147

	return 0;
148 149
}

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
static int machine__write_buildid_table(struct machine *self, int fd)
{
	int err;
	u16 kmisc = PERF_RECORD_MISC_KERNEL,
	    umisc = PERF_RECORD_MISC_USER;

	if (!machine__is_host(self)) {
		kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
		umisc = PERF_RECORD_MISC_GUEST_USER;
	}

	err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid,
					  kmisc, fd);
	if (err == 0)
		err = __dsos__write_buildid_table(&self->user_dsos,
						  self->pid, umisc, fd);
	return err;
}

169
static int dsos__write_buildid_table(struct perf_header *header, int fd)
170
{
171 172 173
	struct perf_session *session = container_of(header,
			struct perf_session, header);
	struct rb_node *nd;
174 175 176 177
	int err = machine__write_buildid_table(&session->host_machine, fd);

	if (err)
		return err;
178

179 180
	for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
		struct machine *pos = rb_entry(nd, struct machine, rb_node);
181
		err = machine__write_buildid_table(pos, fd);
182 183 184
		if (err)
			break;
	}
185 186 187
	return err;
}

188 189
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
			  const char *name, bool is_kallsyms)
190 191
{
	const size_t size = PATH_MAX;
192 193
	char *realname = realpath(name, NULL),
	     *filename = malloc(size),
194
	     *linkname = malloc(size), *targetname;
195 196
	int len, err = -1;

197
	if (realname == NULL || filename == NULL || linkname == NULL)
198 199
		goto out_free;

200
	len = snprintf(filename, size, "%s%s%s",
201
		       debugdir, is_kallsyms ? "/" : "", realname);
202 203 204
	if (mkdir_p(filename, 0755))
		goto out_free;

205
	snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
206

207 208 209 210
	if (access(filename, F_OK)) {
		if (is_kallsyms) {
			 if (copyfile("/proc/kallsyms", filename))
				goto out_free;
211
		} else if (link(realname, filename) && copyfile(name, filename))
212 213
			goto out_free;
	}
214 215 216 217 218 219 220 221 222 223 224 225 226 227

	len = snprintf(linkname, size, "%s/.build-id/%.2s",
		       debugdir, sbuild_id);

	if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
		goto out_free;

	snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
	targetname = filename + strlen(debugdir) - 5;
	memcpy(targetname, "../..", 5);

	if (symlink(targetname, linkname) == 0)
		err = 0;
out_free:
228
	free(realname);
229 230 231 232 233
	free(filename);
	free(linkname);
	return err;
}

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
				 const char *name, const char *debugdir,
				 bool is_kallsyms)
{
	char sbuild_id[BUILD_ID_SIZE * 2 + 1];

	build_id__sprintf(build_id, build_id_size, sbuild_id);

	return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
}

int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
{
	const size_t size = PATH_MAX;
	char *filename = malloc(size),
	     *linkname = malloc(size);
	int err = -1;

	if (filename == NULL || linkname == NULL)
		goto out_free;

	snprintf(linkname, size, "%s/.build-id/%.2s/%s",
		 debugdir, sbuild_id, sbuild_id + 2);

	if (access(linkname, F_OK))
		goto out_free;

	if (readlink(linkname, filename, size) < 0)
		goto out_free;

	if (unlink(linkname))
		goto out_free;

	/*
	 * Since the link is relative, we must make it absolute:
	 */
	snprintf(linkname, size, "%s/.build-id/%.2s/%s",
		 debugdir, sbuild_id, filename);

	if (unlink(linkname))
		goto out_free;

	err = 0;
out_free:
	free(filename);
	free(linkname);
	return err;
}

static int dso__cache_build_id(struct dso *self, const char *debugdir)
{
	bool is_kallsyms = self->kernel && self->long_name[0] != '/';

	return build_id_cache__add_b(self->build_id, sizeof(self->build_id),
				     self->long_name, debugdir, is_kallsyms);
}

291 292 293 294 295 296 297 298 299 300 301 302
static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
{
	struct dso *pos;
	int err = 0;

	dsos__for_each_with_build_id(pos, head)
		if (dso__cache_build_id(pos, debugdir))
			err = -1;

	return err;
}

303 304 305 306 307 308 309 310
static int machine__cache_build_ids(struct machine *self, const char *debugdir)
{
	int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir);
	ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir);
	return ret;
}

static int perf_session__cache_build_ids(struct perf_session *self)
311
{
312
	struct rb_node *nd;
313
	int ret;
314 315
	char debugdir[PATH_MAX];

316
	snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
317 318 319 320

	if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
		return -1;

321 322 323
	ret = machine__cache_build_ids(&self->host_machine, debugdir);

	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 328 329
	}
	return ret ? -1 : 0;
}

330 331 332 333 334 335 336 337
static bool machine__read_build_ids(struct machine *self, bool with_hits)
{
	bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits);
	ret |= __dsos__read_build_ids(&self->user_dsos, with_hits);
	return ret;
}

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 351
static int perf_header__adds_write(struct perf_header *self,
				   struct perf_evlist *evlist, int fd)
352
{
353
	int nr_sections;
354
	struct perf_session *session;
355 356 357
	struct perf_file_section *feat_sec;
	int sec_size;
	u64 sec_start;
358
	int idx = 0, err;
359

360
	session = container_of(self, struct perf_session, header);
361 362 363 364

	if (perf_header__has_feat(self, HEADER_BUILD_ID &&
	    !perf_session__read_build_ids(session, true)))
		perf_header__clear_feat(self, HEADER_BUILD_ID);
365 366 367

	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
	if (!nr_sections)
368
		return 0;
369 370

	feat_sec = calloc(sizeof(*feat_sec), nr_sections);
371 372
	if (feat_sec == NULL)
		return -ENOMEM;
373 374 375 376

	sec_size = sizeof(*feat_sec) * nr_sections;

	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 381 382 383
		struct perf_file_section *trace_sec;

		trace_sec = &feat_sec[idx++];

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 391 392 393 394 395
	if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
		struct perf_file_section *buildid_sec;

		buildid_sec = &feat_sec[idx++];

		/* Write build-ids */
396
		buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
397
		err = dsos__write_buildid_table(self, fd);
398 399 400 401
		if (err < 0) {
			pr_debug("failed to write buildid table\n");
			goto out_free;
		}
402 403
		buildid_sec->size = lseek(fd, 0, SEEK_CUR) -
					  buildid_sec->offset;
404 405
		if (!no_buildid_cache)
			perf_session__cache_build_ids(session);
406
	}
407

408
	lseek(fd, sec_start, SEEK_SET);
409 410 411 412
	err = do_write(fd, feat_sec, sec_size);
	if (err < 0)
		pr_debug("failed to write feature section\n");
out_free:
413
	free(feat_sec);
414
	return err;
415
}
416

417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
int perf_header__write_pipe(int fd)
{
	struct perf_pipe_file_header f_header;
	int err;

	f_header = (struct perf_pipe_file_header){
		.magic	   = PERF_MAGIC,
		.size	   = sizeof(f_header),
	};

	err = do_write(fd, &f_header, sizeof(f_header));
	if (err < 0) {
		pr_debug("failed to write perf pipe header\n");
		return err;
	}

	return 0;
}

436 437 438
int perf_session__write_header(struct perf_session *session,
			       struct perf_evlist *evlist,
			       int fd, bool at_exit)
439 440 441
{
	struct perf_file_header f_header;
	struct perf_file_attr   f_attr;
442 443 444
	struct perf_header *self = &session->header;
	struct perf_evsel *attr, *pair = NULL;
	int err;
445 446 447

	lseek(fd, sizeof(f_header), SEEK_SET);

448 449
	if (session->evlist != evlist)
		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 454
		err = do_write(fd, attr->id, attr->ids * sizeof(u64));
		if (err < 0) {
455
out_err_write:
456 457 458
			pr_debug("failed to write perf header\n");
			return err;
		}
459 460 461 462 463 464 465
		if (session->evlist != evlist) {
			err = do_write(fd, pair->id, pair->ids * sizeof(u64));
			if (err < 0)
				goto out_err_write;
			attr->ids += pair->ids;
			pair = list_entry(pair->node.next, struct perf_evsel, node);
		}
466 467 468 469
	}

	self->attr_offset = lseek(fd, 0, SEEK_CUR);

470
	list_for_each_entry(attr, &evlist->entries, node) {
471 472 473 474 475 476 477
		f_attr = (struct perf_file_attr){
			.attr = attr->attr,
			.ids  = {
				.offset = attr->id_offset,
				.size   = attr->ids * sizeof(u64),
			}
		};
478 479 480 481 482
		err = do_write(fd, &f_attr, sizeof(f_attr));
		if (err < 0) {
			pr_debug("failed to write perf header attribute\n");
			return err;
		}
483 484
	}

485 486
	self->event_offset = lseek(fd, 0, SEEK_CUR);
	self->event_size = event_count * sizeof(struct perf_trace_event_type);
487 488 489 490 491 492 493
	if (events) {
		err = do_write(fd, events, self->event_size);
		if (err < 0) {
			pr_debug("failed to write perf header events\n");
			return err;
		}
	}
494

495 496
	self->data_offset = lseek(fd, 0, SEEK_CUR);

497
	if (at_exit) {
498
		err = perf_header__adds_write(self, evlist, fd);
499 500 501
		if (err < 0)
			return err;
	}
502

503 504 505 506 507 508
	f_header = (struct perf_file_header){
		.magic	   = PERF_MAGIC,
		.size	   = sizeof(f_header),
		.attr_size = sizeof(f_attr),
		.attrs = {
			.offset = self->attr_offset,
509
			.size   = evlist->nr_entries * sizeof(f_attr),
510 511 512 513 514
		},
		.data = {
			.offset = self->data_offset,
			.size	= self->data_size,
		},
515 516 517 518
		.event_types = {
			.offset = self->event_offset,
			.size	= self->event_size,
		},
519 520
	};

521
	memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
522

523
	lseek(fd, 0, SEEK_SET);
524 525 526 527 528
	err = do_write(fd, &f_header, sizeof(f_header));
	if (err < 0) {
		pr_debug("failed to write perf header\n");
		return err;
	}
529
	lseek(fd, self->data_offset + self->data_size, SEEK_SET);
530 531

	self->frozen = 1;
532
	return 0;
533 534
}

535 536 537
static int perf_header__getbuffer64(struct perf_header *self,
				    int fd, void *buf, size_t size)
{
538
	if (readn(fd, buf, size) <= 0)
539 540 541 542 543 544 545 546
		return -1;

	if (self->needs_swap)
		mem_bswap_64(buf, size);

	return 0;
}

547 548
int perf_header__process_sections(struct perf_header *self, int fd,
				  int (*process)(struct perf_file_section *self,
549
						 struct perf_header *ph,
550
						 int feat, int fd))
551
{
552 553 554 555
	struct perf_file_section *feat_sec;
	int nr_sections;
	int sec_size;
	int idx = 0;
556
	int err = -1, feat = 1;
557 558 559

	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
	if (!nr_sections)
560
		return 0;
561 562 563

	feat_sec = calloc(sizeof(*feat_sec), nr_sections);
	if (!feat_sec)
564
		return -1;
565 566 567

	sec_size = sizeof(*feat_sec) * nr_sections;

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 575 576
	while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
		if (perf_header__has_feat(self, feat)) {
			struct perf_file_section *sec = &feat_sec[idx++];
577

578
			err = process(sec, self, feat, fd);
579 580 581 582
			if (err < 0)
				break;
		}
		++feat;
583
	}
584
out_free:
585 586
	free(feat_sec);
	return err;
587
}
588

589 590 591 592 593
int perf_file_header__read(struct perf_file_header *self,
			   struct perf_header *ph, int fd)
{
	lseek(fd, 0, SEEK_SET);

594
	if (readn(fd, self, sizeof(*self)) <= 0 ||
595
	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
596 597
		return -1;

598 599 600 601 602 603 604 605 606 607 608
	if (self->attr_size != sizeof(struct perf_file_attr)) {
		u64 attr_size = bswap_64(self->attr_size);

		if (attr_size != sizeof(struct perf_file_attr))
			return -1;

		mem_bswap_64(self, offsetof(struct perf_file_header,
					    adds_features));
		ph->needs_swap = true;
	}

609 610 611 612 613 614
	if (self->size != sizeof(*self)) {
		/* Support the previous format */
		if (self->size == offsetof(typeof(*self), adds_features))
			bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
		else
			return -1;
615
	}
616

617
	memcpy(&ph->adds_features, &self->adds_features,
618 619 620 621 622 623 624 625 626 627 628 629
	       sizeof(ph->adds_features));
	/*
	 * FIXME: hack that assumes that if we need swap the perf.data file
	 * may be coming from an arch with a different word-size, ergo different
	 * DEFINE_BITMAP format, investigate more later, but for now its mostly
	 * safe to assume that we have a build-id section. Trace files probably
	 * have several other issues in this realm anyway...
	 */
	if (ph->needs_swap) {
		memset(&ph->adds_features, 0, sizeof(ph->adds_features));
		perf_header__set_feat(ph, HEADER_BUILD_ID);
	}
630 631

	ph->event_offset = self->event_types.offset;
632 633
	ph->event_size   = self->event_types.size;
	ph->data_offset  = self->data.offset;
634 635 636 637
	ph->data_size	 = self->data.size;
	return 0;
}

638 639 640 641 642 643
static int __event_process_build_id(struct build_id_event *bev,
				    char *filename,
				    struct perf_session *session)
{
	int err = -1;
	struct list_head *head;
644
	struct machine *machine;
645 646 647 648
	u16 misc;
	struct dso *dso;
	enum dso_kernel_type dso_type;

649 650
	machine = perf_session__findnew_machine(session, bev->pid);
	if (!machine)
651 652 653 654 655 656 657
		goto out;

	misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

	switch (misc) {
	case PERF_RECORD_MISC_KERNEL:
		dso_type = DSO_TYPE_KERNEL;
658
		head = &machine->kernel_dsos;
659 660 661
		break;
	case PERF_RECORD_MISC_GUEST_KERNEL:
		dso_type = DSO_TYPE_GUEST_KERNEL;
662
		head = &machine->kernel_dsos;
663 664 665 666
		break;
	case PERF_RECORD_MISC_USER:
	case PERF_RECORD_MISC_GUEST_USER:
		dso_type = DSO_TYPE_USER;
667
		head = &machine->user_dsos;
668 669 670 671 672 673 674
		break;
	default:
		goto out;
	}

	dso = __dsos__findnew(head, filename);
	if (dso != NULL) {
T
Tom Zanussi 已提交
675 676
		char sbuild_id[BUILD_ID_SIZE * 2 + 1];

677
		dso__set_build_id(dso, &bev->build_id);
T
Tom Zanussi 已提交
678 679 680 681 682 683 684 685 686

		if (filename[0] == '[')
			dso->kernel = dso_type;

		build_id__sprintf(dso->build_id, sizeof(dso->build_id),
				  sbuild_id);
		pr_debug("build id event received for %s: %s\n",
			 dso->long_name, sbuild_id);
	}
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724

	err = 0;
out:
	return err;
}

static int perf_header__read_build_ids(struct perf_header *self,
			int input, u64 offset, u64 size)
{
	struct perf_session *session = container_of(self,
			struct perf_session, header);
	struct build_id_event bev;
	char filename[PATH_MAX];
	u64 limit = offset + size;
	int err = -1;

	while (offset < limit) {
		ssize_t len;

		if (read(input, &bev, sizeof(bev)) != sizeof(bev))
			goto out;

		if (self->needs_swap)
			perf_event_header__bswap(&bev.header);

		len = bev.header.size - sizeof(bev);
		if (read(input, filename, len) != len)
			goto out;

		__event_process_build_id(&bev, filename, session);

		offset += bev.header.size;
	}
	err = 0;
out:
	return err;
}

725
static int perf_file_section__process(struct perf_file_section *self,
726
				      struct perf_header *ph,
727 728
				      int feat, int fd)
{
729
	if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) {
730 731
		pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
			  "%d, continuing...\n", self->offset, feat);
732 733 734 735 736
		return 0;
	}

	switch (feat) {
	case HEADER_TRACE_INFO:
T
Tom Zanussi 已提交
737
		trace_report(fd, false);
738 739 740
		break;

	case HEADER_BUILD_ID:
741
		if (perf_header__read_build_ids(ph, fd, self->offset, self->size))
742 743 744 745 746 747 748 749
			pr_debug("Failed to read buildids, continuing...\n");
		break;
	default:
		pr_debug("unknown feature %d, continuing...\n", feat);
	}

	return 0;
}
750

751
static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
T
Tom Zanussi 已提交
752 753
				       struct perf_header *ph, int fd,
				       bool repipe)
754
{
755
	if (readn(fd, self, sizeof(*self)) <= 0 ||
756 757 758
	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
		return -1;

T
Tom Zanussi 已提交
759 760 761
	if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0)
		return -1;

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
	if (self->size != sizeof(*self)) {
		u64 size = bswap_64(self->size);

		if (size != sizeof(*self))
			return -1;

		ph->needs_swap = true;
	}

	return 0;
}

static int perf_header__read_pipe(struct perf_session *session, int fd)
{
	struct perf_header *self = &session->header;
	struct perf_pipe_file_header f_header;

T
Tom Zanussi 已提交
779 780
	if (perf_file_header__read_pipe(&f_header, self, fd,
					session->repipe) < 0) {
781 782 783 784 785 786 787 788 789
		pr_debug("incompatible file format\n");
		return -EINVAL;
	}

	session->fd = fd;

	return 0;
}

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 795 796 797
	struct perf_file_attr	f_attr;
	u64			f_id;
	int nr_attrs, nr_ids, i, j;

798 799 800 801
	session->evlist = perf_evlist__new(NULL, NULL);
	if (session->evlist == NULL)
		return -ENOMEM;

802 803 804
	if (session->fd_pipe)
		return perf_header__read_pipe(session, fd);

805 806 807 808
	if (perf_file_header__read(&f_header, self, fd) < 0) {
		pr_debug("incompatible file format\n");
		return -EINVAL;
	}
809 810 811 812 813

	nr_attrs = f_header.attrs.size / sizeof(f_attr);
	lseek(fd, f_header.attrs.offset, SEEK_SET);

	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 824 825 826 827 828 829
		if (evsel == NULL)
			goto out_delete_evlist;
		/*
		 * Do it before so that if perf_evsel__alloc_id fails, this
		 * entry gets purged too at perf_evlist__delete().
		 */
		perf_evlist__add(session->evlist, evsel);
830 831

		nr_ids = f_attr.ids.size / sizeof(u64);
832 833 834 835 836 837 838 839
		/*
		 * We don't have the cpu and thread maps on the header, so
		 * for allocating the perf_sample_id table we fake 1 cpu and
		 * hattr->ids threads.
		 */
		if (perf_evsel__alloc_id(evsel, 1, nr_ids))
			goto out_delete_evlist;

840 841 842
		lseek(fd, f_attr.ids.offset, SEEK_SET);

		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 850 851
		lseek(fd, tmp, SEEK_SET);
	}

852 853 854
	if (f_header.event_types.size) {
		lseek(fd, f_header.event_types.offset, SEEK_SET);
		events = malloc(f_header.event_types.size);
855 856
		if (events == NULL)
			return -ENOMEM;
857 858
		if (perf_header__getbuffer64(self, fd, events,
					     f_header.event_types.size))
859
			goto out_errno;
860 861
		event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
	}
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 870
out_errno:
	return -errno;
871 872 873 874 875

out_delete_evlist:
	perf_evlist__delete(session->evlist);
	session->evlist = NULL;
	return -ENOMEM;
876
}
877

878
u64 perf_evlist__sample_type(struct perf_evlist *evlist)
879
{
880
	struct perf_evsel *pos;
881 882
	u64 type = 0;

883
	list_for_each_entry(pos, &evlist->entries, node) {
884
		if (!type)
885 886
			type = pos->attr.sample_type;
		else if (type != pos->attr.sample_type)
887 888 889 890 891 892
			die("non matching sample_type");
	}

	return type;
}

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 904 905 906 907 908
			die("non matching sample_id_all");
	}

	return value;
}

909 910 911
int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
				perf_event__handler_t process,
				struct perf_session *session)
912
{
913
	union perf_event *ev;
914 915 916 917 918 919 920 921 922 923
	size_t size;
	int err;

	size = sizeof(struct perf_event_attr);
	size = ALIGN(size, sizeof(u64));
	size += sizeof(struct perf_event_header);
	size += ids * sizeof(u64);

	ev = malloc(size);

924 925 926
	if (ev == NULL)
		return -ENOMEM;

927 928 929 930 931 932
	ev->attr.attr = *attr;
	memcpy(ev->attr.id, id, ids * sizeof(u64));

	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
	ev->attr.header.size = size;

933
	err = process(ev, NULL, session);
934 935 936 937 938 939

	free(ev);

	return err;
}

940 941
int perf_session__synthesize_attrs(struct perf_session *session,
				   perf_event__handler_t process)
942
{
943 944
	struct perf_evsel *attr;
	int err = 0;
945

946
	list_for_each_entry(attr, &session->evlist->entries, node) {
947 948
		err = perf_event__synthesize_attr(&attr->attr, attr->ids,
						  attr->id, process, session);
949 950 951 952 953 954 955 956 957
		if (err) {
			pr_debug("failed to create perf header attribute\n");
			return err;
		}
	}

	return err;
}

958 959
int perf_event__process_attr(union perf_event *event,
			     struct perf_session *session)
960 961
{
	unsigned int i, ids, n_ids;
962
	struct perf_evsel *evsel;
963

964 965 966 967 968 969 970 971 972
	if (session->evlist == NULL) {
		session->evlist = perf_evlist__new(NULL, NULL);
		if (session->evlist == NULL)
			return -ENOMEM;
	}

	evsel = perf_evsel__new(&event->attr.attr,
				session->evlist->nr_entries);
	if (evsel == NULL)
973 974
		return -ENOMEM;

975 976
	perf_evlist__add(session->evlist, evsel);

977 978
	ids = event->header.size;
	ids -= (void *)&event->attr.id - (void *)event;
979
	n_ids = ids / sizeof(u64);
980 981 982 983 984 985 986
	/*
	 * We don't have the cpu and thread maps on the header, so
	 * for allocating the perf_sample_id table we fake 1 cpu and
	 * hattr->ids threads.
	 */
	if (perf_evsel__alloc_id(evsel, 1, n_ids))
		return -ENOMEM;
987 988

	for (i = 0; i < n_ids; i++) {
989 990
		perf_evlist__id_add(session->evlist, evsel, 0, i,
				    event->attr.id[i]);
991 992 993 994 995 996
	}

	perf_session__update_sample_type(session);

	return 0;
}
997

998 999 1000
int perf_event__synthesize_event_type(u64 event_id, char *name,
				      perf_event__handler_t process,
				      struct perf_session *session)
1001
{
1002
	union perf_event ev;
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
	size_t size = 0;
	int err = 0;

	memset(&ev, 0, sizeof(ev));

	ev.event_type.event_type.event_id = event_id;
	memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME);
	strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);

	ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
	size = strlen(name);
	size = ALIGN(size, sizeof(u64));
	ev.event_type.header.size = sizeof(ev.event_type) -
		(sizeof(ev.event_type.event_type.name) - size);

1018
	err = process(&ev, NULL, session);
1019 1020 1021 1022

	return err;
}

1023 1024
int perf_event__synthesize_event_types(perf_event__handler_t process,
				       struct perf_session *session)
1025 1026 1027 1028 1029 1030 1031
{
	struct perf_trace_event_type *type;
	int i, err = 0;

	for (i = 0; i < event_count; i++) {
		type = &events[i];

1032 1033 1034
		err = perf_event__synthesize_event_type(type->event_id,
							type->name, process,
							session);
1035 1036 1037 1038 1039 1040 1041 1042 1043
		if (err) {
			pr_debug("failed to create perf header event type\n");
			return err;
		}
	}

	return err;
}

1044 1045
int perf_event__process_event_type(union perf_event *event,
				   struct perf_session *session __unused)
1046
{
1047 1048
	if (perf_header__push_event(event->event_type.event_type.event_id,
				    event->event_type.event_type.name) < 0)
1049 1050 1051 1052
		return -ENOMEM;

	return 0;
}
1053

1054 1055
int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
					 perf_event__handler_t process,
1056 1057
				   struct perf_session *session __unused)
{
1058
	union perf_event ev;
1059
	ssize_t size = 0, aligned_size = 0, padding;
K
Kyle McMartin 已提交
1060
	int err __used = 0;
1061 1062 1063 1064

	memset(&ev, 0, sizeof(ev));

	ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1065
	size = read_tracing_data_size(fd, &evlist->entries);
1066 1067 1068 1069 1070 1071 1072
	if (size <= 0)
		return size;
	aligned_size = ALIGN(size, sizeof(u64));
	padding = aligned_size - size;
	ev.tracing_data.header.size = sizeof(ev.tracing_data);
	ev.tracing_data.size = aligned_size;

1073
	process(&ev, NULL, session);
1074

1075
	err = read_tracing_data(fd, &evlist->entries);
1076 1077 1078 1079 1080
	write_padded(fd, NULL, 0, padding);

	return aligned_size;
}

1081 1082
int perf_event__process_tracing_data(union perf_event *event,
				     struct perf_session *session)
1083
{
1084
	ssize_t size_read, padding, size = event->tracing_data.size;
1085 1086 1087 1088 1089 1090 1091
	off_t offset = lseek(session->fd, 0, SEEK_CUR);
	char buf[BUFSIZ];

	/* setup for reading amidst mmap */
	lseek(session->fd, offset + sizeof(struct tracing_data_event),
	      SEEK_SET);

T
Tom Zanussi 已提交
1092
	size_read = trace_report(session->fd, session->repipe);
1093 1094 1095 1096 1097

	padding = ALIGN(size_read, sizeof(u64)) - size_read;

	if (read(session->fd, buf, padding) < 0)
		die("reading input file");
T
Tom Zanussi 已提交
1098 1099 1100 1101 1102
	if (session->repipe) {
		int retw = write(STDOUT_FILENO, buf, padding);
		if (retw <= 0 || retw != padding)
			die("repiping tracing data padding");
	}
1103 1104 1105 1106 1107 1108

	if (size_read + padding != size)
		die("tracing data size mismatch");

	return size_read + padding;
}
1109

1110 1111 1112 1113
int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
				    perf_event__handler_t process,
				    struct machine *machine,
				    struct perf_session *session)
1114
{
1115
	union perf_event ev;
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
	size_t len;
	int err = 0;

	if (!pos->hit)
		return err;

	memset(&ev, 0, sizeof(ev));

	len = pos->long_name_len + 1;
	len = ALIGN(len, NAME_ALIGN);
	memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
	ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
	ev.build_id.header.misc = misc;
1129
	ev.build_id.pid = machine->pid;
1130 1131 1132
	ev.build_id.header.size = sizeof(ev.build_id) + len;
	memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);

1133
	err = process(&ev, NULL, session);
1134 1135 1136 1137

	return err;
}

1138 1139
int perf_event__process_build_id(union perf_event *event,
				 struct perf_session *session)
1140
{
1141 1142
	__event_process_build_id(&event->build_id,
				 event->build_id.filename,
1143
				 session);
1144 1145
	return 0;
}
1146 1147 1148 1149 1150

void disable_buildid_cache(void)
{
	no_buildid_cache = true;
}