builtin-report.c 31.2 KB
Newer Older
1 2 3 4 5 6 7
/*
 * builtin-report.c
 *
 * Builtin report command: Analyze the perf.data input file,
 * look up and read DSOs and symbol information and display
 * a histogram of results, along various sorting keys.
 */
8
#include "builtin.h"
9

10 11
#include "util/util.h"

12
#include "util/color.h"
13
#include "util/list.h"
14
#include "util/cache.h"
15
#include "util/rbtree.h"
16
#include "util/symbol.h"
17
#include "util/string.h"
18

19 20 21 22 23
#include "perf.h"

#include "util/parse-options.h"
#include "util/parse-events.h"

24 25 26 27
#define SHOW_KERNEL	1
#define SHOW_USER	2
#define SHOW_HV		4

28
static char		const *input_name = "perf.data";
29
static char		*vmlinux = NULL;
30 31 32 33

static char		default_sort_order[] = "comm,dso";
static char		*sort_order = default_sort_order;

34 35 36
static int		input;
static int		show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;

37
static int		dump_trace = 0;
I
Ingo Molnar 已提交
38
#define dprintf(x...)	do { if (dump_trace) printf(x); } while (0)
39
#define cdprintf(x...)	do { if (dump_trace) color_fprintf(stdout, color, x); } while (0)
I
Ingo Molnar 已提交
40

41
static int		verbose;
42 43
#define eprintf(x...)	do { if (verbose) fprintf(stderr, x); } while (0)

44
static int		full_paths;
45

46 47 48
static unsigned long	page_size;
static unsigned long	mmap_window = 32;

49 50
static char		default_parent_pattern[] = "^sys_|^do_page_fault";
static char		*parent_pattern = default_parent_pattern;
51
static regex_t		parent_regex;
52

53 54
static int		exclude_other = 1;

55 56
struct ip_event {
	struct perf_event_header header;
57 58
	u64 ip;
	u32 pid, tid;
59
	unsigned char __more_data[];
60
};
61

62
struct ip_callchain {
63 64
	u64 nr;
	u64 ips[0];
65 66
};

67 68
struct mmap_event {
	struct perf_event_header header;
69 70 71 72
	u32 pid, tid;
	u64 start;
	u64 len;
	u64 pgoff;
73 74
	char filename[PATH_MAX];
};
75

76 77
struct comm_event {
	struct perf_event_header header;
78
	u32 pid, tid;
79 80 81
	char comm[16];
};

82 83
struct fork_event {
	struct perf_event_header header;
84
	u32 pid, ppid;
85 86
};

87
struct period_event {
88
	struct perf_event_header header;
89 90 91
	u64 time;
	u64 id;
	u64 sample_period;
92 93
};

94 95
struct lost_event {
	struct perf_event_header header;
96 97
	u64 id;
	u64 lost;
98 99
};

100 101 102 103 104 105 106
typedef union event_union {
	struct perf_event_header	header;
	struct ip_event			ip;
	struct mmap_event		mmap;
	struct comm_event		comm;
	struct fork_event		fork;
	struct period_event		period;
107
	struct lost_event		lost;
108 109 110 111
} event_t;

static LIST_HEAD(dsos);
static struct dso *kernel_dso;
P
Peter Zijlstra 已提交
112
static struct dso *vdso;
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

static void dsos__add(struct dso *dso)
{
	list_add_tail(&dso->node, &dsos);
}

static struct dso *dsos__find(const char *name)
{
	struct dso *pos;

	list_for_each_entry(pos, &dsos, node)
		if (strcmp(pos->name, name) == 0)
			return pos;
	return NULL;
}

static struct dso *dsos__findnew(const char *name)
{
	struct dso *dso = dsos__find(name);
132
	int nr;
133

134 135 136 137 138 139
	if (dso)
		return dso;

	dso = dso__new(name, 0);
	if (!dso)
		goto out_delete_dso;
140

141
	nr = dso__load(dso, NULL, verbose);
142
	if (nr < 0) {
143
		eprintf("Failed to open: %s\n", name);
144
		goto out_delete_dso;
145
	}
146 147
	if (!nr)
		eprintf("No symbols found in: %s, maybe install a debug package?\n", name);
148 149

	dsos__add(dso);
150 151 152 153 154 155 156 157

	return dso;

out_delete_dso:
	dso__delete(dso);
	return NULL;
}

158
static void dsos__fprintf(FILE *fp)
159 160 161 162 163 164 165
{
	struct dso *pos;

	list_for_each_entry(pos, &dsos, node)
		dso__fprintf(pos, fp);
}

166
static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
P
Peter Zijlstra 已提交
167 168 169 170
{
	return dso__find_symbol(kernel_dso, ip);
}

171 172
static int load_kernel(void)
{
173
	int err;
174

175
	kernel_dso = dso__new("[kernel]", 0);
176
	if (!kernel_dso)
177
		return -1;
178

179
	err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
180 181 182 183 184
	if (err) {
		dso__delete(kernel_dso);
		kernel_dso = NULL;
	} else
		dsos__add(kernel_dso);
185

P
Peter Zijlstra 已提交
186 187 188 189 190 191 192 193
	vdso = dso__new("[vdso]", 0);
	if (!vdso)
		return -1;

	vdso->find_symbol = vdso__find_symbol;

	dsos__add(vdso);

194
	return err;
195 196
}

197 198 199 200 201
static char __cwd[PATH_MAX];
static char *cwd = __cwd;
static int cwdlen;

