annotate.c 32.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
 *
 * Parts came from builtin-annotate.c, see those files for further
 * copyright notes.
 *
 * Released under the GPL v2. (and only v2, not any later version)
 */

#include "util.h"
#include "build-id.h"
#include "color.h"
#include "cache.h"
#include "symbol.h"
#include "debug.h"
#include "annotate.h"
17
#include "evsel.h"
18
#include <pthread.h>
19
#include <linux/bitops.h>
20

21
const char 	*disassembler_style;
22
const char	*objdump_path;
23

24 25 26
static struct ins *ins__find(const char *name);
static int disasm_line__parse(char *line, char **namep, char **rawp);

27 28
static void ins__delete(struct ins_operands *ops)
{
29 30 31 32
	zfree(&ops->source.raw);
	zfree(&ops->source.name);
	zfree(&ops->target.raw);
	zfree(&ops->target.name);
33 34
}

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
			      struct ins_operands *ops)
{
	return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->raw);
}

int ins__scnprintf(struct ins *ins, char *bf, size_t size,
		  struct ins_operands *ops)
{
	if (ins->ops->scnprintf)
		return ins->ops->scnprintf(ins, bf, size, ops);

	return ins__raw_scnprintf(ins, bf, size, ops);
}

50
static int call__parse(struct ins_operands *ops)
51
{
52 53
	char *endptr, *tok, *name;

54
	ops->target.addr = strtoull(ops->raw, &endptr, 16);
55 56 57 58 59 60 61 62 63 64 65 66

	name = strchr(endptr, '<');
	if (name == NULL)
		goto indirect_call;

	name++;

	tok = strchr(name, '>');
	if (tok == NULL)
		return -1;

	*tok = '\0';
67
	ops->target.name = strdup(name);
68 69
	*tok = '>';

70
	return ops->target.name == NULL ? -1 : 0;
71 72

indirect_call:
73 74 75 76 77 78
	tok = strchr(endptr, '(');
	if (tok != NULL) {
		ops->target.addr = 0;
		return 0;
	}

79 80 81 82
	tok = strchr(endptr, '*');
	if (tok == NULL)
		return -1;

83
	ops->target.addr = strtoull(tok + 1, NULL, 16);
84 85 86
	return 0;
}

87
static int call__scnprintf(struct ins *ins, char *bf, size_t size,
88
			   struct ins_operands *ops)
89
{
90 91
	if (ops->target.name)
		return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->target.name);
92

93 94 95
	if (ops->target.addr == 0)
		return ins__raw_scnprintf(ins, bf, size, ops);

96
	return scnprintf(bf, size, "%-6.6s *%" PRIx64, ins->name, ops->target.addr);
97 98
}

99
static struct ins_ops call_ops = {
100 101
	.parse	   = call__parse,
	.scnprintf = call__scnprintf,
102 103 104 105 106 107 108
};

bool ins__is_call(const struct ins *ins)
{
	return ins->ops == &call_ops;
}

109
static int jump__parse(struct ins_operands *ops)
110
{
111
	const char *s = strchr(ops->raw, '+');
112

113
	ops->target.addr = strtoull(ops->raw, NULL, 16);
114 115

	if (s++ != NULL)
116
		ops->target.offset = strtoull(s, NULL, 16);
117 118
	else
		ops->target.offset = UINT64_MAX;
119 120 121 122

	return 0;
}

123
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
124
			   struct ins_operands *ops)
125
{
126
	return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
127 128
}

129
static struct ins_ops jump_ops = {
130 131
	.parse	   = jump__parse,
	.scnprintf = jump__scnprintf,
132 133 134 135 136 137 138
};

bool ins__is_jump(const struct ins *ins)
{
	return ins->ops == &jump_ops;
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
{
	char *endptr, *name, *t;

	if (strstr(raw, "(%rip)") == NULL)
		return 0;

	*addrp = strtoull(comment, &endptr, 16);
	name = strchr(endptr, '<');
	if (name == NULL)
		return -1;

	name++;

	t = strchr(name, '>');
	if (t == NULL)
		return 0;

	*t = '\0';
	*namep = strdup(name);
	*t = '>';

	return 0;
}

164 165 166 167 168 169 170 171 172 173 174
static int lock__parse(struct ins_operands *ops)
{
	char *name;

	ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
	if (ops->locked.ops == NULL)
		return 0;

	if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
		goto out_free_ops;

N
Namhyung Kim 已提交
175 176 177
	ops->locked.ins = ins__find(name);
	if (ops->locked.ins == NULL)
		goto out_free_ops;
178

N
Namhyung Kim 已提交
179 180
	if (!ops->locked.ins->ops)
		return 0;
181

N
Namhyung Kim 已提交
182 183
	if (ops->locked.ins->ops->parse)
		ops->locked.ins->ops->parse(ops->locked.ops);
184 185 186 187

	return 0;

out_free_ops:
188
	zfree(&ops->locked.ops);
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
	return 0;
}

static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
			   struct ins_operands *ops)
{
	int printed;

	if (ops->locked.ins == NULL)
		return ins__raw_scnprintf(ins, bf, size, ops);

	printed = scnprintf(bf, size, "%-6.6s ", ins->name);
	return printed + ins__scnprintf(ops->locked.ins, bf + printed,
					size - printed, ops->locked.ops);
}

