1 /* 2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 3 * 4 * Parts came from builtin-annotate.c, see those files for further 5 * copyright notes. 6 * 7 * Released under the GPL v2. (and only v2, not any later version) 8 */ 9 10 #include "util.h" 11 #include "build-id.h" 12 #include "color.h" 13 #include "cache.h" 14 #include "symbol.h" 15 #include "debug.h" 16 #include "annotate.h" 17 #include <pthread.h> 18 19 const char *disassembler_style; 20 21 int symbol__annotate_init(struct map *map __used, struct symbol *sym) 22 { 23 struct annotation *notes = symbol__annotation(sym); 24 pthread_mutex_init(¬es->lock, NULL); 25 return 0; 26 } 27 28 int symbol__alloc_hist(struct symbol *sym) 29 { 30 struct annotation *notes = symbol__annotation(sym); 31 const size_t size = sym->end - sym->start + 1; 32 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 33 34 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); 35 if (notes->src == NULL) 36 return -1; 37 notes->src->sizeof_sym_hist = sizeof_sym_hist; 38 notes->src->nr_histograms = symbol_conf.nr_events; 39 INIT_LIST_HEAD(¬es->src->source); 40 return 0; 41 } 42 43 void symbol__annotate_zero_histograms(struct symbol *sym) 44 { 45 struct annotation *notes = symbol__annotation(sym); 46 47 pthread_mutex_lock(¬es->lock); 48 if (notes->src != NULL) 49 memset(notes->src->histograms, 0, 50 notes->src->nr_histograms * notes->src->sizeof_sym_hist); 51 pthread_mutex_unlock(¬es->lock); 52 } 53 54 int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 55 int evidx, u64 addr) 56 { 57 unsigned offset; 58 struct annotation *notes; 59 struct sym_hist *h; 60 61 notes = symbol__annotation(sym); 62 if (notes->src == NULL) 63 return -ENOMEM; 64 65 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 66 67 if (addr < sym->start || addr > sym->end) 68 return -ERANGE; 69 70 offset = addr - sym->start; 71 h = annotation__histogram(notes, evidx); 72 h->sum++; 73 h->addr[offset]++; 74 75 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 76 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 77 addr, addr - sym->start, evidx, h->addr[offset]); 78 return 0; 79 } 80 81 static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize) 82 { 83 struct objdump_line *self = malloc(sizeof(*self) + privsize); 84 85 if (self != NULL) { 86 self->offset = offset; 87 self->line = line; 88 } 89 90 return self; 91 } 92 93 void objdump_line__free(struct objdump_line *self) 94 { 95 free(self->line); 96 free(self); 97 } 98 99 static void objdump__add_line(struct list_head *head, struct objdump_line *line) 100 { 101 list_add_tail(&line->node, head); 102 } 103 104 struct objdump_line *objdump__get_next_ip_line(struct list_head *head, 105 struct objdump_line *pos) 106 { 107 list_for_each_entry_continue(pos, head, node) 108 if (pos->offset >= 0) 109 return pos; 110 111 return NULL; 112 } 113 114 static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, 115 int evidx, u64 len, int min_pcnt, 116 int printed, int max_lines, 117 struct objdump_line *queue) 118 { 119 static const char *prev_line; 120 static const char *prev_color; 121 122 if (oline->offset != -1) { 123 const char *path = NULL; 124 unsigned int hits = 0; 125 double percent = 0.0; 126 const char *color; 127 struct annotation *notes = symbol__annotation(sym); 128 struct source_line *src_line = notes->src->lines; 129 struct sym_hist *h = annotation__histogram(notes, evidx); 130 s64 offset = oline->offset; 131 struct objdump_line *next; 132 133 next = objdump__get_next_ip_line(¬es->src->source, oline); 134 135 while (offset < (s64)len && 136 (next == NULL || offset < next->offset)) { 137 if (src_line) { 138 if (path == NULL) 139 path = src_line[offset].path; 140 percent += src_line[offset].percent; 141 } else 142 hits += h->addr[offset]; 143 144 ++offset; 145 } 146 147 if (src_line == NULL && h->sum) 148 percent = 100.0 * hits / h->sum; 149 150 if (percent < min_pcnt) 151 return -1; 152 153 if (max_lines && printed >= max_lines) 154 return 1; 155 156 if (queue != NULL) { 157 list_for_each_entry_from(queue, ¬es->src->source, node) { 158 if (queue == oline) 159 break; 160 objdump_line__print(queue, sym, evidx, len, 161 0, 0, 1, NULL); 162 } 163 } 164 165 color = get_percent_color(percent); 166 167 /* 168 * Also color the filename and line if needed, with 169 * the same color than the percentage. Don't print it 170 * twice for close colored addr with the same filename:line 171 */ 172 if (path) { 173 if (!prev_line || strcmp(prev_line, path) 174 || color != prev_color) { 175 color_fprintf(stdout, color, " %s", path); 176 prev_line = path; 177 prev_color = color; 178 } 179 } 180 181 color_fprintf(stdout, color, " %7.2f", percent); 182 printf(" : "); 183 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line); 184 } else if (max_lines && printed >= max_lines) 185 return 1; 186 else { 187 if (queue) 188 return -1; 189 190 if (!*oline->line) 191 printf(" :\n"); 192 else 193 printf(" : %s\n", oline->line); 194 } 195 196 return 0; 197 } 198 199 static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, 200 FILE *file, size_t privsize) 201 { 202 struct annotation *notes = symbol__annotation(sym); 203 struct objdump_line *objdump_line; 204 char *line = NULL, *tmp, *tmp2, *c; 205 size_t line_len; 206 s64 line_ip, offset = -1; 207 208 if (getline(&line, &line_len, file) < 0) 209 return -1; 210 211 if (!line) 212 return -1; 213 214 while (line_len != 0 && isspace(line[line_len - 1])) 215 line[--line_len] = '\0'; 216 217 c = strchr(line, '\n'); 218 if (c) 219 *c = 0; 220 221 line_ip = -1; 222 223 /* 224 * Strip leading spaces: 225 */ 226 tmp = line; 227 while (*tmp) { 228 if (*tmp != ' ') 229 break; 230 tmp++; 231 } 232 233 if (*tmp) { 234 /* 235 * Parse hexa addresses followed by ':' 236 */ 237 line_ip = strtoull(tmp, &tmp2, 16); 238 if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0') 239 line_ip = -1; 240 } 241 242 if (line_ip != -1) { 243 u64 start = map__rip_2objdump(map, sym->start), 244 end = map__rip_2objdump(map, sym->end); 245 246 offset = line_ip - start; 247 if (offset < 0 || (u64)line_ip > end) 248 offset = -1; 249 } 250 251 objdump_line = objdump_line__new(offset, line, privsize); 252 if (objdump_line == NULL) { 253 free(line); 254 return -1; 255 } 256 objdump__add_line(¬es->src->source, objdump_line); 257 258 return 0; 259 } 260 261 int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 262 { 263 struct dso *dso = map->dso; 264 char *filename = dso__build_id_filename(dso, NULL, 0); 265 bool free_filename = true; 266 char command[PATH_MAX * 2]; 267 FILE *file; 268 int err = 0; 269 char symfs_filename[PATH_MAX]; 270 271 if (filename) { 272 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 273 symbol_conf.symfs, filename); 274 } 275 276 if (filename == NULL) { 277 if (dso->has_build_id) { 278 pr_err("Can't annotate %s: not enough memory\n", 279 sym->name); 280 return -ENOMEM; 281 } 282 goto fallback; 283 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 284 strstr(command, "[kernel.kallsyms]") || 285 access(symfs_filename, R_OK)) { 286 free(filename); 287 fallback: 288 /* 289 * If we don't have build-ids or the build-id file isn't in the 290 * cache, or is just a kallsyms file, well, lets hope that this 291 * DSO is the same as when 'perf record' ran. 292 */ 293 filename = dso->long_name; 294 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 295 symbol_conf.symfs, filename); 296 free_filename = false; 297 } 298 299 if (dso->symtab_type == SYMTAB__KALLSYMS) { 300 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 301 char *build_id_msg = NULL; 302 303 if (dso->annotate_warned) 304 goto out_free_filename; 305 306 if (dso->has_build_id) { 307 build_id__sprintf(dso->build_id, 308 sizeof(dso->build_id), bf + 15); 309 build_id_msg = bf; 310 } 311 err = -ENOENT; 312 dso->annotate_warned = 1; 313 pr_err("Can't annotate %s:\n\n" 314 "No vmlinux file%s\nwas found in the path.\n\n" 315 "Please use:\n\n" 316 " perf buildid-cache -av vmlinux\n\n" 317 "or:\n\n" 318 " --vmlinux vmlinux\n", 319 sym->name, build_id_msg ?: ""); 320 goto out_free_filename; 321 } 322 323 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 324 filename, sym->name, map->unmap_ip(map, sym->start), 325 map->unmap_ip(map, sym->end)); 326 327 pr_debug("annotating [%p] %30s : [%p] %30s\n", 328 dso, dso->long_name, sym, sym->name); 329 330 snprintf(command, sizeof(command), 331 "objdump %s%s --start-address=0x%016" PRIx64 332 " --stop-address=0x%016" PRIx64 333 " -d %s %s -C %s|grep -v %s|expand", 334 disassembler_style ? "-M " : "", 335 disassembler_style ? disassembler_style : "", 336 map__rip_2objdump(map, sym->start), 337 map__rip_2objdump(map, sym->end+1), 338 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 339 symbol_conf.annotate_src ? "-S" : "", 340 symfs_filename, filename); 341 342 pr_debug("Executing: %s\n", command); 343 344 file = popen(command, "r"); 345 if (!file) 346 goto out_free_filename; 347 348 while (!feof(file)) 349 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 350 break; 351 352 pclose(file); 353 out_free_filename: 354 if (free_filename) 355 free(filename); 356 return err; 357 } 358 359 static void insert_source_line(struct rb_root *root, struct source_line *src_line) 360 { 361 struct source_line *iter; 362 struct rb_node **p = &root->rb_node; 363 struct rb_node *parent = NULL; 364 365 while (*p != NULL) { 366 parent = *p; 367 iter = rb_entry(parent, struct source_line, node); 368 369 if (src_line->percent > iter->percent) 370 p = &(*p)->rb_left; 371 else 372 p = &(*p)->rb_right; 373 } 374 375 rb_link_node(&src_line->node, parent, p); 376 rb_insert_color(&src_line->node, root); 377 } 378 379 static void symbol__free_source_line(struct symbol *sym, int len) 380 { 381 struct annotation *notes = symbol__annotation(sym); 382 struct source_line *src_line = notes->src->lines; 383 int i; 384 385 for (i = 0; i < len; i++) 386 free(src_line[i].path); 387 388 free(src_line); 389 notes->src->lines = NULL; 390 } 391 392 /* Get the filename:line for the colored entries */ 393 static int symbol__get_source_line(struct symbol *sym, struct map *map, 394 int evidx, struct rb_root *root, int len, 395 const char *filename) 396 { 397 u64 start; 398 int i; 399 char cmd[PATH_MAX * 2]; 400 struct source_line *src_line; 401 struct annotation *notes = symbol__annotation(sym); 402 struct sym_hist *h = annotation__histogram(notes, evidx); 403 404 if (!h->sum) 405 return 0; 406 407 src_line = notes->src->lines = calloc(len, sizeof(struct source_line)); 408 if (!notes->src->lines) 409 return -1; 410 411 start = map__rip_2objdump(map, sym->start); 412 413 for (i = 0; i < len; i++) { 414 char *path = NULL; 415 size_t line_len; 416 u64 offset; 417 FILE *fp; 418 419 src_line[i].percent = 100.0 * h->addr[i] / h->sum; 420 if (src_line[i].percent <= 0.5) 421 continue; 422 423 offset = start + i; 424 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); 425 fp = popen(cmd, "r"); 426 if (!fp) 427 continue; 428 429 if (getline(&path, &line_len, fp) < 0 || !line_len) 430 goto next; 431 432 src_line[i].path = malloc(sizeof(char) * line_len + 1); 433 if (!src_line[i].path) 434 goto next; 435 436 strcpy(src_line[i].path, path); 437 insert_source_line(root, &src_line[i]); 438 439 next: 440 pclose(fp); 441 } 442 443 return 0; 444 } 445 446 static void print_summary(struct rb_root *root, const char *filename) 447 { 448 struct source_line *src_line; 449 struct rb_node *node; 450 451 printf("\nSorted summary for file %s\n", filename); 452 printf("----------------------------------------------\n\n"); 453 454 if (RB_EMPTY_ROOT(root)) { 455 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); 456 return; 457 } 458 459 node = rb_first(root); 460 while (node) { 461 double percent; 462 const char *color; 463 char *path; 464 465 src_line = rb_entry(node, struct source_line, node); 466 percent = src_line->percent; 467 color = get_percent_color(percent); 468 path = src_line->path; 469 470 color_fprintf(stdout, color, " %7.2f %s", percent, path); 471 node = rb_next(node); 472 } 473 } 474 475 static void symbol__annotate_hits(struct symbol *sym, int evidx) 476 { 477 struct annotation *notes = symbol__annotation(sym); 478 struct sym_hist *h = annotation__histogram(notes, evidx); 479 u64 len = sym->end - sym->start, offset; 480 481 for (offset = 0; offset < len; ++offset) 482 if (h->addr[offset] != 0) 483 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 484 sym->start + offset, h->addr[offset]); 485 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 486 } 487 488 int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, 489 bool full_paths, int min_pcnt, int max_lines, 490 int context) 491 { 492 struct dso *dso = map->dso; 493 const char *filename = dso->long_name, *d_filename; 494 struct annotation *notes = symbol__annotation(sym); 495 struct objdump_line *pos, *queue = NULL; 496 int printed = 2, queue_len = 0; 497 int more = 0; 498 u64 len; 499 500 if (full_paths) 501 d_filename = filename; 502 else 503 d_filename = basename(filename); 504 505 len = sym->end - sym->start; 506 507 printf(" Percent | Source code & Disassembly of %s\n", d_filename); 508 printf("------------------------------------------------\n"); 509 510 if (verbose) 511 symbol__annotate_hits(sym, evidx); 512 513 list_for_each_entry(pos, ¬es->src->source, node) { 514 if (context && queue == NULL) { 515 queue = pos; 516 queue_len = 0; 517 } 518 519 switch (objdump_line__print(pos, sym, evidx, len, min_pcnt, 520 printed, max_lines, queue)) { 521 case 0: 522 ++printed; 523 if (context) { 524 printed += queue_len; 525 queue = NULL; 526 queue_len = 0; 527 } 528 break; 529 case 1: 530 /* filtered by max_lines */ 531 ++more; 532 break; 533 case -1: 534 default: 535 /* 536 * Filtered by min_pcnt or non IP lines when 537 * context != 0 538 */ 539 if (!context) 540 break; 541 if (queue_len == context) 542 queue = list_entry(queue->node.next, typeof(*queue), node); 543 else 544 ++queue_len; 545 break; 546 } 547 } 548 549 return more; 550 } 551 552 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) 553 { 554 struct annotation *notes = symbol__annotation(sym); 555 struct sym_hist *h = annotation__histogram(notes, evidx); 556 557 memset(h, 0, notes->src->sizeof_sym_hist); 558 } 559 560 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) 561 { 562 struct annotation *notes = symbol__annotation(sym); 563 struct sym_hist *h = annotation__histogram(notes, evidx); 564 int len = sym->end - sym->start, offset; 565 566 h->sum = 0; 567 for (offset = 0; offset < len; ++offset) { 568 h->addr[offset] = h->addr[offset] * 7 / 8; 569 h->sum += h->addr[offset]; 570 } 571 } 572 573 void objdump_line_list__purge(struct list_head *head) 574 { 575 struct objdump_line *pos, *n; 576 577 list_for_each_entry_safe(pos, n, head, node) { 578 list_del(&pos->node); 579 objdump_line__free(pos); 580 } 581 } 582 583 int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, 584 bool print_lines, bool full_paths, int min_pcnt, 585 int max_lines) 586 { 587 struct dso *dso = map->dso; 588 const char *filename = dso->long_name; 589 struct rb_root source_line = RB_ROOT; 590 u64 len; 591 592 if (symbol__annotate(sym, map, 0) < 0) 593 return -1; 594 595 len = sym->end - sym->start; 596 597 if (print_lines) { 598 symbol__get_source_line(sym, map, evidx, &source_line, 599 len, filename); 600 print_summary(&source_line, filename); 601 } 602 603 symbol__annotate_printf(sym, map, evidx, full_paths, 604 min_pcnt, max_lines, 0); 605 if (print_lines) 606 symbol__free_source_line(sym, len); 607 608 objdump_line_list__purge(&symbol__annotation(sym)->src->source); 609 610 return 0; 611 } 612