static int strcommon(const char *pathname)
202 203 204 205 206 207 208 209 210
{
	int n = 0;

	while (pathname[n] == cwd[n] && n < cwdlen)
		++n;

	return n;
}

211 212
struct map {
	struct list_head node;
213 214 215 216
	u64	 start;
	u64	 end;
	u64	 pgoff;
	u64	 (*map_ip)(struct map *, u64);
217 218 219
	struct dso	 *dso;
};

220
static u64 map__map_ip(struct map *map, u64 ip)
P
Peter Zijlstra 已提交
221 222 223 224
{
	return ip - map->start + map->pgoff;
}

225
static u64 vdso__map_ip(struct map *map, u64 ip)
P
Peter Zijlstra 已提交
226 227 228 229
{
	return ip;
}

230 231 232 233 234
static inline int is_anon_memory(const char *filename)
{
     return strcmp(filename, "//anon") == 0;
}

235
static struct map *map__new(struct mmap_event *event)
236 237 238 239
{
	struct map *self = malloc(sizeof(*self));

	if (self != NULL) {
240 241
		const char *filename = event->filename;
		char newfilename[PATH_MAX];
242
		int anon;
243 244

		if (cwd) {
245 246
			int n = strcommon(filename);

247 248 249 250 251 252 253
			if (n == cwdlen) {
				snprintf(newfilename, sizeof(newfilename),
					 ".%s", filename + n);
				filename = newfilename;
			}
		}

254 255 256 257 258 259 260
		anon = is_anon_memory(filename);

		if (anon) {
			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid);
			filename = newfilename;
		}

261 262 263 264
		self->start = event->start;
		self->end   = event->start + event->len;
		self->pgoff = event->pgoff;

265
		self->dso = dsos__findnew(filename);
266 267
		if (self->dso == NULL)
			goto out_delete;
P
Peter Zijlstra 已提交
268

269
		if (self->dso == vdso || anon)
P
Peter Zijlstra 已提交
270 271 272
			self->map_ip = vdso__map_ip;
		else
			self->map_ip = map__map_ip;
273 274 275 276 277 278 279
	}
	return self;
out_delete:
	free(self);
	return NULL;
}

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
static struct map *map__clone(struct map *self)
{
	struct map *map = malloc(sizeof(*self));

	if (!map)
		return NULL;

	memcpy(map, self, sizeof(*self));

	return map;
}

static int map__overlap(struct map *l, struct map *r)
{
	if (l->start > r->start) {
		struct map *t = l;
		l = r;
		r = t;
	}

	if (l->end > r->start)
		return 1;

	return 0;
}
305

306 307
static size_t map__fprintf(struct map *self, FILE *fp)
{
308
	return fprintf(fp, " %Lx-%Lx %Lx %s\n",
309 310 311 312
		       self->start, self->end, self->pgoff, self->dso->name);
}


313
struct thread {
314
	struct rb_node	 rb_node;
315 316 317 318 319 320 321 322 323 324 325
	struct list_head maps;
	pid_t		 pid;
	char		 *comm;
};

static struct thread *thread__new(pid_t pid)
{
	struct thread *self = malloc(sizeof(*self));

	if (self != NULL) {
		self->pid = pid;
P
Peter Zijlstra 已提交
326
		self->comm = malloc(32);
327
		if (self->comm)
P
Peter Zijlstra 已提交
328
			snprintf(self->comm, 32, ":%d", self->pid);
329 330 331 332 333 334 335 336
		INIT_LIST_HEAD(&self->maps);
	}

	return self;
}

static int thread__set_comm(struct thread *self, const char *comm)
{
P
Peter Zijlstra 已提交
337 338
	if (self->comm)
		free(self->comm);
339 340 341 342
	self->comm = strdup(comm);
	return self->comm ? 0 : -ENOMEM;
}

343 344 345 346 347 348 349 350 351 352 353 354
static size_t thread__fprintf(struct thread *self, FILE *fp)
{
	struct map *pos;
	size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);

	list_for_each_entry(pos, &self->maps, node)
		ret += map__fprintf(pos, fp);

	return ret;
}


355
static struct rb_root threads;
356
static struct thread *last_match;
357

358
static struct thread *threads__findnew(pid_t pid)
359
{
360 361 362
	struct rb_node **p = &threads.rb_node;
	struct rb_node *parent = NULL;
	struct thread *th;
363

364 365 366 367 368 369 370 371
	/*
	 * Font-end cache - PID lookups come in blocks,
	 * so most of the time we dont have to look up
	 * the full rbtree:
	 */
	if (last_match && last_match->pid == pid)
		return last_match;

372 373 374
	while (*p != NULL) {
		parent = *p;
		th = rb_entry(parent, struct thread, rb_node);
375

376 377
		if (th->pid == pid) {
			last_match = th;
378
			return th;
379
		}
380

381 382 383 384
		if (pid < th->pid)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
385 386
	}

387 388 389 390
	th = thread__new(pid);
	if (th != NULL) {
		rb_link_node(&th->rb_node, parent, p);
		rb_insert_color(&th->rb_node, &threads);
391
		last_match = th;
392
	}
393

394
	return th;
395 396 397 398
}

