header.c 14.0 KB
Newer Older
1 2 3 4
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
5
#include <linux/list.h>
6 7 8

#include "util.h"
#include "header.h"
9 10
#include "../perf.h"
#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 21
{
	struct perf_header_attr *self = malloc(sizeof(*self));

22 23 24 25 26 27 28 29 30 31
	if (self != NULL) {
		self->attr = *attr;
		self->ids  = 0;
		self->size = 1;
		self->id   = malloc(sizeof(u64));
		if (self->id == NULL) {
			free(self);
			self = NULL;
		}
	}
32 33 34 35

	return self;
}

36 37 38 39 40 41
void perf_header_attr__delete(struct perf_header_attr *self)
{
	free(self->id);
	free(self);
}

42
int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
43 44 45 46 47
{
	int pos = self->ids;

	self->ids++;
	if (self->ids > self->size) {
48 49 50 51 52 53 54 55
		int nsize = self->size * 2;
		u64 *nid = realloc(self->id, nsize * sizeof(u64));

		if (nid == NULL)
			return -1;

		self->size = nsize;
		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 64 65
	self->size = 1;
	self->attr = malloc(sizeof(void *));
	return self->attr == NULL ? -ENOMEM : 0;
66 67
}

68
void perf_header__exit(struct perf_header *self)
69 70 71
{
	int i;
	for (i = 0; i < self->attrs; ++i)
72
                perf_header_attr__delete(self->attr[i]);
73 74 75
	free(self->attr);
}

76 77
int perf_header__add_attr(struct perf_header *self,
			  struct perf_header_attr *attr)
78 79
{
	if (self->frozen)
80
		return -1;
81

82
	if (self->attrs == self->size) {
83 84 85 86 87 88 89 90 91
		int nsize = self->size * 2;
		struct perf_header_attr **nattr;

		nattr = realloc(self->attr, nsize * sizeof(void *));
		if (nattr == NULL)
			return -1;

		self->size = nsize;
		self->attr = nattr;
92
	}
93 94

	self->attr[self->attrs++] = attr;
95
	return 0;
96 97
}

98 99
#define MAX_EVENT_NAME 64

100 101
struct perf_trace_event_type {
	u64	event_id;
102
	char	name[MAX_EVENT_NAME];
103 104 105 106 107
};

static int event_count;
static struct perf_trace_event_type *events;

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 114

	if (!events) {
		events = malloc(sizeof(struct perf_trace_event_type));
115 116
		if (events == NULL)
			return -ENOMEM;
117
	} else {
118 119 120 121 122 123
		struct perf_trace_event_type *nevents;

		nevents = realloc(events, (event_count + 1) * sizeof(*events));
		if (nevents == NULL)
			return -ENOMEM;
		events = nevents;
124 125 126
	}
	memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
	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 133 134 135 136 137 138 139 140 141
}

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;
}

142 143 144 145 146
static const char *__perf_magic = "PERFFILE";

#define PERF_MAGIC	(*(u64 *)__perf_magic)

struct perf_file_attr {
147
	struct perf_event_attr	attr;
148 149 150
	struct perf_file_section	ids;
};

151 152 153 154 155 156 157 158 159 160
void perf_header__set_feat(struct perf_header *self, int feat)
{
	set_bit(feat, self->adds_features);
}

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

161
static int do_write(int fd, const void *buf, size_t size)
162 163 164 165 166
{
	while (size) {
		int ret = write(fd, buf, size);

		if (ret < 0)
167
			return -errno;
168 169 170 171

		size -= ret;
		buf += ret;
	}
172 173

	return 0;
174 175
}

176 177 178 179 180 181
#define dsos__for_each_with_build_id(pos, head)	\
	list_for_each_entry(pos, head, node)	\
		if (!pos->has_build_id)		\
			continue;		\
		else