205 206
static void lock__delete(struct ins_operands *ops)
{
207 208 209
	zfree(&ops->locked.ops);
	zfree(&ops->target.raw);
	zfree(&ops->target.name);
210 211
}

212
static struct ins_ops lock_ops = {
213
	.free	   = lock__delete,
214 215 216 217
	.parse	   = lock__parse,
	.scnprintf = lock__scnprintf,
};

218 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
static int mov__parse(struct ins_operands *ops)
{
	char *s = strchr(ops->raw, ','), *target, *comment, prev;

	if (s == NULL)
		return -1;

	*s = '\0';
	ops->source.raw = strdup(ops->raw);
	*s = ',';
	
	if (ops->source.raw == NULL)
		return -1;

	target = ++s;

	while (s[0] != '\0' && !isspace(s[0]))
		++s;
	prev = *s;
	*s = '\0';

	ops->target.raw = strdup(target);
	*s = prev;

	if (ops->target.raw == NULL)
		goto out_free_source;

	comment = strchr(s, '#');
	if (comment == NULL)
		return 0;

	while (comment[0] != '\0' && isspace(comment[0]))
		++comment;

	comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
	comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);

	return 0;

out_free_source:
258
	zfree(&ops->source.raw);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
	return -1;
}

static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
			   struct ins_operands *ops)
{
	return scnprintf(bf, size, "%-6.6s %s,%s", ins->name,
			 ops->source.name ?: ops->source.raw,
			 ops->target.name ?: ops->target.raw);
}

static struct ins_ops mov_ops = {
	.parse	   = mov__parse,
	.scnprintf = mov__scnprintf,
};

275 276 277 278 279 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 305 306 307 308 309 310 311 312 313 314 315
static int dec__parse(struct ins_operands *ops)
{
	char *target, *comment, *s, prev;

	target = s = ops->raw;

	while (s[0] != '\0' && !isspace(s[0]))
		++s;
	prev = *s;
	*s = '\0';

	ops->target.raw = strdup(target);
	*s = prev;

	if (ops->target.raw == NULL)
		return -1;

	comment = strchr(s, '#');
	if (comment == NULL)
		return 0;

	while (comment[0] != '\0' && isspace(comment[0]))
		++comment;

	comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);

	return 0;
}

static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
			   struct ins_operands *ops)
{
	return scnprintf(bf, size, "%-6.6s %s", ins->name,
			 ops->target.name ?: ops->target.raw);
}

static struct ins_ops dec_ops = {
	.parse	   = dec__parse,
	.scnprintf = dec__scnprintf,
};

316 317
static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
			  struct ins_operands *ops __maybe_unused)
318 319 320 321 322 323 324 325
{
	return scnprintf(bf, size, "%-6.6s", "nop");
}

static struct ins_ops nop_ops = {
	.scnprintf = nop__scnprintf,
};

326 327 328 329
/*
 * Must be sorted by name!
 */