static void thread__insert_map(struct thread *self, struct map *map)
{
399 400 401 402
	struct map *pos, *tmp;

	list_for_each_entry_safe(pos, tmp, &self->maps, node) {
		if (map__overlap(pos, map)) {
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
			if (verbose >= 2) {
				printf("overlapping maps:\n");
				map__fprintf(map, stdout);
				map__fprintf(pos, stdout);
			}

			if (map->start <= pos->start && map->end > pos->start)
				pos->start = map->end;

			if (map->end >= pos->end && map->start < pos->end)
				pos->end = map->start;

			if (verbose >= 2) {
				printf("after collision:\n");
				map__fprintf(pos, stdout);
			}

			if (pos->start >= pos->end) {
				list_del_init(&pos->node);
				free(pos);
			}
424 425 426
		}
	}

427 428 429
	list_add_tail(&map->node, &self->maps);
}

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
static int thread__fork(struct thread *self, struct thread *parent)
{
	struct map *map;

	if (self->comm)
		free(self->comm);
	self->comm = strdup(parent->comm);
	if (!self->comm)
		return -ENOMEM;

	list_for_each_entry(map, &parent->maps, node) {
		struct map *new = map__clone(map);
		if (!new)
			return -ENOMEM;
		thread__insert_map(self, new);
	}

	return 0;
}

450
static struct map *thread__find_map(struct thread *self, u64 ip)
451
{
452 453
	struct map *pos;

454 455 456 457 458 459 460 461 462 463
	if (self == NULL)
		return NULL;

	list_for_each_entry(pos, &self->maps, node)
		if (ip >= pos->start && ip <= pos->end)
			return pos;

	return NULL;
}

464 465 466 467 468 469 470 471 472 473 474 475 476 477
static size_t threads__fprintf(FILE *fp)
{
	size_t ret = 0;
	struct rb_node *nd;

	for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
		struct thread *pos = rb_entry(nd, struct thread, rb_node);

		ret += thread__fprintf(pos, fp);
	}

	return ret;
}

478 479 480 481 482 483 484 485 486 487 488 489 490
/*
 * histogram, sorted on item, collects counts
 */

static struct rb_root hist;

struct hist_entry {
	struct rb_node	 rb_node;

	struct thread	 *thread;
	struct map	 *map;
	struct dso	 *dso;
	struct symbol	 *sym;
491
	struct symbol	 *parent;
492
	u64		 ip;
493 494
	char		 level;

495
	u64		 count;
496 497
};

498 499 500 501 502 503 504
/*
 * configurable sorting bits
 */

struct sort_entry {
	struct list_head list;

505 506
	char *header;

507
	int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
P
Peter Zijlstra 已提交
508
	int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
509 510 511
	size_t	(*print)(FILE *fp, struct hist_entry *);
};

512 513 514 515 516 517 518 519 520 521
static int64_t cmp_null(void *l, void *r)
{
	if (!l && !r)
		return 0;
	else if (!l)
		return -1;
	else
		return 1;
}

P
Peter Zijlstra 已提交
522 523
/* --sort pid */

524
static int64_t
525
sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
526
{
527 528 529 530 531 532
	return right->thread->pid - left->thread->pid;
}

static size_t
sort__thread_print(FILE *fp, struct hist_entry *self)
{
533
	return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
534
}
535

536
static struct sort_entry sort_thread = {
537
	.header = "         Command:  Pid",
538 539 540 541
	.cmp	= sort__thread_cmp,
	.print	= sort__thread_print,
};

P
Peter Zijlstra 已提交
542 543
/* --sort comm */

544 545
static int64_t
sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
P
Peter Zijlstra 已提交
546 547 548 549 550 551
{
	return right->thread->pid - left->thread->pid;
}

static int64_t
sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
552 553 554 555
{
	char *comm_l = left->thread->comm;
	char *comm_r = right->thread->comm;

556 557
	if (!comm_l || !comm_r)
		return cmp_null(comm_l, comm_r);
558 559 560 561 562 563 564

	return strcmp(comm_l, comm_r);
}

static size_t
sort__comm_print(FILE *fp, struct hist_entry *self)
{
565
	return fprintf(fp, "%16s", self->thread->comm);
566 567 568
}

static struct sort_entry sort_comm = {
569
	.header		= "         Command",
P
Peter Zijlstra 已提交
570 571 572
	.cmp		= sort__comm_cmp,
	.collapse	= sort__comm_collapse,
	.print		= sort__comm_print,
573 574
};

P
Peter Zijlstra 已提交
575 576
/* --sort dso */

577 578 579 580 581 582
static int64_t
sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
{
	struct dso *dso_l = left->dso;
	struct dso *dso_r = right->dso;

583 584
	if (!dso_l || !dso_r)
		return cmp_null(dso_l, dso_r);
585 586 587 588 589 590 591

	return strcmp(dso_l->name, dso_r->name);
}

static size_t
sort__dso_print(FILE *fp, struct hist_entry *self)
{
592
	if (self->dso)
593
		return fprintf(fp, "%-25s", self->dso->name);
594

595
	return fprintf(fp, "%016llx         ", (u64)self->ip);
596 597 598
}

static struct sort_entry sort_dso = {
599
	.header = "Shared Object            ",
600 601 602 603
	.cmp	= sort__dso_cmp,
	.print	= sort__dso_print,
};

P
Peter Zijlstra 已提交
604 605
/* --sort symbol */

606 607 608
static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
609
	u64 ip_l, ip_r;
610 611 612 613 614 615 616 617 618 619

	if (left->sym == right->sym)
		return 0;

	ip_l = left->sym ? left->sym->start : left->ip;
	ip_r = right->sym ? right->sym->start : right->ip;

	return (int64_t)(ip_r - ip_l);
}