182
static int __dsos__write_buildid_table(struct list_head *head, int fd)
183
{
O
OGAWA Hirofumi 已提交
184
#define NAME_ALIGN	64
185
	struct dso *pos;
O
OGAWA Hirofumi 已提交
186
	static const char zero_buf[NAME_ALIGN];
187

188
	dsos__for_each_with_build_id(pos, head) {
189
		int err;
190
		struct build_id_event b;
191
		size_t len = pos->long_name_len + 1;
192

O
OGAWA Hirofumi 已提交
193
		len = ALIGN(len, NAME_ALIGN);
194 195 196
		memset(&b, 0, sizeof(b));
		memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
		b.header.size = sizeof(b) + len;
197 198 199
		err = do_write(fd, &b, sizeof(b));
		if (err < 0)
			return err;
O
OGAWA Hirofumi 已提交
200 201 202
		err = do_write(fd, pos->long_name, pos->long_name_len + 1);
		if (err < 0)
			return err;
203
		err = do_write(fd, zero_buf, len - pos->long_name_len - 1);
204 205
		if (err < 0)
			return err;
206
	}
207 208

	return 0;
209 210
}

211 212 213 214 215 216 217 218
static int dsos__write_buildid_table(int fd)
{
	int err = __dsos__write_buildid_table(&dsos__kernel, fd);
	if (err == 0)
		err = __dsos__write_buildid_table(&dsos__user, fd);
	return err;
}

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 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
static int dso__cache_build_id(struct dso *self, const char *debugdir)
{
	const size_t size = PATH_MAX;
	char *filename = malloc(size),
	     *linkname = malloc(size), *targetname, *sbuild_id;
	int len, err = -1;

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

	len = snprintf(filename, size, "%s%s", debugdir, self->long_name);
	if (mkdir_p(filename, 0755))
		goto out_free;

	len += snprintf(filename + len, sizeof(filename) - len, "/");
	sbuild_id = filename + len;
	build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);

	if (access(filename, F_OK) && link(self->long_name, filename) &&
	    copyfile(self->long_name, filename))
		goto out_free;

	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:
	free(filename);
	free(linkname);
	return err;
}

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;
}

static int dsos__cache_build_ids(void)
{
	int err_kernel, err_user;
	char debugdir[PATH_MAX];

	snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"),
		 DEBUG_CACHE_DIR);

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

	err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir);
	err_user   = __dsos__cache_build_ids(&dsos__user, debugdir);
	return err_kernel || err_user ? -1 : 0;
}

287
static int perf_header__adds_write(struct perf_header *self, int fd)
288
{
289 290 291 292
	int nr_sections;
	struct perf_file_section *feat_sec;
	int sec_size;
	u64 sec_start;
293
	int idx = 0, err;
294

295
	if (dsos__read_build_ids())
296 297 298 299
		perf_header__set_feat(self, HEADER_BUILD_ID);

	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
	if (!nr_sections)
300
		return 0;
301 302

	feat_sec = calloc(sizeof(*feat_sec), nr_sections);
303 304
	if (feat_sec == NULL)
		return -ENOMEM;
305 306 307 308 309

	sec_size = sizeof(*feat_sec) * nr_sections;

	sec_start = self->data_offset + self->data_size;
	lseek(fd, sec_start + sec_size, SEEK_SET);
310

311
	if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
312 313 314 315
		struct perf_file_section *trace_sec;

		trace_sec = &feat_sec[idx++];

316
		/* Write trace info */
317
		trace_sec->offset = lseek(fd, 0, SEEK_CUR);
318
		read_tracing_data(fd, attrs, nr_counters);
319
		trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
320
	}
321

322

323 324 325 326 327 328 329
	if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
		struct perf_file_section *buildid_sec;

		buildid_sec = &feat_sec[idx++];

		/* Write build-ids */
		buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
330 331 332 333 334
		err = dsos__write_buildid_table(fd);
		if (err < 0) {
			pr_debug("failed to write buildid table\n");
			goto out_free;
		}
335
		buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset;
336
		dsos__cache_build_ids();
337
	}
338 339

	lseek(fd, sec_start, SEEK_SET);
340 341 342 343
	err = do_write(fd, feat_sec, sec_size);
	if (err < 0)
		pr_debug("failed to write feature section\n");
out_free:
344
	free(feat_sec);
345
	return err;
346
}
347