static struct ins instructions[] = {
330 331 332 333 334
	{ .name = "add",   .ops  = &mov_ops, },
	{ .name = "addl",  .ops  = &mov_ops, },
	{ .name = "addq",  .ops  = &mov_ops, },
	{ .name = "addw",  .ops  = &mov_ops, },
	{ .name = "and",   .ops  = &mov_ops, },
335
	{ .name = "bts",   .ops  = &mov_ops, },
336 337
	{ .name = "call",  .ops  = &call_ops, },
	{ .name = "callq", .ops  = &call_ops, },
338 339 340 341 342 343
	{ .name = "cmp",   .ops  = &mov_ops, },
	{ .name = "cmpb",  .ops  = &mov_ops, },
	{ .name = "cmpl",  .ops  = &mov_ops, },
	{ .name = "cmpq",  .ops  = &mov_ops, },
	{ .name = "cmpw",  .ops  = &mov_ops, },
	{ .name = "cmpxch", .ops  = &mov_ops, },
344 345
	{ .name = "dec",   .ops  = &dec_ops, },
	{ .name = "decl",  .ops  = &dec_ops, },
346
	{ .name = "imul",  .ops  = &mov_ops, },
347 348
	{ .name = "inc",   .ops  = &dec_ops, },
	{ .name = "incl",  .ops  = &dec_ops, },
349
	{ .name = "ja",	   .ops  = &jump_ops, },
350 351 352 353 354
	{ .name = "jae",   .ops  = &jump_ops, },
	{ .name = "jb",	   .ops  = &jump_ops, },
	{ .name = "jbe",   .ops  = &jump_ops, },
	{ .name = "jc",	   .ops  = &jump_ops, },
	{ .name = "jcxz",  .ops  = &jump_ops, },
355
	{ .name = "je",	   .ops  = &jump_ops, },
356 357 358 359 360
	{ .name = "jecxz", .ops  = &jump_ops, },
	{ .name = "jg",	   .ops  = &jump_ops, },
	{ .name = "jge",   .ops  = &jump_ops, },
	{ .name = "jl",    .ops  = &jump_ops, },
	{ .name = "jle",   .ops  = &jump_ops, },
361 362
	{ .name = "jmp",   .ops  = &jump_ops, },
	{ .name = "jmpq",  .ops  = &jump_ops, },
363 364 365 366 367
	{ .name = "jna",   .ops  = &jump_ops, },
	{ .name = "jnae",  .ops  = &jump_ops, },
	{ .name = "jnb",   .ops  = &jump_ops, },
	{ .name = "jnbe",  .ops  = &jump_ops, },
	{ .name = "jnc",   .ops  = &jump_ops, },
368
	{ .name = "jne",   .ops  = &jump_ops, },
369 370 371 372 373 374 375 376 377 378 379 380 381
	{ .name = "jng",   .ops  = &jump_ops, },
	{ .name = "jnge",  .ops  = &jump_ops, },
	{ .name = "jnl",   .ops  = &jump_ops, },
	{ .name = "jnle",  .ops  = &jump_ops, },
	{ .name = "jno",   .ops  = &jump_ops, },
	{ .name = "jnp",   .ops  = &jump_ops, },
	{ .name = "jns",   .ops  = &jump_ops, },
	{ .name = "jnz",   .ops  = &jump_ops, },
	{ .name = "jo",	   .ops  = &jump_ops, },
	{ .name = "jp",	   .ops  = &jump_ops, },
	{ .name = "jpe",   .ops  = &jump_ops, },
	{ .name = "jpo",   .ops  = &jump_ops, },
	{ .name = "jrcxz", .ops  = &jump_ops, },
382
	{ .name = "js",	   .ops  = &jump_ops, },
383
	{ .name = "jz",	   .ops  = &jump_ops, },
384
	{ .name = "lea",   .ops  = &mov_ops, },
385
	{ .name = "lock",  .ops  = &lock_ops, },
386 387 388 389 390 391 392 393
	{ .name = "mov",   .ops  = &mov_ops, },
	{ .name = "movb",  .ops  = &mov_ops, },
	{ .name = "movdqa",.ops  = &mov_ops, },
	{ .name = "movl",  .ops  = &mov_ops, },
	{ .name = "movq",  .ops  = &mov_ops, },
	{ .name = "movslq", .ops  = &mov_ops, },
	{ .name = "movzbl", .ops  = &mov_ops, },
	{ .name = "movzwl", .ops  = &mov_ops, },
394 395 396
	{ .name = "nop",   .ops  = &nop_ops, },
	{ .name = "nopl",  .ops  = &nop_ops, },
	{ .name = "nopw",  .ops  = &nop_ops, },
397 398 399 400 401
	{ .name = "or",    .ops  = &mov_ops, },
	{ .name = "orl",   .ops  = &mov_ops, },
	{ .name = "test",  .ops  = &mov_ops, },
	{ .name = "testb", .ops  = &mov_ops, },
	{ .name = "testl", .ops  = &mov_ops, },
402
	{ .name = "xadd",  .ops  = &mov_ops, },
403 404
	{ .name = "xbeginl", .ops  = &jump_ops, },
	{ .name = "xbeginq", .ops  = &jump_ops, },
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
};

static int ins__cmp(const void *name, const void *insp)
{
	const struct ins *ins = insp;

	return strcmp(name, ins->name);
}

static struct ins *ins__find(const char *name)
{
	const int nmemb = ARRAY_SIZE(instructions);

	return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp);
}

421
int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
422 423
{
	struct annotation *notes = symbol__annotation(sym);
424 425 426
	pthread_mutex_init(&notes->lock, NULL);
	return 0;
}
427

428
int symbol__alloc_hist(struct symbol *sym)
429 430
{
	struct annotation *notes = symbol__annotation(sym);
431
	const size_t size = symbol__size(sym);
432 433 434 435 436 437 438 439 440 441 442 443
	size_t sizeof_sym_hist;

	/* Check for overflow when calculating sizeof_sym_hist */
	if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64))
		return -1;

	sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));

	/* Check for overflow in zalloc argument */
	if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
				/ symbol_conf.nr_events)
		return -1;
444

445
	notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
446 447 448
	if (notes->src == NULL)
		return -1;
	notes->src->sizeof_sym_hist = sizeof_sym_hist;
449
	notes->src->nr_histograms   = symbol_conf.nr_events;
450 451
	INIT_LIST_HEAD(&notes->src->source);
	return 0;
452 453
}

454 455 456 457
void symbol__annotate_zero_histograms(struct symbol *sym)
{
	struct annotation *notes = symbol__annotation(sym);

458 459 460 461 462
	pthread_mutex_lock(&notes->lock);
	if (notes->src != NULL)
		memset(notes->src->histograms, 0,
		       notes->src->nr_histograms * notes->src->sizeof_sym_hist);
	pthread_mutex_unlock(&notes->lock);
463 464
}

465 466
static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
				      struct annotation *notes, int evidx, u64 addr)
467
{
468
	unsigned offset;
469 470 471 472
	struct sym_hist *h;

	pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));

473 474
	if (addr < sym->start || addr > sym->end)
		return -ERANGE;
475

476 477
	offset = addr - sym->start;
	h = annotation__histogram(notes, evidx);
478 479 480 481
	h->sum++;
	h->addr[offset]++;

	pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
482 483
		  ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
		  addr, addr - sym->start, evidx, h->addr[offset]);
484 485 486
	return 0;
}

487 488
static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
				    int evidx, u64 addr)
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
{
	struct annotation *notes;

	if (sym == NULL || use_browser != 1 || !sort__has_sym)
		return 0;

	notes = symbol__annotation(sym);
	if (notes->src == NULL) {
		if (symbol__alloc_hist(sym) < 0)
			return -ENOMEM;
	}

	return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
}

