diff options
Diffstat (limited to 'tools/perf/util/annotate.c')
| -rw-r--r-- | tools/perf/util/annotate.c | 85 |
1 files changed, 49 insertions, 36 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 6db435167d7..c777bdaf91d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
| @@ -14,25 +14,39 @@ | |||
| 14 | #include "symbol.h" | 14 | #include "symbol.h" |
| 15 | #include "debug.h" | 15 | #include "debug.h" |
| 16 | #include "annotate.h" | 16 | #include "annotate.h" |
| 17 | #include <pthread.h> | ||
| 17 | 18 | ||
| 18 | int symbol__alloc_hist(struct symbol *sym, int nevents) | 19 | int symbol__annotate_init(struct map *map __used, struct symbol *sym) |
| 19 | { | 20 | { |
| 20 | struct annotation *notes = symbol__annotation(sym); | 21 | struct annotation *notes = symbol__annotation(sym); |
| 22 | pthread_mutex_init(¬es->lock, NULL); | ||
| 23 | return 0; | ||
| 24 | } | ||
| 21 | 25 | ||
| 22 | notes->sizeof_sym_hist = (sizeof(*notes->histograms) + | 26 | int symbol__alloc_hist(struct symbol *sym, int nevents) |
| 27 | { | ||
| 28 | struct annotation *notes = symbol__annotation(sym); | ||
| 29 | size_t sizeof_sym_hist = (sizeof(struct sym_hist) + | ||
| 23 | (sym->end - sym->start) * sizeof(u64)); | 30 | (sym->end - sym->start) * sizeof(u64)); |
| 24 | notes->histograms = calloc(nevents, notes->sizeof_sym_hist); | 31 | |
| 25 | notes->nr_histograms = nevents; | 32 | notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist); |
| 26 | return notes->histograms == NULL ? -1 : 0; | 33 | if (notes->src == NULL) |
| 34 | return -1; | ||
| 35 | notes->src->sizeof_sym_hist = sizeof_sym_hist; | ||
| 36 | notes->src->nr_histograms = nevents; | ||
| 37 | INIT_LIST_HEAD(¬es->src->source); | ||
| 38 | return 0; | ||
| 27 | } | 39 | } |
| 28 | 40 | ||
| 29 | void symbol__annotate_zero_histograms(struct symbol *sym) | 41 | void symbol__annotate_zero_histograms(struct symbol *sym) |
| 30 | { | 42 | { |
| 31 | struct annotation *notes = symbol__annotation(sym); | 43 | struct annotation *notes = symbol__annotation(sym); |
| 32 | 44 | ||
| 33 | if (notes->histograms != NULL) | 45 | pthread_mutex_lock(¬es->lock); |
| 34 | memset(notes->histograms, 0, | 46 | if (notes->src != NULL) |
| 35 | notes->nr_histograms * notes->sizeof_sym_hist); | 47 | memset(notes->src->histograms, 0, |
| 48 | notes->src->nr_histograms * notes->src->sizeof_sym_hist); | ||
| 49 | pthread_mutex_unlock(¬es->lock); | ||
| 36 | } | 50 | } |
| 37 | 51 | ||
| 38 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | 52 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, |
| @@ -43,7 +57,7 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
| 43 | struct sym_hist *h; | 57 | struct sym_hist *h; |
| 44 | 58 | ||
| 45 | notes = symbol__annotation(sym); | 59 | notes = symbol__annotation(sym); |
| 46 | if (notes->histograms == NULL) | 60 | if (notes->src == NULL) |
| 47 | return -ENOMEM; | 61 | return -ENOMEM; |
| 48 | 62 | ||
| 49 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 63 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
| @@ -95,8 +109,7 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head, | |||
| 95 | return NULL; | 109 | return NULL; |
| 96 | } | 110 | } |
| 97 | 111 | ||
| 98 | static int objdump_line__print(struct objdump_line *oline, | 112 | static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, |
| 99 | struct list_head *head, struct symbol *sym, | ||
| 100 | int evidx, u64 len, int min_pcnt, | 113 | int evidx, u64 len, int min_pcnt, |
| 101 | int printed, int max_lines) | 114 | int printed, int max_lines) |
| 102 | { | 115 | { |
| @@ -109,10 +122,12 @@ static int objdump_line__print(struct objdump_line *oline, | |||
| 109 | double percent = 0.0; | 122 | double percent = 0.0; |
| 110 | const char *color; | 123 | const char *color; |
| 111 | struct annotation *notes = symbol__annotation(sym); | 124 | struct annotation *notes = symbol__annotation(sym); |
| 112 | struct source_line *src_line = notes->src_line; | 125 | struct source_line *src_line = notes->src->lines; |
| 113 | struct sym_hist *h = annotation__histogram(notes, evidx); | 126 | struct sym_hist *h = annotation__histogram(notes, evidx); |
| 114 | s64 offset = oline->offset; | 127 | s64 offset = oline->offset; |
| 115 | struct objdump_line *next = objdump__get_next_ip_line(head, oline); | 128 | struct objdump_line *next; |
| 129 | |||
| 130 | next = objdump__get_next_ip_line(¬es->src->source, oline); | ||
| 116 | 131 | ||
| 117 | while (offset < (s64)len && | 132 | while (offset < (s64)len && |
| 118 | (next == NULL || offset < next->offset)) { | 133 | (next == NULL || offset < next->offset)) { |
| @@ -166,9 +181,10 @@ static int objdump_line__print(struct objdump_line *oline, | |||
| 166 | return 0; | 181 | return 0; |
| 167 | } | 182 | } |
| 168 | 183 | ||
| 169 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file, | 184 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, |
| 170 | struct list_head *head, size_t privsize) | 185 | FILE *file, size_t privsize) |
| 171 | { | 186 | { |
| 187 | struct annotation *notes = symbol__annotation(sym); | ||
| 172 | struct objdump_line *objdump_line; | 188 | struct objdump_line *objdump_line; |
| 173 | char *line = NULL, *tmp, *tmp2, *c; | 189 | char *line = NULL, *tmp, *tmp2, *c; |
| 174 | size_t line_len; | 190 | size_t line_len; |
| @@ -222,13 +238,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE | |||
| 222 | free(line); | 238 | free(line); |
| 223 | return -1; | 239 | return -1; |
| 224 | } | 240 | } |
| 225 | objdump__add_line(head, objdump_line); | 241 | objdump__add_line(¬es->src->source, objdump_line); |
| 226 | 242 | ||
| 227 | return 0; | 243 | return 0; |
| 228 | } | 244 | } |
| 229 | 245 | ||
| 230 | int symbol__annotate(struct symbol *sym, struct map *map, | 246 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) |
| 231 | struct list_head *head, size_t privsize) | ||
| 232 | { | 247 | { |
| 233 | struct dso *dso = map->dso; | 248 | struct dso *dso = map->dso; |
| 234 | char *filename = dso__build_id_filename(dso, NULL, 0); | 249 | char *filename = dso__build_id_filename(dso, NULL, 0); |
| @@ -297,7 +312,7 @@ fallback: | |||
| 297 | goto out_free_filename; | 312 | goto out_free_filename; |
| 298 | 313 | ||
| 299 | while (!feof(file)) | 314 | while (!feof(file)) |
| 300 | if (symbol__parse_objdump_line(sym, map, file, head, privsize) < 0) | 315 | if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) |
| 301 | break; | 316 | break; |
| 302 | 317 | ||
| 303 | pclose(file); | 318 | pclose(file); |
| @@ -330,14 +345,14 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin | |||
| 330 | static void symbol__free_source_line(struct symbol *sym, int len) | 345 | static void symbol__free_source_line(struct symbol *sym, int len) |
| 331 | { | 346 | { |
| 332 | struct annotation *notes = symbol__annotation(sym); | 347 | struct annotation *notes = symbol__annotation(sym); |
| 333 | struct source_line *src_line = notes->src_line; | 348 | struct source_line *src_line = notes->src->lines; |
| 334 | int i; | 349 | int i; |
| 335 | 350 | ||
| 336 | for (i = 0; i < len; i++) | 351 | for (i = 0; i < len; i++) |
| 337 | free(src_line[i].path); | 352 | free(src_line[i].path); |
| 338 | 353 | ||
| 339 | free(src_line); | 354 | free(src_line); |
| 340 | notes->src_line = NULL; | 355 | notes->src->lines = NULL; |
| 341 | } | 356 | } |
| 342 | 357 | ||
| 343 | /* Get the filename:line for the colored entries */ | 358 | /* Get the filename:line for the colored entries */ |
| @@ -355,8 +370,8 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, | |||
| 355 | if (!h->sum) | 370 | if (!h->sum) |
| 356 | return 0; | 371 | return 0; |
| 357 | 372 | ||
| 358 | src_line = notes->src_line = calloc(len, sizeof(struct source_line)); | 373 | src_line = notes->src->lines = calloc(len, sizeof(struct source_line)); |
| 359 | if (!notes->src_line) | 374 | if (!notes->src->lines) |
| 360 | return -1; | 375 | return -1; |
| 361 | 376 | ||
| 362 | start = map->unmap_ip(map, sym->start); | 377 | start = map->unmap_ip(map, sym->start); |
| @@ -436,12 +451,12 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx) | |||
| 436 | printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); | 451 | printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); |
| 437 | } | 452 | } |
| 438 | 453 | ||
| 439 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 454 | int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, |
| 440 | struct list_head *head, int evidx, bool full_paths, | 455 | bool full_paths, int min_pcnt, int max_lines) |
| 441 | int min_pcnt, int max_lines) | ||
| 442 | { | 456 | { |
| 443 | struct dso *dso = map->dso; | 457 | struct dso *dso = map->dso; |
| 444 | const char *filename = dso->long_name, *d_filename; | 458 | const char *filename = dso->long_name, *d_filename; |
| 459 | struct annotation *notes = symbol__annotation(sym); | ||
| 445 | struct objdump_line *pos; | 460 | struct objdump_line *pos; |
| 446 | int printed = 2; | 461 | int printed = 2; |
| 447 | int more = 0; | 462 | int more = 0; |
| @@ -460,8 +475,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, | |||
| 460 | if (verbose) | 475 | if (verbose) |
| 461 | symbol__annotate_hits(sym, evidx); | 476 | symbol__annotate_hits(sym, evidx); |
| 462 | 477 | ||
| 463 | list_for_each_entry(pos, head, node) { | 478 | list_for_each_entry(pos, ¬es->src->source, node) { |
| 464 | switch (objdump_line__print(pos, head, sym, evidx, len, min_pcnt, | 479 | switch (objdump_line__print(pos, sym, evidx, len, min_pcnt, |
| 465 | printed, max_lines)) { | 480 | printed, max_lines)) { |
| 466 | case 0: | 481 | case 0: |
| 467 | ++printed; | 482 | ++printed; |
| @@ -485,11 +500,10 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) | |||
| 485 | struct annotation *notes = symbol__annotation(sym); | 500 | struct annotation *notes = symbol__annotation(sym); |
| 486 | struct sym_hist *h = annotation__histogram(notes, evidx); | 501 | struct sym_hist *h = annotation__histogram(notes, evidx); |
| 487 | 502 | ||
| 488 | memset(h, 0, notes->sizeof_sym_hist); | 503 | memset(h, 0, notes->src->sizeof_sym_hist); |
| 489 | } | 504 | } |
| 490 | 505 | ||
| 491 | void symbol__annotate_decay_histogram(struct symbol *sym, | 506 | void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) |
| 492 | struct list_head *head, int evidx) | ||
| 493 | { | 507 | { |
| 494 | struct annotation *notes = symbol__annotation(sym); | 508 | struct annotation *notes = symbol__annotation(sym); |
| 495 | struct sym_hist *h = annotation__histogram(notes, evidx); | 509 | struct sym_hist *h = annotation__histogram(notes, evidx); |
| @@ -497,7 +511,7 @@ void symbol__annotate_decay_histogram(struct symbol *sym, | |||
| 497 | 511 | ||
| 498 | h->sum = 0; | 512 | h->sum = 0; |
| 499 | 513 | ||
| 500 | list_for_each_entry(pos, head, node) { | 514 | list_for_each_entry(pos, ¬es->src->source, node) { |
| 501 | if (pos->offset != -1) { | 515 | if (pos->offset != -1) { |
| 502 | h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; | 516 | h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; |
| 503 | h->sum += h->addr[pos->offset]; | 517 | h->sum += h->addr[pos->offset]; |
| @@ -522,10 +536,9 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, | |||
| 522 | struct dso *dso = map->dso; | 536 | struct dso *dso = map->dso; |
| 523 | const char *filename = dso->long_name; | 537 | const char *filename = dso->long_name; |
| 524 | struct rb_root source_line = RB_ROOT; | 538 | struct rb_root source_line = RB_ROOT; |
| 525 | LIST_HEAD(head); | ||
| 526 | u64 len; | 539 | u64 len; |
| 527 | 540 | ||
| 528 | if (symbol__annotate(sym, map, &head, 0) < 0) | 541 | if (symbol__annotate(sym, map, 0) < 0) |
| 529 | return -1; | 542 | return -1; |
| 530 | 543 | ||
| 531 | len = sym->end - sym->start; | 544 | len = sym->end - sym->start; |
| @@ -536,12 +549,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, | |||
| 536 | print_summary(&source_line, filename); | 549 | print_summary(&source_line, filename); |
| 537 | } | 550 | } |
| 538 | 551 | ||
| 539 | symbol__annotate_printf(sym, map, &head, evidx, full_paths, | 552 | symbol__annotate_printf(sym, map, evidx, full_paths, |
| 540 | min_pcnt, max_lines); | 553 | min_pcnt, max_lines); |
| 541 | if (print_lines) | 554 | if (print_lines) |
| 542 | symbol__free_source_line(sym, len); | 555 | symbol__free_source_line(sym, len); |
| 543 | 556 | ||
| 544 | objdump_line_list__purge(&head); | 557 | objdump_line_list__purge(&symbol__annotation(sym)->src->source); |
| 545 | 558 | ||
| 546 | return 0; | 559 | return 0; |
| 547 | } | 560 | } |