348
int perf_header__write(struct perf_header *self, int fd, bool at_exit)
349 350 351 352
{
	struct perf_file_header f_header;
	struct perf_file_attr   f_attr;
	struct perf_header_attr	*attr;
353
	int i, err;
354 355 356 357 358 359 360 361

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


	for (i = 0; i < self->attrs; i++) {
		attr = self->attr[i];

		attr->id_offset = lseek(fd, 0, SEEK_CUR);
362 363 364 365 366
		err = do_write(fd, attr->id, attr->ids * sizeof(u64));
		if (err < 0) {
			pr_debug("failed to write perf header\n");
			return err;
		}
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
	}


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

	for (i = 0; i < self->attrs; i++) {
		attr = self->attr[i];

		f_attr = (struct perf_file_attr){
			.attr = attr->attr,
			.ids  = {
				.offset = attr->id_offset,
				.size   = attr->ids * sizeof(u64),
			}
		};
382 383 384 385 386
		err = do_write(fd, &f_attr, sizeof(f_attr));
		if (err < 0) {
			pr_debug("failed to write perf header attribute\n");
			return err;
		}
387 388
	}

389 390
	self->event_offset = lseek(fd, 0, SEEK_CUR);
	self->event_size = event_count * sizeof(struct perf_trace_event_type);
391 392 393 394 395 396 397
	if (events) {
		err = do_write(fd, events, self->event_size);
		if (err < 0) {
			pr_debug("failed to write perf header events\n");
			return err;
		}
	}
398

399 400
	self->data_offset = lseek(fd, 0, SEEK_CUR);

401 402 403 404 405
	if (at_exit) {
		err = perf_header__adds_write(self, fd);
		if (err < 0)
			return err;
	}
406

407 408 409 410 411 412 413 414 415 416 417 418
	f_header = (struct perf_file_header){
		.magic	   = PERF_MAGIC,
		.size	   = sizeof(f_header),
		.attr_size = sizeof(f_attr),
		.attrs = {
			.offset = self->attr_offset,
			.size   = self->attrs * sizeof(f_attr),
		},
		.data = {
			.offset = self->data_offset,
			.size	= self->data_size,
		},
419 420 421 422
		.event_types = {
			.offset = self->event_offset,
			.size	= self->event_size,
		},
423 424
	};

425
	memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
426

427
	lseek(fd, 0, SEEK_SET);
428 429 430 431 432
	err = do_write(fd, &f_header, sizeof(f_header));
	if (err < 0) {
		pr_debug("failed to write perf header\n");
		return err;
	}
433 434 435
	lseek(fd, self->data_offset + self->data_size, SEEK_SET);

	self->frozen = 1;
436
	return 0;
437 438
}

439
static int do_read(int fd, void *buf, size_t size)
440 441 442 443
{
	while (size) {
		int ret = read(fd, buf, size);

444 445
		if (ret <= 0)
			return -1;
446 447 448 449

		size -= ret;
		buf += ret;
	}
450 451

	return 0;
452 453
}

454 455 456
int perf_header__process_sections(struct perf_header *self, int fd,
				  int (*process)(struct perf_file_section *self,
						 int feat, int fd))
457
{
458 459 460 461
	struct perf_file_section *feat_sec;
	int nr_sections;
	int sec_size;
	int idx = 0;
462
	int err = -1, feat = 1;
463 464 465

	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
	if (!nr_sections)
466
		return 0;
467 468 469

	feat_sec = calloc(sizeof(*feat_sec), nr_sections);
	if (!feat_sec)
470
		return -1;
471 472 473 474 475

	sec_size = sizeof(*feat_sec) * nr_sections;

	lseek(fd, self->data_offset + self->data_size, SEEK_SET);

476 477
	if (do_read(fd, feat_sec, sec_size))
		goto out_free;
478

479
	err = 0;
480 481 482
	while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
		if (perf_header__has_feat(self, feat)) {
			struct perf_file_section *sec = &feat_sec[idx++];
483

484 485 486 487 488
			err = process(sec, feat, fd);
			if (err < 0)
				break;
		}
		++feat;
489
	}
490
out_free:
491 492
	free(feat_sec);
	return err;
493
}
494

495 496 497 498 499
int perf_file_header__read(struct perf_file_header *self,
			   struct perf_header *ph, int fd)
{
	lseek(fd, 0, SEEK_SET);

500 501
	if (do_read(fd, self, sizeof(*self)) ||
	    self->magic     != PERF_MAGIC ||
502 503 504 505 506 507 508 509 510
	    self->attr_size != sizeof(struct perf_file_attr))
		return -1;

	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;
511
	}