504 505 506 507 508
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
{
	return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
}

509 510 511 512 513
int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
{
	return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
}

514 515 516 517 518 519 520 521 522 523
static void disasm_line__init_ins(struct disasm_line *dl)
{
	dl->ins = ins__find(dl->name);

	if (dl->ins == NULL)
		return;

	if (!dl->ins->ops)
		return;

524 525
	if (dl->ins->ops->parse)
		dl->ins->ops->parse(&dl->ops);
526 527
}

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
static int disasm_line__parse(char *line, char **namep, char **rawp)
{
	char *name = line, tmp;

	while (isspace(name[0]))
		++name;

	if (name[0] == '\0')
		return -1;

	*rawp = name + 1;

	while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
		++*rawp;

	tmp = (*rawp)[0];
	(*rawp)[0] = '\0';
	*namep = strdup(name);

	if (*namep == NULL)
		goto out_free_name;

	(*rawp)[0] = tmp;

	if ((*rawp)[0] != '\0') {
		(*rawp)++;
		while (isspace((*rawp)[0]))
			++(*rawp);
	}

	return 0;

out_free_name:
561
	zfree(namep);
562 563 564
	return -1;
}

565
static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize)
566
{
567
	struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
568

569 570 571 572
	if (dl != NULL) {
		dl->offset = offset;
		dl->line = strdup(line);
		if (dl->line == NULL)
573
			goto out_delete;
574 575

		if (offset != -1) {
576
			if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
577 578
				goto out_free_line;

579
			disasm_line__init_ins(dl);
580
		}
581 582
	}

583
	return dl;
584 585

out_free_line:
586
	zfree(&dl->line);
587
out_delete:
588
	free(dl);
589
	return NULL;
590 591
}

592
void disasm_line__free(struct disasm_line *dl)
593
{
594 595
	zfree(&dl->line);
	zfree(&dl->name);
596 597 598 599
	if (dl->ins && dl->ins->ops->free)
		dl->ins->ops->free(&dl->ops);
	else
		ins__delete(&dl->ops);
600
	free(dl);
601 602
}

603 604 605 606 607 608 609 610
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
{
	if (raw || !dl->ins)
		return scnprintf(bf, size, "%-6.6s %s", dl->name, dl->ops.raw);

	return ins__scnprintf(dl->ins, bf, size, &dl->ops);
}

611
static void disasm__add(struct list_head *head, struct disasm_line *line)
612 613 614 615
{
	list_add_tail(&line->node, head);
}

616
struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos)
617 618 619 620 621 622 623 624
{
	list_for_each_entry_continue(pos, head, node)
		if (pos->offset >= 0)
			return pos;

	return NULL;
}

625 626
double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
			    s64 end, const char **path)
627 628 629 630
{
	struct source_line *src_line = notes->src->lines;
	double percent = 0.0;

631
	if (src_line) {
632 633 634
		size_t sizeof_src_line = sizeof(*src_line) +
				sizeof(src_line->p) * (src_line->nr_pcnt - 1);

635
		while (offset < end) {
636 637 638
			src_line = (void *)notes->src->lines +
					(sizeof_src_line * offset);

639
			if (*path == NULL)
640
				*path = src_line->path;
641

642 643
			percent += src_line->p[evidx].percent;
			offset++;
644 645
		}
	} else {
646 647 648
		struct sym_hist *h = annotation__histogram(notes, evidx);
		unsigned int hits = 0;

649 650
		while (offset < end)
			hits += h->addr[offset++];
651

652 653 654
		if (h->sum)
			percent = 100.0 * hits / h->sum;
	}
655 656 657 658

	return percent;
}

659
static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
660
		      struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
661
		      int max_lines, struct disasm_line *queue)
662 663 664 665
{
	static const char *prev_line;
	static const char *prev_color;

666
	if (dl->offset != -1) {
667
		const char *path = NULL;
668 669 670
		double percent, max_percent = 0.0;
		double *ppercents = &percent;
		int i, nr_percent = 1;
671 672
		const char *color;
		struct annotation *notes = symbol__annotation(sym);
673
		s64 offset = dl->offset;
674
		const u64 addr = start + offset;
675
		struct disasm_line *next;
676

677
		next = disasm__get_next_ip_line(&notes->src->source, dl);
678

679
		if (perf_evsel__is_group_event(evsel)) {
680 681 682 683 684 685 686 687
			nr_percent = evsel->nr_members;
			ppercents = calloc(nr_percent, sizeof(double));
			if (ppercents == NULL)
				return -1;
		}

		for (i = 0; i < nr_percent; i++) {
			percent = disasm__calc_percent(notes,
688 689 690 691
					notes->src->lines ? i : evsel->idx + i,
					offset,
					next ? next->offset : (s64) len,
					&path);
692 693 694 695 696 697 698

			ppercents[i] = percent;
			if (percent > max_percent)
				max_percent = percent;
		}

		if (max_percent < min_pcnt)
699 700
			return -1;

701
		if (max_lines && printed >= max_lines)
702
			return 1;
703

704 705
		if (queue != NULL) {
			list_for_each_entry_from(queue, &notes->src->source, node) {
706
				if (queue == dl)
707
					break;
708
				disasm_line__print(queue, sym, start, evsel, len,
709 710 711 712
						    0, 0, 1, NULL);
			}
		}

713
		color = get_percent_color(max_percent);
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728

		/*
		 * Also color the filename and line if needed, with
		 * the same color than the percentage. Don't print it
		 * twice for close colored addr with the same filename:line
		 */
		if (path) {
			if (!prev_line || strcmp(prev_line, path)
				       || color != prev_color) {
				color_fprintf(stdout, color, " %s", path);
				prev_line = path;
				prev_color = color;
			}
		}

729 730 731 732 733 734
		for (i = 0; i < nr_percent; i++) {
			percent = ppercents[i];
			color = get_percent_color(percent);
			color_fprintf(stdout, color, " %7.2f", percent);
		}

735
		printf(" :	");
736
		color_fprintf(stdout, PERF_COLOR_MAGENTA, "  %" PRIx64 ":", addr);
737
		color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line);
738 739 740 741

		if (ppercents != &percent)
			free(ppercents);

742
	} else if (max_lines && printed >= max_lines)