620 621 622 623 624 625
static size_t
sort__sym_print(FILE *fp, struct hist_entry *self)
{
	size_t ret = 0;

	if (verbose)
626
		ret += fprintf(fp, "%#018llx  ", (u64)self->ip);
627

628 629 630 631
	if (self->sym) {
		ret += fprintf(fp, "[%c] %s",
			self->dso == kernel_dso ? 'k' : '.', self->sym->name);
	} else {
632
		ret += fprintf(fp, "%#016llx", (u64)self->ip);
633
	}
634 635 636 637 638

	return ret;
}

static struct sort_entry sort_sym = {
639
	.header = "Symbol",
640 641
	.cmp	= sort__sym_cmp,
	.print	= sort__sym_print,
642 643
};

644
/* --sort parent */
645 646

static int64_t
647
sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
648
{
649 650
	struct symbol *sym_l = left->parent;
	struct symbol *sym_r = right->parent;
651 652 653 654 655 656 657 658

	if (!sym_l || !sym_r)
		return cmp_null(sym_l, sym_r);

	return strcmp(sym_l->name, sym_r->name);
}

static size_t
659
sort__parent_print(FILE *fp, struct hist_entry *self)
660 661 662
{
	size_t ret = 0;

663
	ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
664 665 666 667

	return ret;
}

668 669 670 671
static struct sort_entry sort_parent = {
	.header = "Parent symbol       ",
	.cmp	= sort__parent_cmp,
	.print	= sort__parent_print,
672 673
};

P
Peter Zijlstra 已提交
674
static int sort__need_collapse = 0;
675
static int sort__has_parent = 0;
P
Peter Zijlstra 已提交
676

677
struct sort_dimension {
678 679 680
	char			*name;
	struct sort_entry	*entry;
	int			taken;
681 682 683 684
};

static struct sort_dimension sort_dimensions[] = {
	{ .name = "pid",	.entry = &sort_thread,	},
685
	{ .name = "comm",	.entry = &sort_comm,	},
686
	{ .name = "dso",	.entry = &sort_dso,	},
687
	{ .name = "symbol",	.entry = &sort_sym,	},
688
	{ .name = "parent",	.entry = &sort_parent,	},
689 690
};

691 692
static LIST_HEAD(hist_entry__sort_list);

693 694 695 696 697 698 699 700 701 702
static int sort_dimension__add(char *tok)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
		struct sort_dimension *sd = &sort_dimensions[i];

		if (sd->taken)
			continue;

703
		if (strncasecmp(tok, sd->name, strlen(tok)))
704 705
			continue;

P
Peter Zijlstra 已提交
706 707 708
		if (sd->entry->collapse)
			sort__need_collapse = 1;

709 710
		if (sd->entry == &sort_parent) {
			int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
711 712 713
			if (ret) {
				char err[BUFSIZ];

714 715 716
				regerror(ret, &parent_regex, err, sizeof(err));
				fprintf(stderr, "Invalid regex: %s\n%s",
					parent_pattern, err);
717 718
				exit(-1);
			}
719
			sort__has_parent = 1;
720 721
		}

722 723
		list_add_tail(&sd->entry->list, &hist_entry__sort_list);
		sd->taken = 1;
724

725 726 727 728 729 730
		return 0;
	}

	return -ESRCH;
}

731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
static int64_t
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
{
	struct sort_entry *se;
	int64_t cmp = 0;

	list_for_each_entry(se, &hist_entry__sort_list, list) {
		cmp = se->cmp(left, right);
		if (cmp)
			break;
	}

	return cmp;
}

P
Peter Zijlstra 已提交
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
static int64_t
hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
{
	struct sort_entry *se;
	int64_t cmp = 0;

	list_for_each_entry(se, &hist_entry__sort_list, list) {
		int64_t (*f)(struct hist_entry *, struct hist_entry *);

		f = se->collapse ?: se->cmp;

		cmp = f(left, right);
		if (cmp)
			break;
	}

	return cmp;
}

765
static size_t
766
hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
767 768 769 770
{
	struct sort_entry *se;
	size_t ret;

771 772 773
	if (exclude_other && !self->parent)
		return 0;

774
	if (total_samples) {
775 776 777 778
		double percent = self->count * 100.0 / total_samples;
		char *color = PERF_COLOR_NORMAL;

		/*
779 780 781
		 * We color high-overhead entries in red, mid-overhead
		 * entries in green - and keep the low overhead places
		 * normal:
782
		 */
783
		if (percent >= 5.0) {
784
			color = PERF_COLOR_RED;
785 786 787 788
		} else {
			if (percent >= 0.5)
				color = PERF_COLOR_GREEN;
		}
789 790

		ret = color_fprintf(fp, color, "   %6.2f%%",
791 792
				(self->count * 100.0) / total_samples);
	} else
793
		ret = fprintf(fp, "%12Ld ", self->count);
794

795
	list_for_each_entry(se, &hist_entry__sort_list, list) {
796 797 798
		if (exclude_other && (se == &sort_parent))
			continue;

799
		fprintf(fp, "  ");
800
		ret += se->print(fp, self);
801
	}
802 803 804 805 806 807

	ret += fprintf(fp, "\n");

	return ret;
}

808 809 810 811 812 813
/*
 *
 */

static struct symbol *
resolve_symbol(struct thread *thread, struct map **mapp,
814
	       struct dso **dsop, u64 *ipp)