512

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
	memcpy(&ph->adds_features, &self->adds_features,
	       sizeof(self->adds_features));

	ph->event_offset = self->event_types.offset;
	ph->event_size	 = self->event_types.size;
	ph->data_offset	 = self->data.offset;
	ph->data_size	 = self->data.size;
	return 0;
}

static int perf_file_section__process(struct perf_file_section *self,
				      int feat, int fd)
{
	if (lseek(fd, self->offset, SEEK_SET) < 0) {
		pr_debug("Failed to lseek to %Ld offset for feature %d, "
			 "continuing...\n", self->offset, feat);
		return 0;
	}

	switch (feat) {
	case HEADER_TRACE_INFO:
		trace_report(fd);
		break;

	case HEADER_BUILD_ID:
		if (perf_header__read_build_ids(fd, self->offset, self->size))
			pr_debug("Failed to read buildids, continuing...\n");
		break;
	default:
		pr_debug("unknown feature %d, continuing...\n", feat);
	}

	return 0;
}
547

548
int perf_header__read(struct perf_header *self, int fd)
549 550 551 552 553 554
{
	struct perf_file_header f_header;
	struct perf_file_attr	f_attr;
	u64			f_id;
	int nr_attrs, nr_ids, i, j;

555 556 557 558
	if (perf_file_header__read(&f_header, self, fd) < 0) {
		pr_debug("incompatible file format\n");
		return -EINVAL;
	}
559 560 561 562 563 564

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

	for (i = 0; i < nr_attrs; i++) {
		struct perf_header_attr *attr;
565
		off_t tmp;
566

567 568
		if (do_read(fd, &f_attr, sizeof(f_attr)))
			goto out_errno;
569
		tmp = lseek(fd, 0, SEEK_CUR);
570 571

		attr = perf_header_attr__new(&f_attr.attr);
572
		if (attr == NULL)
573
			 return -ENOMEM;
574 575 576 577 578

		nr_ids = f_attr.ids.size / sizeof(u64);
		lseek(fd, f_attr.ids.offset, SEEK_SET);

		for (j = 0; j < nr_ids; j++) {
579 580
			if (do_read(fd, &f_id, sizeof(f_id)))
				goto out_errno;
581

582 583 584 585 586 587 588 589
			if (perf_header_attr__add_id(attr, f_id) < 0) {
				perf_header_attr__delete(attr);
				return -ENOMEM;
			}
		}
		if (perf_header__add_attr(self, attr) < 0) {
			perf_header_attr__delete(attr);
			return -ENOMEM;
590
		}
591

592 593 594
		lseek(fd, tmp, SEEK_SET);
	}

595 596 597
	if (f_header.event_types.size) {
		lseek(fd, f_header.event_types.offset, SEEK_SET);
		events = malloc(f_header.event_types.size);
598 599
		if (events == NULL)
			return -ENOMEM;
600 601
		if (do_read(fd, events, f_header.event_types.size))
			goto out_errno;
602 603
		event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
	}
604

605
	perf_header__process_sections(self, fd, perf_file_section__process);
606

607
	lseek(fd, self->data_offset, SEEK_SET);
608 609

	self->frozen = 1;
610
	return 0;
611 612
out_errno:
	return -errno;
613
}
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631

u64 perf_header__sample_type(struct perf_header *header)
{
	u64 type = 0;
	int i;

	for (i = 0; i < header->attrs; i++) {
		struct perf_header_attr *attr = header->attr[i];

		if (!type)
			type = attr->attr.sample_type;
		else if (type != attr->attr.sample_type)
			die("non matching sample_type");
	}

	return type;
}

632
struct perf_event_attr *
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
perf_header__find_attr(u64 id, struct perf_header *header)
{
	int i;

	for (i = 0; i < header->attrs; i++) {
		struct perf_header_attr *attr = header->attr[i];
		int j;

		for (j = 0; j < attr->ids; j++) {
			if (attr->id[j] == id)
				return &attr->attr;
		}
	}

	return NULL;
}