22 static struct ins *ins__find(
const char *
name);
23 static int disasm_line__parse(
char *
line,
char **namep,
char **rawp);
33 static int ins__raw_scnprintf(
struct ins *
ins,
char *
bf,
size_t size,
42 if (ins->
ops->scnprintf)
43 return ins->
ops->scnprintf(ins, bf, size, ops);
45 return ins__raw_scnprintf(ins, bf, size, ops);
50 char *endptr, *tok, *
name;
54 name =
strchr(endptr,
'<');
65 ops->
target.name = strdup(name);
85 static int call__scnprintf(
struct ins *
ins,
char *
bf,
size_t size,
92 return ins__raw_scnprintf(ins, bf, size, ops);
97 static struct ins_ops call_ops = {
99 .scnprintf = call__scnprintf,
104 return ins->
ops == &call_ops;
116 ops->
target.offset = UINT64_MAX;
121 static int jump__scnprintf(
struct ins *ins,
char *bf,
size_t size,
127 static struct ins_ops jump_ops = {
128 .parse = jump__parse,
129 .scnprintf = jump__scnprintf,
134 return ins->
ops == &jump_ops;
137 static int comment__symbol(
char *
raw,
char *comment,
u64 *addrp,
char **namep)
139 char *endptr, *
name, *
t;
144 *addrp =
strtoull(comment, &endptr, 16);
145 name =
strchr(endptr,
'<');
156 *namep = strdup(name);
170 if (disasm_line__parse(ops->
raw, &name, &ops->
locked.ops->raw) < 0)
173 ops->
locked.ins = ins__find(name);
177 if (!ops->
locked.ins->ops)
180 if (ops->
locked.ins->ops->parse)
191 static int lock__scnprintf(
struct ins *ins,
char *bf,
size_t size,
197 return ins__raw_scnprintf(ins, bf, size, ops);
201 size - printed, ops->
locked.ops);
211 static struct ins_ops lock_ops = {
212 .free = lock__delete,
213 .parse = lock__parse,
214 .scnprintf = lock__scnprintf,
233 while (s[0] !=
'\0' && !
isspace(s[0]))
242 goto out_free_source;
248 while (comment[0] !=
'\0' &&
isspace(comment[0]))
262 static int mov__scnprintf(
struct ins *ins,
char *bf,
size_t size,
270 static struct ins_ops mov_ops = {
272 .scnprintf = mov__scnprintf,
279 target = s = ops->
raw;
281 while (s[0] !=
'\0' && !
isspace(s[0]))
286 ops->
target.raw = strdup(target);
296 while (comment[0] !=
'\0' &&
isspace(comment[0]))
304 static int dec__scnprintf(
struct ins *ins,
char *bf,
size_t size,
311 static struct ins_ops dec_ops = {
313 .scnprintf = dec__scnprintf,
316 static int nop__scnprintf(
struct ins *ins
__maybe_unused,
char *bf,
size_t size,
319 return scnprintf(bf, size,
"%-6.6s",
"nop");
322 static struct ins_ops nop_ops = {
323 .scnprintf = nop__scnprintf,
329 static struct ins instructions[] = {
330 { .name =
"add", .ops = &mov_ops, },
331 { .name =
"addl", .ops = &mov_ops, },
332 { .name =
"addq", .ops = &mov_ops, },
333 { .name =
"addw", .ops = &mov_ops, },
334 { .name =
"and", .ops = &mov_ops, },
335 { .name =
"bts", .ops = &mov_ops, },
336 { .name =
"call", .ops = &call_ops, },
337 { .name =
"callq", .ops = &call_ops, },
338 { .name =
"cmp", .ops = &mov_ops, },
339 { .name =
"cmpb", .ops = &mov_ops, },
340 { .name =
"cmpl", .ops = &mov_ops, },
341 { .name =
"cmpq", .ops = &mov_ops, },
342 { .name =
"cmpw", .ops = &mov_ops, },
343 { .name =
"cmpxch", .ops = &mov_ops, },
344 { .name =
"dec", .ops = &dec_ops, },
345 { .name =
"decl", .ops = &dec_ops, },
346 { .name =
"imul", .ops = &mov_ops, },
347 { .name =
"inc", .ops = &dec_ops, },
348 { .name =
"incl", .ops = &dec_ops, },
349 { .name =
"ja", .ops = &jump_ops, },
350 { .name =
"jae", .ops = &jump_ops, },
351 { .name =
"jb", .ops = &jump_ops, },
352 { .name =
"jbe", .ops = &jump_ops, },
353 { .name =
"jc", .ops = &jump_ops, },
354 { .name =
"jcxz", .ops = &jump_ops, },
355 { .name =
"je", .ops = &jump_ops, },
356 { .name =
"jecxz", .ops = &jump_ops, },
357 { .name =
"jg", .ops = &jump_ops, },
358 { .name =
"jge", .ops = &jump_ops, },
359 { .name =
"jl", .ops = &jump_ops, },
360 { .name =
"jle", .ops = &jump_ops, },
361 { .name =
"jmp", .ops = &jump_ops, },
362 { .name =
"jmpq", .ops = &jump_ops, },
363 { .name =
"jna", .ops = &jump_ops, },
364 { .name =
"jnae", .ops = &jump_ops, },
365 { .name =
"jnb", .ops = &jump_ops, },
366 { .name =
"jnbe", .ops = &jump_ops, },
367 { .name =
"jnc", .ops = &jump_ops, },
368 { .name =
"jne", .ops = &jump_ops, },
369 { .name =
"jng", .ops = &jump_ops, },
370 { .name =
"jnge", .ops = &jump_ops, },
371 { .name =
"jnl", .ops = &jump_ops, },
372 { .name =
"jnle", .ops = &jump_ops, },
373 { .name =
"jno", .ops = &jump_ops, },
374 { .name =
"jnp", .ops = &jump_ops, },
375 { .name =
"jns", .ops = &jump_ops, },
376 { .name =
"jnz", .ops = &jump_ops, },
377 { .name =
"jo", .ops = &jump_ops, },
378 { .name =
"jp", .ops = &jump_ops, },
379 { .name =
"jpe", .ops = &jump_ops, },
380 { .name =
"jpo", .ops = &jump_ops, },
381 { .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 { .name =
"mov", .ops = &mov_ops, },
387 { .name =
"movb", .ops = &mov_ops, },
388 { .name =
"movdqa",.ops = &mov_ops, },
389 { .name =
"movl", .ops = &mov_ops, },
390 { .name =
"movq", .ops = &mov_ops, },
391 { .name =
"movslq", .ops = &mov_ops, },
392 { .name =
"movzbl", .ops = &mov_ops, },
393 { .name =
"movzwl", .ops = &mov_ops, },
394 { .name =
"nop", .ops = &nop_ops, },
395 { .name =
"nopl", .ops = &nop_ops, },
396 { .name =
"nopw", .ops = &nop_ops, },
397 { .name =
"or", .ops = &mov_ops, },
398 { .name =
"orl", .ops = &mov_ops, },
399 { .name =
"test", .ops = &mov_ops, },
400 { .name =
"testb", .ops = &mov_ops, },
401 { .name =
"testl", .ops = &mov_ops, },
402 { .name =
"xadd", .ops = &mov_ops, },
405 static int ins__cmp(
const void *name,
const void *insp)
407 const struct ins *ins = insp;
412 static struct ins *ins__find(
const char *name)
416 return bsearch(name, instructions, nmemb,
sizeof(
struct ins), ins__cmp);
421 struct annotation *notes = symbol__annotation(sym);
422 pthread_mutex_init(¬es->
lock,
NULL);
428 struct annotation *notes = symbol__annotation(sym);
429 const size_t size = symbol__size(sym);
430 size_t sizeof_sym_hist;
436 sizeof_sym_hist = (
sizeof(
struct sym_hist) + size *
sizeof(
u64));
439 if (sizeof_sym_hist > (
SIZE_MAX -
sizeof(*notes->
src))
446 notes->
src->sizeof_sym_hist = sizeof_sym_hist;
448 INIT_LIST_HEAD(¬es->
src->source);
454 struct annotation *notes = symbol__annotation(sym);
456 pthread_mutex_lock(¬es->
lock);
459 notes->
src->nr_histograms * notes->
src->sizeof_sym_hist);
460 pthread_mutex_unlock(¬es->
lock);
470 notes = symbol__annotation(sym);
476 if (addr < sym->
start || addr > sym->
end)
479 offset = addr - sym->
start;
480 h = annotation__histogram(notes, evidx);
486 addr, addr - sym->
start, evidx, h->
addr[offset]);
500 if (dl->
ins->ops->parse)
501 dl->
ins->ops->parse(&dl->
ops);
504 static int disasm_line__parse(
char *
line,
char **namep,
char **rawp)
506 char *name = line,
tmp;
516 while ((*rawp)[0] !=
'\0' && !
isspace((*rawp)[0]))
521 *namep = strdup(name);
528 if ((*rawp)[0] !=
'\0') {
548 dl->
line = strdup(line);
553 if (disasm_line__parse(dl->
line, &dl->
name, &dl->
ops.raw) < 0)
556 disasm_line__init_ins(dl);
573 if (dl->
ins && dl->
ins->ops->free)
574 dl->
ins->ops->free(&dl->
ops);
576 ins__delete(&dl->
ops);
603 int evidx,
u64 len,
int min_pcnt,
int printed,
606 static const char *prev_line;
607 static const char *prev_color;
611 unsigned int hits = 0;
614 struct annotation *notes = symbol__annotation(sym);
616 struct sym_hist *
h = annotation__histogram(notes, evidx);
623 while (offset < (
s64)len &&
635 if (src_line ==
NULL && h->
sum)
636 percent = 100.0 * hits / h->
sum;
638 if (percent < min_pcnt)
641 if (max_lines && printed >= max_lines)
648 disasm_line__print(queue, sym, start, evidx, len,
661 if (!prev_line ||
strcmp(prev_line, path)
662 || color != prev_color) {
673 }
else if (max_lines && printed >= max_lines)
688 static int symbol__parse_objdump_line(
struct symbol *sym,
struct map *
map,
689 FILE *
file,
size_t privsize)
691 struct annotation *notes = symbol__annotation(sym);
693 char *line =
NULL, *parsed_line, *
tmp, *tmp2, *
c;
695 s64 line_ip, offset = -1;
697 if (getline(&line, &line_len, file) < 0)
703 while (line_len != 0 &&
isspace(line[line_len - 1]))
704 line[--line_len] =
'\0';
728 if (*tmp2 !=
':' || tmp == tmp2 || tmp2[1] ==
'\0')
736 offset = line_ip -
start;
737 if (offset < 0 || (
u64)line_ip >
end)
740 parsed_line = tmp2 + 1;
743 dl = disasm_line__new(offset, parsed_line, privsize);
749 disasm__add(¬es->
src->source, dl);
758 bool free_filename =
true;
765 snprintf(symfs_filename,
sizeof(symfs_filename),
"%s%s",
769 if (filename ==
NULL) {
771 pr_err(
"Can't annotate %s: not enough memory\n",
776 }
else if (readlink(symfs_filename, command,
sizeof(command)) < 0 ||
777 strstr(command,
"[kernel.kallsyms]") ||
778 access(symfs_filename, R_OK)) {
787 snprintf(symfs_filename,
sizeof(symfs_filename),
"%s%s",
789 free_filename =
false;
794 char *build_id_msg =
NULL;
797 goto out_free_filename;
806 pr_err(
"Can't annotate %s:\n\n"
807 "No vmlinux file%s\nwas found in the path.\n\n"
809 " perf buildid-cache -av vmlinux\n\n"
811 " --vmlinux vmlinux\n",
812 sym->
name, build_id_msg ?:
"");
813 goto out_free_filename;
820 pr_debug(
"annotating [%p] %30s : [%p] %30s\n",
824 "%s %s%s --start-address=0x%016" PRIx64
825 " --stop-address=0x%016" PRIx64
826 " -d %s %s -C %s|grep -v %s|expand",
834 symfs_filename, filename);
836 pr_debug(
"Executing: %s\n", command);
838 file = popen(command,
"r");
840 goto out_free_filename;
843 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
869 rb_link_node(&src_line->
node, parent, p);
873 static void symbol__free_source_line(
struct symbol *sym,
int len)
875 struct annotation *notes = symbol__annotation(sym);
879 for (i = 0; i < len; i++)
880 free(src_line[i].path);
887 static int symbol__get_source_line(
struct symbol *sym,
struct map *map,
888 int evidx,
struct rb_root *root,
int len,
895 struct annotation *notes = symbol__annotation(sym);
896 struct sym_hist *h = annotation__histogram(notes, evidx);
901 src_line = notes->
src->lines = calloc(len,
sizeof(
struct source_line));
902 if (!notes->
src->lines)
907 for (i = 0; i < len; i++) {
914 if (src_line[i].percent <= 0.5)
918 sprintf(cmd,
"addr2line -e %s %016" PRIx64, filename, offset);
919 fp = popen(cmd,
"r");
923 if (getline(&path, &line_len, fp) < 0 || !line_len)
926 src_line[
i].
path =
malloc(
sizeof(
char) * line_len + 1);
927 if (!src_line[i].path)
930 strcpy(src_line[i].path, path);
931 insert_source_line(root, &src_line[i]);
940 static void print_summary(
struct rb_root *root,
const char *filename)
945 printf(
"\nSorted summary for file %s\n", filename);
946 printf(
"----------------------------------------------\n\n");
962 path = src_line->
path;
969 static void symbol__annotate_hits(
struct symbol *sym,
int evidx)
971 struct annotation *notes = symbol__annotation(sym);
972 struct sym_hist *h = annotation__histogram(notes, evidx);
975 for (offset = 0; offset < len; ++
offset)
976 if (h->
addr[offset] != 0)
983 bool full_paths,
int min_pcnt,
int max_lines,
988 const char *d_filename;
989 struct annotation *notes = symbol__annotation(sym);
992 int printed = 2, queue_len = 0;
1003 d_filename = basename(filename);
1005 len = symbol__size(sym);
1007 printf(
" Percent | Source code & Disassembly of %s\n", d_filename);
1008 printf(
"------------------------------------------------\n");
1011 symbol__annotate_hits(sym, evidx);
1014 if (context && queue ==
NULL) {
1019 switch (disasm_line__print(pos, sym, start, evidx, len,
1020 min_pcnt, printed, max_lines,
1025 printed += queue_len;
1042 if (queue_len == context)
1057 struct annotation *notes = symbol__annotation(sym);
1058 struct sym_hist *h = annotation__histogram(notes, evidx);
1060 memset(h, 0, notes->
src->sizeof_sym_hist);
1065 struct annotation *notes = symbol__annotation(sym);
1066 struct sym_hist *h = annotation__histogram(notes, evidx);
1067 int len = symbol__size(sym),
offset;
1070 for (offset = 0; offset < len; ++
offset) {
1086 static size_t disasm_line__fprintf(
struct disasm_line *dl, FILE *fp)
1095 if (dl->
ops.raw[0] !=
'\0') {
1096 printed +=
fprintf(fp,
"%.*s %s\n", 6 - (
int)printed,
" ",
1100 return printed +
fprintf(fp,
"\n");
1109 printed += disasm_line__fprintf(pos, fp);
1115 bool print_lines,
bool full_paths,
int min_pcnt,
1126 len = symbol__size(sym);
1129 symbol__get_source_line(sym, map, evidx, &source_line,
1131 print_summary(&source_line, filename);
1135 min_pcnt, max_lines, 0);
1137 symbol__free_source_line(sym, len);