815 816 817
{
	struct dso *dso = dsop ? *dsop : NULL;
	struct map *map = mapp ? *mapp : NULL;
818
	u64 ip = *ipp;
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847

	if (!thread)
		return NULL;

	if (dso)
		goto got_dso;

	if (map)
		goto got_map;

	map = thread__find_map(thread, ip);
	if (map != NULL) {
		if (mapp)
			*mapp = map;
got_map:
		ip = map->map_ip(map, ip);

		dso = map->dso;
	} else {
		/*
		 * If this is outside of all known maps,
		 * and is a negative address, try to look it
		 * up in the kernel dso, as it might be a
		 * vsyscall (which executes in user-mode):
		 */
		if ((long long)ip < 0)
		dso = kernel_dso;
	}
	dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
848 849
	dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
	*ipp  = ip;
850 851 852 853 854 855 856 857 858 859

	if (dsop)
		*dsop = dso;

	if (!dso)
		return NULL;
got_dso:
	return dso->find_symbol(dso, ip);
}

860
static int call__match(struct symbol *sym)
861
{
862
	if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
863
		return 1;
864

865
	return 0;
866 867
}

868 869 870 871
/*
 * collect histogram counts
 */

872 873
static int
hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
874 875
		struct symbol *sym, u64 ip, struct ip_callchain *chain,
		char level, u64 count)
876
{
877 878 879 880 881 882 883 884 885 886
	struct rb_node **p = &hist.rb_node;
	struct rb_node *parent = NULL;
	struct hist_entry *he;
	struct hist_entry entry = {
		.thread	= thread,
		.map	= map,
		.dso	= dso,
		.sym	= sym,
		.ip	= ip,
		.level	= level,
887
		.count	= count,
888
		.parent = NULL,
889 890 891
	};
	int cmp;

892
	if (sort__has_parent && chain) {
893
		u64 context = PERF_CONTEXT_MAX;
894 895 896
		int i;

		for (i = 0; i < chain->nr; i++) {
897
			u64 ip = chain->ips[i];
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
			struct dso *dso = NULL;
			struct symbol *sym;

			if (ip >= PERF_CONTEXT_MAX) {
				context = ip;
				continue;
			}

			switch (context) {
			case PERF_CONTEXT_KERNEL:
				dso = kernel_dso;
				break;
			default:
				break;
			}

914
			sym = resolve_symbol(thread, NULL, &dso, &ip);
915 916 917 918 919

			if (sym && call__match(sym)) {
				entry.parent = sym;
				break;
			}
920 921 922
		}
	}

923 924 925 926 927 928 929
	while (*p != NULL) {
		parent = *p;
		he = rb_entry(parent, struct hist_entry, rb_node);

		cmp = hist_entry__cmp(&entry, he);

		if (!cmp) {
930
			he->count += count;
931 932 933 934 935 936 937
			return 0;
		}

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
938
	}
939 940 941 942 943 944 945 946 947

	he = malloc(sizeof(*he));
	if (!he)
		return -ENOMEM;
	*he = entry;
	rb_link_node(&he->rb_node, parent, p);
	rb_insert_color(&he->rb_node, &hist);

	return 0;
948 949
}

P
Peter Zijlstra 已提交
950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
static void hist_entry__free(struct hist_entry *he)
{
	free(he);
}

/*
 * collapse the histogram
 */

static struct rb_root collapse_hists;