743 744
		return 1;
	else {
745 746
		int width = 8;

747 748 749
		if (queue)
			return -1;

750
		if (perf_evsel__is_group_event(evsel))
751 752
			width *= evsel->nr_members;

753
		if (!*dl->line)
754
			printf(" %*s:\n", width, " ");
755
		else
756
			printf(" %*s:	%s\n", width, " ", dl->line);
757
	}
758 759

	return 0;
760 761
}

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
/*
 * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw)
 * which looks like following
 *
 *  0000000000415500 <_init>:
 *    415500:       sub    $0x8,%rsp
 *    415504:       mov    0x2f5ad5(%rip),%rax        # 70afe0 <_DYNAMIC+0x2f8>
 *    41550b:       test   %rax,%rax
 *    41550e:       je     415515 <_init+0x15>
 *    415510:       callq  416e70 <__gmon_start__@plt>
 *    415515:       add    $0x8,%rsp
 *    415519:       retq
 *
 * it will be parsed and saved into struct disasm_line as
 *  <offset>       <name>  <ops.raw>
 *
 * The offset will be a relative offset from the start of the symbol and -1
 * means that it's not a disassembly line so should be treated differently.
 * The ops.raw part will be parsed further according to type of the instruction.
 */
782 783
static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
				      FILE *file, size_t privsize)
784
{
785
	struct annotation *notes = symbol__annotation(sym);
786
	struct disasm_line *dl;
787
	char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
	size_t line_len;
	s64 line_ip, offset = -1;

	if (getline(&line, &line_len, file) < 0)
		return -1;

	if (!line)
		return -1;

	while (line_len != 0 && isspace(line[line_len - 1]))
		line[--line_len] = '\0';

	c = strchr(line, '\n');
	if (c)
		*c = 0;

	line_ip = -1;
N
Namhyung Kim 已提交
805
	parsed_line = line;
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830

	/*
	 * Strip leading spaces:
	 */
	tmp = line;
	while (*tmp) {
		if (*tmp != ' ')
			break;
		tmp++;
	}

	if (*tmp) {
		/*
		 * Parse hexa addresses followed by ':'
		 */
		line_ip = strtoull(tmp, &tmp2, 16);
		if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
			line_ip = -1;
	}

	if (line_ip != -1) {
		u64 start = map__rip_2objdump(map, sym->start),
		    end = map__rip_2objdump(map, sym->end);

		offset = line_ip - start;
831
		if ((u64)line_ip < start || (u64)line_ip > end)
832
			offset = -1;
833 834
		else
			parsed_line = tmp2 + 1;
N
Namhyung Kim 已提交
835
	}
836

837
	dl = disasm_line__new(offset, parsed_line, privsize);
838 839
	free(line);

840
	if (dl == NULL)
841
		return -1;
842

843 844 845 846
	if (dl->ops.target.offset == UINT64_MAX)
		dl->ops.target.offset = dl->ops.target.addr -
					map__rip_2objdump(map, sym->start);

847
	/* kcore has no symbols, so add the call target name */
848
	if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
849 850 851 852 853 854 855 856
		struct addr_map_symbol target = {
			.map = map,
			.addr = dl->ops.target.addr,
		};

		if (!map_groups__find_ams(&target, NULL) &&
		    target.sym->start == target.al_addr)
			dl->ops.target.name = strdup(target.sym->name);
857 858
	}

859
	disasm__add(&notes->src->source, dl);
860 861 862 863

	return 0;
}

864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
static void delete_last_nop(struct symbol *sym)
{
	struct annotation *notes = symbol__annotation(sym);
	struct list_head *list = &notes->src->source;
	struct disasm_line *dl;

	while (!list_empty(list)) {
		dl = list_entry(list->prev, struct disasm_line, node);

		if (dl->ins && dl->ins->ops) {
			if (dl->ins->ops != &nop_ops)
				return;
		} else {
			if (!strstr(dl->line, " nop ") &&
			    !strstr(dl->line, " nopl ") &&
			    !strstr(dl->line, " nopw "))
				return;
		}

		list_del(&dl->node);
		disasm_line__free(dl);
	}
}