static void collapse__insert_entry(struct hist_entry *he)
{
	struct rb_node **p = &collapse_hists.rb_node;
	struct rb_node *parent = NULL;
	struct hist_entry *iter;
	int64_t cmp;

	while (*p != NULL) {
		parent = *p;
		iter = rb_entry(parent, struct hist_entry, rb_node);

		cmp = hist_entry__collapse(iter, he);

		if (!cmp) {
			iter->count += he->count;
			hist_entry__free(he);
			return;
		}

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	rb_link_node(&he->rb_node, parent, p);
	rb_insert_color(&he->rb_node, &collapse_hists);
}

static void collapse__resort(void)
{
	struct rb_node *next;
	struct hist_entry *n;

	if (!sort__need_collapse)
		return;

	next = rb_first(&hist);
	while (next) {
		n = rb_entry(next, struct hist_entry, rb_node);
		next = rb_next(&n->rb_node);

		rb_erase(&n->rb_node, &hist);
		collapse__insert_entry(n);
	}
}

1008 1009 1010 1011 1012 1013 1014
/*
 * reverse the map, sort on count.
 */

static struct rb_root output_hists;

static void output__insert_entry(struct hist_entry *he)
1015
{
1016
	struct rb_node **p = &output_hists.rb_node;
1017
	struct rb_node *parent = NULL;
1018
	struct hist_entry *iter;
1019 1020 1021

	while (*p != NULL) {
		parent = *p;
1022
		iter = rb_entry(parent, struct hist_entry, rb_node);
1023

1024
		if (he->count > iter->count)
1025 1026 1027 1028 1029
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

1030 1031
	rb_link_node(&he->rb_node, parent, p);
	rb_insert_color(&he->rb_node, &output_hists);
1032 1033
}

1034
static void output__resort(void)
1035
{
P
Peter Zijlstra 已提交
1036
	struct rb_node *next;
1037
	struct hist_entry *n;
1038
	struct rb_root *tree = &hist;
1039

P
Peter Zijlstra 已提交
1040
	if (sort__need_collapse)
1041 1042 1043
		tree = &collapse_hists;

	next = rb_first(tree);
P
Peter Zijlstra 已提交
1044

1045 1046 1047
	while (next) {
		n = rb_entry(next, struct hist_entry, rb_node);
		next = rb_next(&n->rb_node);
1048

1049
		rb_erase(&n->rb_node, tree);
1050
		output__insert_entry(n);
1051 1052 1053
	}
}

1054
static size_t output__fprintf(FILE *fp, u64 total_samples)
1055
{
1056
	struct hist_entry *pos;
1057
	struct sort_entry *se;
1058 1059 1060
	struct rb_node *nd;
	size_t ret = 0;

1061
	fprintf(fp, "\n");
1062
	fprintf(fp, "#\n");
1063
	fprintf(fp, "# (%Ld samples)\n", (u64)total_samples);
1064 1065 1066
	fprintf(fp, "#\n");

	fprintf(fp, "# Overhead");
1067 1068 1069
	list_for_each_entry(se, &hist_entry__sort_list, list) {
		if (exclude_other && (se == &sort_parent))
			continue;
1070
		fprintf(fp, "  %s", se->header);
1071
	}
1072 1073 1074
	fprintf(fp, "\n");

	fprintf(fp, "# ........");
1075
	list_for_each_entry(se, &hist_entry__sort_list, list) {
1076 1077
		int i;

1078 1079 1080
		if (exclude_other && (se == &sort_parent))
			continue;

1081
		fprintf(fp, "  ");
1082
		for (i = 0; i < strlen(se->header); i++)
1083
			fprintf(fp, ".");
1084
	}
1085 1086 1087
	fprintf(fp, "\n");

	fprintf(fp, "#\n");
1088

1089 1090 1091
	for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
		pos = rb_entry(nd, struct hist_entry, rb_node);
		ret += hist_entry__fprintf(fp, pos, total_samples);
1092 1093
	}

1094 1095
	if (sort_order == default_sort_order &&
			parent_pattern == default_parent_pattern) {
1096
		fprintf(fp, "#\n");
1097
		fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n");
1098 1099
		fprintf(fp, "#\n");
	}
1100
	fprintf(fp, "\n");
1101

1102 1103 1104
	return ret;
}

1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
static void register_idle_thread(void)
{
	struct thread *thread = threads__findnew(0);

	if (thread == NULL ||
			thread__set_comm(thread, "[idle]")) {
		fprintf(stderr, "problem inserting idle task.\n");
		exit(-1);
	}
}

1116 1117 1118 1119
static unsigned long total = 0,
		     total_mmap = 0,
		     total_comm = 0,
		     total_fork = 0,
1120 1121
		     total_unknown = 0,
		     total_lost = 0;
1122

1123
static int validate_chain(struct ip_callchain *chain, event_t *event)
1124 1125 1126 1127 1128 1129
{
	unsigned int chain_size;

	chain_size = event->header.size;
	chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;

1130
	if (chain->nr*sizeof(u64) > chain_size)
1131 1132 1133 1134 1135
		return -1;

	return 0;
}

1136
static int
1137 1138 1139 1140 1141 1142
process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
{
	char level;
	int show = 0;
	struct dso *dso = NULL;
	struct thread *thread = threads__findnew(event->ip.pid);
1143 1144
	u64 ip = event->ip.ip;
	u64 period = 1;
1145
	struct map *map = NULL;
1146
	void *more_data = event->ip.__more_data;
1147
	struct ip_callchain *chain = NULL;
1148

1149
	if (event->header.type & PERF_SAMPLE_PERIOD) {
1150 1151
		period = *(u64 *)more_data;
		more_data += sizeof(u64);
1152
	}
1153

1154
	dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
1155 1156 1157 1158
		(void *)(offset + head),
		(void *)(long)(event->header.size),
		event->header.misc,
		event->ip.pid,
1159
		(void *)(long)ip,
1160
		(long long)period);
1161

1162 1163 1164 1165 1166
	if (event->header.type & PERF_SAMPLE_CALLCHAIN) {
		int i;

		chain = (void *)more_data;

1167
		dprintf("... chain: nr:%Lu\n", chain->nr);
1168

1169 1170 1171 1172 1173 1174
		if (validate_chain(chain, event) < 0) {
			eprintf("call-chain problem with event, skipping it.\n");
			return 0;
		}

		if (dump_trace) {
1175
			for (i = 0; i < chain->nr; i++)
1176
				dprintf("..... %2d: %016Lx\n", i, chain->ips[i]);
1177 1178 1179
		}
	}

1180 1181 1182
	dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);

	if (thread == NULL) {
1183
		eprintf("problem processing %d event, skipping it.\n",
1184 1185 1186
			event->header.type);
		return -1;
	}
1187

1188 1189 1190
	if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
		show = SHOW_KERNEL;
		level = 'k';
1191

1192
		dso = kernel_dso;
1193

1194
		dprintf(" ...... dso: %s\n", dso->name);
1195

1196
	} else if (event->header.misc & PERF_EVENT_MISC_USER) {
1197

1198 1199
		show = SHOW_USER;
		level = '.';
1200

1201 1202 1203 1204 1205
	} else {
		show = SHOW_HV;
		level = 'H';
		dprintf(" ...... dso: [hypervisor]\n");
	}
1206

1207
	if (show & show_mask) {
1208
		struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1209

1210
		if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
1211
			eprintf("problem incrementing symbol count, skipping event\n");
1212
			return -1;
1213
		}
1214
	}
1215
	total += period;
1216

1217 1218
	return 0;
}
I
Ingo Molnar 已提交
1219

1220 1221 1222 1223 1224 1225
static int
process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
{
	struct thread *thread = threads__findnew(event->mmap.pid);
	struct map *map = map__new(&event->mmap);

1226
	dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
1227 1228
		(void *)(offset + head),
		(void *)(long)(event->header.size),
1229
		event->mmap.pid,
1230 1231 1232 1233 1234 1235 1236
		(void *)(long)event->mmap.start,
		(void *)(long)event->mmap.len,
		(void *)(long)event->mmap.pgoff,
		event->mmap.filename);

	if (thread == NULL || map == NULL) {
		dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n");
1237
		return 0;
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
	}

	thread__insert_map(thread, map);
	total_mmap++;

	return 0;
}

static int
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{
	struct thread *thread = threads__findnew(event->comm.pid);

	dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
		(void *)(offset + head),
		(void *)(long)(event->header.size),
		event->comm.comm, event->comm.pid);

	if (thread == NULL ||
	    thread__set_comm(thread, event->comm.comm)) {
		dprintf("problem processing PERF_EVENT_COMM, skipping event.\n");
		return -1;
1260
	}
1261 1262 1263 1264 1265
	total_comm++;

	return 0;
}

1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
static int
process_fork_event(event_t *event, unsigned long offset, unsigned long head)
{
	struct thread *thread = threads__findnew(event->fork.pid);
	struct thread *parent = threads__findnew(event->fork.ppid);

	dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n",
		(void *)(offset + head),
		(void *)(long)(event->header.size),
		event->fork.pid, event->fork.ppid);

	if (!thread || !parent || thread__fork(thread, parent)) {
		dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
		return -1;
	}
	total_fork++;

	return 0;
}

1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
static int
process_period_event(event_t *event, unsigned long offset, unsigned long head)
{
	dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
		(void *)(offset + head),
		(void *)(long)(event->header.size),
		event->period.time,
		event->period.id,
		event->period.sample_period);

	return 0;
}

1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
static int
process_lost_event(event_t *event, unsigned long offset, unsigned long head)
{
	dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
		(void *)(offset + head),
		(void *)(long)(event->header.size),
		event->lost.id,
		event->lost.lost);

	total_lost += event->lost.lost;

	return 0;
}

1313 1314 1315
static void trace_event(event_t *event)
{
	unsigned char *raw_event = (void *)event;
1316
	char *color = PERF_COLOR_BLUE;
1317 1318 1319 1320 1321
	int i, j;

	if (!dump_trace)
		return;

1322 1323
	dprintf(".");
	cdprintf("\n. ... raw event: size %d bytes\n", event->header.size);
1324 1325

	for (i = 0; i < event->header.size; i++) {
1326 1327 1328 1329
		if ((i & 15) == 0) {
			dprintf(".");
			cdprintf("  %04x: ", i);
		}
1330

1331
		cdprintf(" %02x", raw_event[i]);
1332 1333

		if (((i & 15) == 15) || i == event->header.size-1) {
1334
			cdprintf("  ");
1335
			for (j = 0; j < 15-(i & 15); j++)
1336
				cdprintf("   ");
1337
			for (j = 0; j < (i & 15); j++) {
1338
				if (isprint(raw_event[i-15+j]))
1339
					cdprintf("%c", raw_event[i-15+j]);
1340
				else
1341
					cdprintf(".");
1342
			}
1343
			cdprintf("\n");
1344 1345 1346 1347 1348
		}
	}
	dprintf(".\n");
}

1349 1350 1351
static int
process_event(event_t *event, unsigned long offset, unsigned long head)
{
1352 1353
	trace_event(event);

1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
	if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
		return process_overflow_event(event, offset, head);

	switch (event->header.type) {
	case PERF_EVENT_MMAP:
		return process_mmap_event(event, offset, head);

	case PERF_EVENT_COMM:
		return process_comm_event(event, offset, head);

1364 1365 1366
	case PERF_EVENT_FORK:
		return process_fork_event(event, offset, head);

1367 1368
	case PERF_EVENT_PERIOD:
		return process_period_event(event, offset, head);
1369 1370 1371 1372

	case PERF_EVENT_LOST:
		return process_lost_event(event, offset, head);

1373 1374 1375
	/*
	 * We dont process them right now but they are fine:
	 */
1376

1377 1378 1379 1380
	case PERF_EVENT_THROTTLE:
	case PERF_EVENT_UNTHROTTLE:
		return 0;

1381 1382 1383 1384 1385 1386 1387
	default:
		return -1;
	}

	return 0;
}

1388 1389
static struct perf_file_header		file_header;

1390 1391
static int __cmd_report(void)
{
1392
	int ret, rc = EXIT_FAILURE;
1393
	unsigned long offset = 0;
1394
	unsigned long head = sizeof(file_header);
1395 1396 1397
	struct stat stat;
	event_t *event;
	uint32_t size;
1398
	char *buf;
1399 1400 1401 1402 1403

	register_idle_thread();

	input = open(input_name, O_RDONLY);
	if (input < 0) {
1404 1405 1406 1407
		fprintf(stderr, " failed to open file: %s", input_name);
		if (!strcmp(input_name, "perf.data"))
			fprintf(stderr, "  (try 'perf record' first)");
		fprintf(stderr, "\n");
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
		exit(-1);
	}

	ret = fstat(input, &stat);
	if (ret < 0) {
		perror("failed to stat file");
		exit(-1);
	}

	if (!stat.st_size) {
		fprintf(stderr, "zero-sized file, nothing to do!\n");
		exit(0);
	}

1422 1423 1424 1425
	if (read(input, &file_header, sizeof(file_header)) == -1) {
		perror("failed to read file headers");
		exit(-1);
	}
1426 1427 1428 1429 1430 1431 1432

	if (sort__has_parent &&
	    !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) {
		fprintf(stderr, "selected --sort parent, but no callchain data\n");
		exit(-1);
	}

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
	if (load_kernel() < 0) {
		perror("failed to load kernel symbols");
		return EXIT_FAILURE;
	}

	if (!full_paths) {
		if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
			perror("failed to get the current directory");
			return EXIT_FAILURE;
		}
		cwdlen = strlen(cwd);
	} else {
		cwd = NULL;
		cwdlen = 0;
	}