888
int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
889 890 891 892 893 894 895 896
{
	struct dso *dso = map->dso;
	char *filename = dso__build_id_filename(dso, NULL, 0);
	bool free_filename = true;
	char command[PATH_MAX * 2];
	FILE *file;
	int err = 0;
	char symfs_filename[PATH_MAX];
897 898
	struct kcore_extract kce;
	bool delete_extract = false;
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921

	if (filename) {
		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
			 symbol_conf.symfs, filename);
	}

	if (filename == NULL) {
		if (dso->has_build_id) {
			pr_err("Can't annotate %s: not enough memory\n",
			       sym->name);
			return -ENOMEM;
		}
		goto fallback;
	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
		   strstr(command, "[kernel.kallsyms]") ||
		   access(symfs_filename, R_OK)) {
		free(filename);
fallback:
		/*
		 * If we don't have build-ids or the build-id file isn't in the
		 * cache, or is just a kallsyms file, well, lets hope that this
		 * DSO is the same as when 'perf record' ran.
		 */
922
		filename = (char *)dso->long_name;
923 924 925 926 927
		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
			 symbol_conf.symfs, filename);
		free_filename = false;
	}

928 929
	if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
	    !dso__is_kcore(dso)) {
930 931 932
		char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
		char *build_id_msg = NULL;

933 934
		if (dso->annotate_warned)
			goto out_free_filename;
935 936 937 938 939 940

		if (dso->has_build_id) {
			build_id__sprintf(dso->build_id,
					  sizeof(dso->build_id), bf + 15);
			build_id_msg = bf;
		}
941 942
		err = -ENOENT;
		dso->annotate_warned = 1;
943 944 945
		pr_err("Can't annotate %s:\n\n"
		       "No vmlinux file%s\nwas found in the path.\n\n"
		       "Please use:\n\n"
946
		       "  perf buildid-cache -vu vmlinux\n\n"
947
		       "or:\n\n"
948
		       "  --vmlinux vmlinux\n",
949
		       sym->name, build_id_msg ?: "");
950 951 952 953 954 955 956 957 958 959
		goto out_free_filename;
	}

	pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
		 filename, sym->name, map->unmap_ip(map, sym->start),
		 map->unmap_ip(map, sym->end));

	pr_debug("annotating [%p] %30s : [%p] %30s\n",
		 dso, dso->long_name, sym, sym->name);

960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
	if (dso__is_kcore(dso)) {
		kce.kcore_filename = symfs_filename;
		kce.addr = map__rip_2objdump(map, sym->start);
		kce.offs = sym->start;
		kce.len = sym->end + 1 - sym->start;
		if (!kcore_extract__create(&kce)) {
			delete_extract = true;
			strlcpy(symfs_filename, kce.extract_filename,
				sizeof(symfs_filename));
			if (free_filename) {
				free(filename);
				free_filename = false;
			}
			filename = symfs_filename;
		}
	}

977
	snprintf(command, sizeof(command),
978
		 "%s %s%s --start-address=0x%016" PRIx64
979
		 " --stop-address=0x%016" PRIx64
980
		 " -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
981
		 objdump_path ? objdump_path : "objdump",
982 983
		 disassembler_style ? "-M " : "",
		 disassembler_style ? disassembler_style : "",
984
		 map__rip_2objdump(map, sym->start),
I
Ingo Molnar 已提交
985
		 map__rip_2objdump(map, sym->end+1),
986 987
		 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
		 symbol_conf.annotate_src ? "-S" : "",
988 989 990 991 992 993 994 995 996
		 symfs_filename, filename);

	pr_debug("Executing: %s\n", command);

	file = popen(command, "r");
	if (!file)
		goto out_free_filename;

	while (!feof(file))
997
		if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
998 999
			break;

1000 1001 1002 1003 1004 1005 1006
	/*
	 * kallsyms does not have symbol sizes so there may a nop at the end.
	 * Remove it.
	 */
	if (dso__is_kcore(dso))
		delete_last_nop(sym);

1007 1008
	pclose(file);
out_free_filename:
1009 1010
	if (delete_extract)
		kcore_extract__delete(&kce);
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
	if (free_filename)
		free(filename);
	return err;
}