remap:
	buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
			   MAP_SHARED, input, offset);
	if (buf == MAP_FAILED) {
		perror("failed to mmap file");
		exit(-1);
	}

more:
	event = (event_t *)(buf + head);

	size = event->header.size;
	if (!size)
		size = 8;

	if (head + event->header.size >= page_size * mmap_window) {
		unsigned long shift = page_size * (head / page_size);
		int ret;

		ret = munmap(buf, page_size * mmap_window);
		assert(ret == 0);

		offset += shift;
		head -= shift;
		goto remap;
	}

	size = event->header.size;

1477
	dprintf("\n%p [%p]: event: %d\n",
1478 1479 1480 1481
			(void *)(offset + head),
			(void *)(long)event->header.size,
			event->header.type);

1482 1483
	if (!size || process_event(event, offset, head) < 0) {

I
Ingo Molnar 已提交
1484 1485 1486 1487
		dprintf("%p [%p]: skipping unknown header type: %d\n",
			(void *)(offset + head),
			(void *)(long)(event->header.size),
			event->header.type);
1488

1489
		total_unknown++;
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499

		/*
		 * assume we lost track of the stream, check alignment, and
		 * increment a single u64 in the hope to catch on again 'soon'.
		 */

		if (unlikely(head & 7))
			head &= ~7ULL;

		size = 8;
1500
	}
1501

1502
	head += size;
I
Ingo Molnar 已提交
1503

1504 1505 1506
	if (offset + head >= sizeof(file_header) + file_header.data_size)
		goto done;

1507 1508 1509
	if (offset + head < stat.st_size)
		goto more;

1510
done:
1511 1512
	rc = EXIT_SUCCESS;
	close(input);
1513

I
Ingo Molnar 已提交
1514 1515 1516
	dprintf("      IP events: %10ld\n", total);
	dprintf("    mmap events: %10ld\n", total_mmap);
	dprintf("    comm events: %10ld\n", total_comm);
1517
	dprintf("    fork events: %10ld\n", total_fork);
1518
	dprintf("    lost events: %10ld\n", total_lost);
I
Ingo Molnar 已提交
1519
	dprintf(" unknown events: %10ld\n", total_unknown);
1520

I
Ingo Molnar 已提交
1521
	if (dump_trace)
1522 1523
		return 0;

1524 1525 1526
	if (verbose >= 3)
		threads__fprintf(stdout);

1527
	if (verbose >= 2)
1528 1529
		dsos__fprintf(stdout);

P
Peter Zijlstra 已提交
1530
	collapse__resort();
1531 1532
	output__resort();
	output__fprintf(stdout, total);
1533 1534 1535 1536

	return rc;
}

1537 1538 1539 1540 1541 1542 1543 1544
static const char * const report_usage[] = {
	"perf report [<options>] <command>",
	NULL
};

static const struct option options[] = {
	OPT_STRING('i', "input", &input_name, "file",
		    "input file name"),
1545 1546
	OPT_BOOLEAN('v', "verbose", &verbose,
		    "be more verbose (show symbol address, etc)"),
1547 1548
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
		    "dump raw trace in ASCII"),
1549
	OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1550
	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1551
		   "sort by key(s): pid, comm, dso, symbol, parent"),
1552 1553
	OPT_BOOLEAN('P', "full-paths", &full_paths,
		    "Don't shorten the pathnames taking into account the cwd"),
1554 1555
	OPT_STRING('p', "parent", &parent_pattern, "regex",
		   "regex filter to identify parent, see: '--sort parent'"),
1556 1557
	OPT_BOOLEAN('x', "exclude-other", &exclude_other,
		    "Only display entries with parent-match"),
1558 1559 1560
	OPT_END()
};

1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
static void setup_sorting(void)
{
	char *tmp, *tok, *str = strdup(sort_order);

	for (tok = strtok_r(str, ", ", &tmp);
			tok; tok = strtok_r(NULL, ", ", &tmp)) {
		if (sort_dimension__add(tok) < 0) {
			error("Unknown --sort key: `%s'", tok);
			usage_with_options(report_usage, options);
		}
	}

	free(str);
}

1576 1577
int cmd_report(int argc, const char **argv, const char *prefix)
{
1578
	symbol__init();
1579 1580 1581

	page_size = getpagesize();

1582
	argc = parse_options(argc, argv, options, report_usage, 0);
1583

1584 1585
	setup_sorting();

1586 1587 1588 1589 1590
	if (parent_pattern != default_parent_pattern)
		sort_dimension__add("parent");
	else
		exclude_other = 0;

1591 1592 1593 1594 1595 1596
	/*
	 * Any (unrecognized) arguments left?
	 */
	if (argc)
		usage_with_options(report_usage, options);

1597 1598
	setup_pager();

1599 1600
	return __cmd_report();
}