static void insert_source_line(struct rb_root *root, struct source_line *src_line)
{
	struct source_line *iter;
	struct rb_node **p = &root->rb_node;
	struct rb_node *parent = NULL;
1021
	int i, ret;
1022 1023 1024 1025 1026

	while (*p != NULL) {
		parent = *p;
		iter = rb_entry(parent, struct source_line, node);

1027 1028
		ret = strcmp(iter->path, src_line->path);
		if (ret == 0) {
1029 1030
			for (i = 0; i < src_line->nr_pcnt; i++)
				iter->p[i].percent_sum += src_line->p[i].percent;
1031 1032 1033 1034 1035 1036 1037 1038 1039
			return;
		}

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

1040 1041
	for (i = 0; i < src_line->nr_pcnt; i++)
		src_line->p[i].percent_sum = src_line->p[i].percent;
1042 1043 1044 1045 1046

	rb_link_node(&src_line->node, parent, p);
	rb_insert_color(&src_line->node, root);
}

1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
static int cmp_source_line(struct source_line *a, struct source_line *b)
{
	int i;

	for (i = 0; i < a->nr_pcnt; i++) {
		if (a->p[i].percent_sum == b->p[i].percent_sum)
			continue;
		return a->p[i].percent_sum > b->p[i].percent_sum;
	}

	return 0;
}

1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
static void __resort_source_line(struct rb_root *root, struct source_line *src_line)
{
	struct source_line *iter;
	struct rb_node **p = &root->rb_node;
	struct rb_node *parent = NULL;

	while (*p != NULL) {
		parent = *p;
		iter = rb_entry(parent, struct source_line, node);

1070
		if (cmp_source_line(src_line, iter))
1071 1072 1073 1074 1075 1076 1077 1078 1079
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	rb_link_node(&src_line->node, parent, p);
	rb_insert_color(&src_line->node, root);
}

1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
{
	struct source_line *src_line;
	struct rb_node *node;

	node = rb_first(src_root);
	while (node) {
		struct rb_node *next;

		src_line = rb_entry(node, struct source_line, node);
		next = rb_next(node);
		rb_erase(node, src_root);

		__resort_source_line(dest_root, src_line);
		node = next;
	}
}

1098 1099 1100
static void symbol__free_source_line(struct symbol *sym, int len)
{
	struct annotation *notes = symbol__annotation(sym);
1101
	struct source_line *src_line = notes->src->lines;
1102
	size_t sizeof_src_line;
1103 1104
	int i;

1105 1106
	sizeof_src_line = sizeof(*src_line) +
			  (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
1107

1108
	for (i = 0; i < len; i++) {
1109
		free_srcline(src_line->path);
1110 1111 1112
		src_line = (void *)src_line + sizeof_src_line;
	}

1113
	zfree(&notes->src->lines);
1114 1115 1116 1117
}

/* Get the filename:line for the colored entries */
static int symbol__get_source_line(struct symbol *sym, struct map *map,
1118
				   struct perf_evsel *evsel,
1119
				   struct rb_root *root, int len)
1120 1121
{
	u64 start;
1122 1123
	int i, k;
	int evidx = evsel->idx;
1124 1125
	struct source_line *src_line;
	struct annotation *notes = symbol__annotation(sym);
1126
	struct sym_hist *h = annotation__histogram(notes, evidx);
1127
	struct rb_root tmp_root = RB_ROOT;
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
	int nr_pcnt = 1;
	u64 h_sum = h->sum;
	size_t sizeof_src_line = sizeof(struct source_line);

	if (perf_evsel__is_group_event(evsel)) {
		for (i = 1; i < evsel->nr_members; i++) {
			h = annotation__histogram(notes, evidx + i);
			h_sum += h->sum;
		}
		nr_pcnt = evsel->nr_members;
		sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->p);
	}
1140

1141
	if (!h_sum)
1142 1143
		return 0;

1144
	src_line = notes->src->lines = calloc(len, sizeof_src_line);
1145
	if (!notes->src->lines)
1146 1147
		return -1;

1148
	start = map__rip_2objdump(map, sym->start);
1149 1150 1151

	for (i = 0; i < len; i++) {
		u64 offset;
1152
		double percent_max = 0.0;
1153

1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
		src_line->nr_pcnt = nr_pcnt;

		for (k = 0; k < nr_pcnt; k++) {
			h = annotation__histogram(notes, evidx + k);
			src_line->p[k].percent = 100.0 * h->addr[i] / h->sum;

			if (src_line->p[k].percent > percent_max)
				percent_max = src_line->p[k].percent;
		}

		if (percent_max <= 0.5)
			goto next;
1166 1167

		offset = start + i;
1168
		src_line->path = get_srcline(map->dso, offset);
1169
		insert_source_line(&tmp_root, src_line);
1170

1171 1172
	next:
		src_line = (void *)src_line + sizeof_src_line;
1173 1174
	}

1175
	resort_source_line(root, &tmp_root);
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
	return 0;
}

static void print_summary(struct rb_root *root, const char *filename)
{
	struct source_line *src_line;
	struct rb_node *node;

	printf("\nSorted summary for file %s\n", filename);
	printf("----------------------------------------------\n\n");

	if (RB_EMPTY_ROOT(root)) {
		printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
		return;
	}

	node = rb_first(root);
	while (node) {
1194
		double percent, percent_max = 0.0;
1195 1196
		const char *color;
		char *path;
1197
		int i;
1198 1199

		src_line = rb_entry(node, struct source_line, node);
1200 1201 1202 1203 1204 1205 1206 1207 1208
		for (i = 0; i < src_line->nr_pcnt; i++) {
			percent = src_line->p[i].percent_sum;
			color = get_percent_color(percent);
			color_fprintf(stdout, color, " %7.2f", percent);

			if (percent > percent_max)
				percent_max = percent;
		}

1209
		path = src_line->path;
1210
		color = get_percent_color(percent_max);
1211
		color_fprintf(stdout, color, " %s\n", path);
1212 1213 1214 1215 1216

		node = rb_next(node);
	}
}

1217
static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1218 1219
{
	struct annotation *notes = symbol__annotation(sym);
1220
	struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1221
	u64 len = symbol__size(sym), offset;
1222 1223 1224 1225 1226 1227 1228 1229

	for (offset = 0; offset < len; ++offset)
		if (h->addr[offset] != 0)
			printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
			       sym->start + offset, h->addr[offset]);
	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
}

1230 1231 1232
int symbol__annotate_printf(struct symbol *sym, struct map *map,
			    struct perf_evsel *evsel, bool full_paths,
			    int min_pcnt, int max_lines, int context)
1233 1234
{
	struct dso *dso = map->dso;
1235 1236
	char *filename;
	const char *d_filename;
1237
	struct annotation *notes = symbol__annotation(sym);
1238
	struct disasm_line *pos, *queue = NULL;
1239
	u64 start = map__rip_2objdump(map, sym->start);
1240
	int printed = 2, queue_len = 0;
1241
	int more = 0;
1242
	u64 len;
1243 1244
	int width = 8;
	int namelen;
1245

1246 1247 1248 1249
	filename = strdup(dso->long_name);
	if (!filename)
		return -ENOMEM;

1250 1251 1252 1253 1254
	if (full_paths)
		d_filename = filename;
	else
		d_filename = basename(filename);

1255
	len = symbol__size(sym);
1256 1257
	namelen = strlen(d_filename);

1258
	if (perf_evsel__is_group_event(evsel))
1259
		width *= evsel->nr_members;
1260

1261 1262 1263 1264
	printf(" %-*.*s|	Source code & Disassembly of %s\n",
	       width, width, "Percent", d_filename);
	printf("-%-*.*s-------------------------------------\n",
	       width+namelen, width+namelen, graph_dotted_line);
1265 1266

	if (verbose)
1267
		symbol__annotate_hits(sym, evsel);
1268

1269
	list_for_each_entry(pos, &notes->src->source, node) {
1270 1271 1272 1273 1274
		if (context && queue == NULL) {
			queue = pos;
			queue_len = 0;
		}

1275
		switch (disasm_line__print(pos, sym, start, evsel, len,
1276 1277
					    min_pcnt, printed, max_lines,
					    queue)) {
1278 1279
		case 0:
			++printed;
1280 1281 1282 1283 1284
			if (context) {
				printed += queue_len;
				queue = NULL;
				queue_len = 0;
			}
1285 1286 1287 1288
			break;
		case 1:
			/* filtered by max_lines */
			++more;
1289
			break;
1290 1291
		case -1:
		default:
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
			/*
			 * Filtered by min_pcnt or non IP lines when
			 * context != 0
			 */
			if (!context)
				break;
			if (queue_len == context)
				queue = list_entry(queue->node.next, typeof(*queue), node);
			else
				++queue_len;
1302 1303 1304 1305
			break;
		}
	}

1306 1307
	free(filename);

1308 1309
	return more;
}
1310

1311 1312 1313 1314 1315
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
{
	struct annotation *notes = symbol__annotation(sym);
	struct sym_hist *h = annotation__histogram(notes, evidx);

1316
	memset(h, 0, notes->src->sizeof_sym_hist);
1317 1318
}

1319
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1320 1321 1322
{
	struct annotation *notes = symbol__annotation(sym);
	struct sym_hist *h = annotation__histogram(notes, evidx);
1323
	int len = symbol__size(sym), offset;
1324 1325

	h->sum = 0;
1326 1327 1328
	for (offset = 0; offset < len; ++offset) {
		h->addr[offset] = h->addr[offset] * 7 / 8;
		h->sum += h->addr[offset];
1329 1330 1331
	}
}

1332
void disasm__purge(struct list_head *head)
1333
{
1334
	struct disasm_line *pos, *n;
1335 1336 1337

	list_for_each_entry_safe(pos, n, head, node) {
		list_del(&pos->node);
1338
		disasm_line__free(pos);
1339 1340 1341
	}
}

1342 1343 1344 1345 1346 1347 1348 1349 1350
static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
{
	size_t printed;

	if (dl->offset == -1)
		return fprintf(fp, "%s\n", dl->line);

	printed = fprintf(fp, "%#" PRIx64 " %s", dl->offset, dl->name);

1351
	if (dl->ops.raw[0] != '\0') {
1352
		printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
1353
				   dl->ops.raw);
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
	}

	return printed + fprintf(fp, "\n");
}

size_t disasm__fprintf(struct list_head *head, FILE *fp)
{
	struct disasm_line *pos;
	size_t printed = 0;

	list_for_each_entry(pos, head, node)
		printed += disasm_line__fprintf(pos, fp);

	return printed;
}

1370 1371 1372
int symbol__tty_annotate(struct symbol *sym, struct map *map,
			 struct perf_evsel *evsel, bool print_lines,
			 bool full_paths, int min_pcnt, int max_lines)
1373 1374 1375 1376 1377
{
	struct dso *dso = map->dso;
	struct rb_root source_line = RB_ROOT;
	u64 len;

1378
	if (symbol__annotate(sym, map, 0) < 0)
1379 1380
		return -1;

1381
	len = symbol__size(sym);
1382 1383

	if (print_lines) {
1384 1385
		symbol__get_source_line(sym, map, evsel, &source_line, len);
		print_summary(&source_line, dso->long_name);
1386 1387
	}

1388
	symbol__annotate_printf(sym, map, evsel, full_paths,
1389
				min_pcnt, max_lines, 0);
1390 1391 1392
	if (print_lines)
		symbol__free_source_line(sym, len);

1393
	disasm__purge(&symbol__annotation(sym)->src->source);
1394

1395 1396
	return 0;
}
1397 1398 1399 1400 1401

int hist_entry__annotate(struct hist_entry *he, size_t privsize)
{
	return symbol__annotate(he->ms.sym, he->ms.map, privsize);
}