diff options
Diffstat (limited to 'tools/perf/util')
80 files changed, 1827 insertions, 899 deletions
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index e6d134773d0a..c0b43ee40d95 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c | |||
| @@ -55,8 +55,7 @@ int split_cmdline(char *cmdline, const char ***argv) | |||
| 55 | src++; | 55 | src++; |
| 56 | c = cmdline[src]; | 56 | c = cmdline[src]; |
| 57 | if (!c) { | 57 | if (!c) { |
| 58 | free(*argv); | 58 | zfree(argv); |
| 59 | *argv = NULL; | ||
| 60 | return error("cmdline ends with \\"); | 59 | return error("cmdline ends with \\"); |
| 61 | } | 60 | } |
| 62 | } | 61 | } |
| @@ -68,8 +67,7 @@ int split_cmdline(char *cmdline, const char ***argv) | |||
| 68 | cmdline[dst] = 0; | 67 | cmdline[dst] = 0; |
| 69 | 68 | ||
| 70 | if (quoted) { | 69 | if (quoted) { |
| 71 | free(*argv); | 70 | zfree(argv); |
| 72 | *argv = NULL; | ||
| 73 | return error("unclosed quote"); | 71 | return error("unclosed quote"); |
| 74 | } | 72 | } |
| 75 | 73 | ||
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index cf6242c92ee2..469eb679fb9d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
| @@ -26,10 +26,10 @@ static int disasm_line__parse(char *line, char **namep, char **rawp); | |||
| 26 | 26 | ||
| 27 | static void ins__delete(struct ins_operands *ops) | 27 | static void ins__delete(struct ins_operands *ops) |
| 28 | { | 28 | { |
| 29 | free(ops->source.raw); | 29 | zfree(&ops->source.raw); |
| 30 | free(ops->source.name); | 30 | zfree(&ops->source.name); |
| 31 | free(ops->target.raw); | 31 | zfree(&ops->target.raw); |
| 32 | free(ops->target.name); | 32 | zfree(&ops->target.name); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, | 35 | static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, |
| @@ -185,8 +185,7 @@ static int lock__parse(struct ins_operands *ops) | |||
| 185 | return 0; | 185 | return 0; |
| 186 | 186 | ||
| 187 | out_free_ops: | 187 | out_free_ops: |
| 188 | free(ops->locked.ops); | 188 | zfree(&ops->locked.ops); |
| 189 | ops->locked.ops = NULL; | ||
| 190 | return 0; | 189 | return 0; |
| 191 | } | 190 | } |
| 192 | 191 | ||
| @@ -205,9 +204,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size, | |||
| 205 | 204 | ||
| 206 | static void lock__delete(struct ins_operands *ops) | 205 | static void lock__delete(struct ins_operands *ops) |
| 207 | { | 206 | { |
| 208 | free(ops->locked.ops); | 207 | zfree(&ops->locked.ops); |
| 209 | free(ops->target.raw); | 208 | zfree(&ops->target.raw); |
| 210 | free(ops->target.name); | 209 | zfree(&ops->target.name); |
| 211 | } | 210 | } |
| 212 | 211 | ||
| 213 | static struct ins_ops lock_ops = { | 212 | static struct ins_ops lock_ops = { |
| @@ -256,8 +255,7 @@ static int mov__parse(struct ins_operands *ops) | |||
| 256 | return 0; | 255 | return 0; |
| 257 | 256 | ||
| 258 | out_free_source: | 257 | out_free_source: |
| 259 | free(ops->source.raw); | 258 | zfree(&ops->source.raw); |
| 260 | ops->source.raw = NULL; | ||
| 261 | return -1; | 259 | return -1; |
| 262 | } | 260 | } |
| 263 | 261 | ||
| @@ -464,17 +462,12 @@ void symbol__annotate_zero_histograms(struct symbol *sym) | |||
| 464 | pthread_mutex_unlock(¬es->lock); | 462 | pthread_mutex_unlock(¬es->lock); |
| 465 | } | 463 | } |
| 466 | 464 | ||
| 467 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | 465 | static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, |
| 468 | int evidx, u64 addr) | 466 | struct annotation *notes, int evidx, u64 addr) |
| 469 | { | 467 | { |
| 470 | unsigned offset; | 468 | unsigned offset; |
| 471 | struct annotation *notes; | ||
| 472 | struct sym_hist *h; | 469 | struct sym_hist *h; |
| 473 | 470 | ||
| 474 | notes = symbol__annotation(sym); | ||
| 475 | if (notes->src == NULL) | ||
| 476 | return -ENOMEM; | ||
| 477 | |||
| 478 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 471 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
| 479 | 472 | ||
| 480 | if (addr < sym->start || addr > sym->end) | 473 | if (addr < sym->start || addr > sym->end) |
| @@ -491,6 +484,33 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
| 491 | return 0; | 484 | return 0; |
| 492 | } | 485 | } |
| 493 | 486 | ||
| 487 | static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | ||
| 488 | int evidx, u64 addr) | ||
| 489 | { | ||
| 490 | struct annotation *notes; | ||
| 491 | |||
| 492 | if (sym == NULL || use_browser != 1 || !sort__has_sym) | ||
| 493 | return 0; | ||
| 494 | |||
| 495 | notes = symbol__annotation(sym); | ||
| 496 | if (notes->src == NULL) { | ||
| 497 | if (symbol__alloc_hist(sym) < 0) | ||
| 498 | return -ENOMEM; | ||
| 499 | } | ||
| 500 | |||
| 501 | return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); | ||
| 502 | } | ||
| 503 | |||
| 504 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) | ||
| 505 | { | ||
| 506 | return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); | ||
| 507 | } | ||
| 508 | |||
| 509 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) | ||
| 510 | { | ||
| 511 | return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); | ||
| 512 | } | ||
| 513 | |||
| 494 | static void disasm_line__init_ins(struct disasm_line *dl) | 514 | static void disasm_line__init_ins(struct disasm_line *dl) |
| 495 | { | 515 | { |
| 496 | dl->ins = ins__find(dl->name); | 516 | dl->ins = ins__find(dl->name); |
| @@ -538,8 +558,7 @@ static int disasm_line__parse(char *line, char **namep, char **rawp) | |||
| 538 | return 0; | 558 | return 0; |
| 539 | 559 | ||
| 540 | out_free_name: | 560 | out_free_name: |
| 541 | free(*namep); | 561 | zfree(namep); |
| 542 | *namep = NULL; | ||
| 543 | return -1; | 562 | return -1; |
| 544 | } | 563 | } |
| 545 | 564 | ||
| @@ -564,7 +583,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs | |||
| 564 | return dl; | 583 | return dl; |
| 565 | 584 | ||
| 566 | out_free_line: | 585 | out_free_line: |
| 567 | free(dl->line); | 586 | zfree(&dl->line); |
| 568 | out_delete: | 587 | out_delete: |
| 569 | free(dl); | 588 | free(dl); |
| 570 | return NULL; | 589 | return NULL; |
| @@ -572,8 +591,8 @@ out_delete: | |||
| 572 | 591 | ||
| 573 | void disasm_line__free(struct disasm_line *dl) | 592 | void disasm_line__free(struct disasm_line *dl) |
| 574 | { | 593 | { |
| 575 | free(dl->line); | 594 | zfree(&dl->line); |
| 576 | free(dl->name); | 595 | zfree(&dl->name); |
| 577 | if (dl->ins && dl->ins->ops->free) | 596 | if (dl->ins && dl->ins->ops->free) |
| 578 | dl->ins->ops->free(&dl->ops); | 597 | dl->ins->ops->free(&dl->ops); |
| 579 | else | 598 | else |
| @@ -900,7 +919,7 @@ fallback: | |||
| 900 | * cache, or is just a kallsyms file, well, lets hope that this | 919 | * cache, or is just a kallsyms file, well, lets hope that this |
| 901 | * DSO is the same as when 'perf record' ran. | 920 | * DSO is the same as when 'perf record' ran. |
| 902 | */ | 921 | */ |
| 903 | filename = dso->long_name; | 922 | filename = (char *)dso->long_name; |
| 904 | snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", | 923 | snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", |
| 905 | symbol_conf.symfs, filename); | 924 | symbol_conf.symfs, filename); |
| 906 | free_filename = false; | 925 | free_filename = false; |
| @@ -1091,8 +1110,7 @@ static void symbol__free_source_line(struct symbol *sym, int len) | |||
| 1091 | src_line = (void *)src_line + sizeof_src_line; | 1110 | src_line = (void *)src_line + sizeof_src_line; |
| 1092 | } | 1111 | } |
| 1093 | 1112 | ||
| 1094 | free(notes->src->lines); | 1113 | zfree(¬es->src->lines); |
| 1095 | notes->src->lines = NULL; | ||
| 1096 | } | 1114 | } |
| 1097 | 1115 | ||
| 1098 | /* Get the filename:line for the colored entries */ | 1116 | /* Get the filename:line for the colored entries */ |
| @@ -1376,3 +1394,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, | |||
| 1376 | 1394 | ||
| 1377 | return 0; | 1395 | return 0; |
| 1378 | } | 1396 | } |
| 1397 | |||
| 1398 | int hist_entry__annotate(struct hist_entry *he, size_t privsize) | ||
| 1399 | { | ||
| 1400 | return symbol__annotate(he->ms.sym, he->ms.map, privsize); | ||
| 1401 | } | ||
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 834b7b57b788..b2aef59d6bb2 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
| @@ -132,12 +132,17 @@ static inline struct annotation *symbol__annotation(struct symbol *sym) | |||
| 132 | return &a->annotation; | 132 | return &a->annotation; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | 135 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); |
| 136 | int evidx, u64 addr); | 136 | |
| 137 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); | ||
| 138 | |||
| 137 | int symbol__alloc_hist(struct symbol *sym); | 139 | int symbol__alloc_hist(struct symbol *sym); |
| 138 | void symbol__annotate_zero_histograms(struct symbol *sym); | 140 | void symbol__annotate_zero_histograms(struct symbol *sym); |
| 139 | 141 | ||
| 140 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); | 142 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); |
| 143 | |||
| 144 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | ||
| 145 | |||
| 141 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); | 146 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); |
| 142 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 147 | int symbol__annotate_printf(struct symbol *sym, struct map *map, |
| 143 | struct perf_evsel *evsel, bool full_paths, | 148 | struct perf_evsel *evsel, bool full_paths, |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index a92770c98cc7..6baabe63182b 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
| @@ -89,7 +89,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) | |||
| 89 | return raw - build_id; | 89 | return raw - build_id; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | char *dso__build_id_filename(struct dso *dso, char *bf, size_t size) | 92 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) |
| 93 | { | 93 | { |
| 94 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 94 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
| 95 | 95 | ||
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 929f28a7c14d..845ef865eced 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h | |||
| @@ -10,7 +10,7 @@ extern struct perf_tool build_id__mark_dso_hit_ops; | |||
| 10 | struct dso; | 10 | struct dso; |
| 11 | 11 | ||
| 12 | int build_id__sprintf(const u8 *build_id, int len, char *bf); | 12 | int build_id__sprintf(const u8 *build_id, int len, char *bf); |
| 13 | char *dso__build_id_filename(struct dso *dso, char *bf, size_t size); | 13 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); |
| 14 | 14 | ||
| 15 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, | 15 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, |
| 16 | struct perf_sample *sample, struct perf_evsel *evsel, | 16 | struct perf_sample *sample, struct perf_evsel *evsel, |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index e3970e3eaacf..8d9db454f1a9 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
| @@ -15,8 +15,12 @@ | |||
| 15 | #include <errno.h> | 15 | #include <errno.h> |
| 16 | #include <math.h> | 16 | #include <math.h> |
| 17 | 17 | ||
| 18 | #include "asm/bug.h" | ||
| 19 | |||
| 18 | #include "hist.h" | 20 | #include "hist.h" |
| 19 | #include "util.h" | 21 | #include "util.h" |
| 22 | #include "sort.h" | ||
| 23 | #include "machine.h" | ||
| 20 | #include "callchain.h" | 24 | #include "callchain.h" |
| 21 | 25 | ||
| 22 | __thread struct callchain_cursor callchain_cursor; | 26 | __thread struct callchain_cursor callchain_cursor; |
| @@ -356,19 +360,14 @@ append_chain_children(struct callchain_node *root, | |||
| 356 | /* lookup in childrens */ | 360 | /* lookup in childrens */ |
| 357 | while (*p) { | 361 | while (*p) { |
| 358 | s64 ret; | 362 | s64 ret; |
| 359 | struct callchain_list *cnode; | ||
| 360 | 363 | ||
| 361 | parent = *p; | 364 | parent = *p; |
| 362 | rnode = rb_entry(parent, struct callchain_node, rb_node_in); | 365 | rnode = rb_entry(parent, struct callchain_node, rb_node_in); |
| 363 | cnode = list_first_entry(&rnode->val, struct callchain_list, | ||
| 364 | list); | ||
| 365 | 366 | ||
| 366 | /* just check first entry */ | 367 | /* If at least first entry matches, rely to children */ |
| 367 | ret = match_chain(node, cnode); | 368 | ret = append_chain(rnode, cursor, period); |
| 368 | if (ret == 0) { | 369 | if (ret == 0) |
| 369 | append_chain(rnode, cursor, period); | ||
| 370 | goto inc_children_hit; | 370 | goto inc_children_hit; |
| 371 | } | ||
| 372 | 371 | ||
| 373 | if (ret < 0) | 372 | if (ret < 0) |
| 374 | p = &parent->rb_left; | 373 | p = &parent->rb_left; |
| @@ -389,11 +388,11 @@ append_chain(struct callchain_node *root, | |||
| 389 | struct callchain_cursor *cursor, | 388 | struct callchain_cursor *cursor, |
| 390 | u64 period) | 389 | u64 period) |
| 391 | { | 390 | { |
| 392 | struct callchain_cursor_node *curr_snap = cursor->curr; | ||
| 393 | struct callchain_list *cnode; | 391 | struct callchain_list *cnode; |
| 394 | u64 start = cursor->pos; | 392 | u64 start = cursor->pos; |
| 395 | bool found = false; | 393 | bool found = false; |
| 396 | u64 matches; | 394 | u64 matches; |
| 395 | int cmp = 0; | ||
| 397 | 396 | ||
| 398 | /* | 397 | /* |
| 399 | * Lookup in the current node | 398 | * Lookup in the current node |
| @@ -408,7 +407,8 @@ append_chain(struct callchain_node *root, | |||
| 408 | if (!node) | 407 | if (!node) |
| 409 | break; | 408 | break; |
| 410 | 409 | ||
| 411 | if (match_chain(node, cnode) != 0) | 410 | cmp = match_chain(node, cnode); |
| 411 | if (cmp) | ||
| 412 | break; | 412 | break; |
| 413 | 413 | ||
| 414 | found = true; | 414 | found = true; |
| @@ -418,9 +418,8 @@ append_chain(struct callchain_node *root, | |||
| 418 | 418 | ||
| 419 | /* matches not, relay no the parent */ | 419 | /* matches not, relay no the parent */ |
| 420 | if (!found) { | 420 | if (!found) { |
| 421 | cursor->curr = curr_snap; | 421 | WARN_ONCE(!cmp, "Chain comparison error\n"); |
| 422 | cursor->pos = start; | 422 | return cmp; |
| 423 | return -1; | ||
| 424 | } | 423 | } |
| 425 | 424 | ||
| 426 | matches = cursor->pos - start; | 425 | matches = cursor->pos - start; |
| @@ -531,3 +530,24 @@ int callchain_cursor_append(struct callchain_cursor *cursor, | |||
| 531 | 530 | ||
| 532 | return 0; | 531 | return 0; |
| 533 | } | 532 | } |
| 533 | |||
| 534 | int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, | ||
| 535 | struct perf_evsel *evsel, struct addr_location *al, | ||
| 536 | int max_stack) | ||
| 537 | { | ||
| 538 | if (sample->callchain == NULL) | ||
| 539 | return 0; | ||
| 540 | |||
| 541 | if (symbol_conf.use_callchain || sort__has_parent) { | ||
| 542 | return machine__resolve_callchain(al->machine, evsel, al->thread, | ||
| 543 | sample, parent, al, max_stack); | ||
| 544 | } | ||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | |||
| 548 | int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) | ||
| 549 | { | ||
| 550 | if (!symbol_conf.use_callchain) | ||
| 551 | return 0; | ||
| 552 | return callchain_append(he->callchain, &callchain_cursor, sample->period); | ||
| 553 | } | ||
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 4f7f989876ec..8ad97e9b119f 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
| @@ -145,10 +145,16 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor) | |||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | struct option; | 147 | struct option; |
| 148 | struct hist_entry; | ||
| 148 | 149 | ||
| 149 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts); | 150 | int record_parse_callchain(const char *arg, struct record_opts *opts); |
| 150 | int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); | 151 | int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); |
| 151 | int record_callchain_opt(const struct option *opt, const char *arg, int unset); | 152 | int record_callchain_opt(const struct option *opt, const char *arg, int unset); |
| 152 | 153 | ||
| 154 | int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, | ||
| 155 | struct perf_evsel *evsel, struct addr_location *al, | ||
| 156 | int max_stack); | ||
| 157 | int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); | ||
| 158 | |||
| 153 | extern const char record_callchain_help[]; | 159 | extern const char record_callchain_help[]; |
| 154 | #endif /* __PERF_CALLCHAIN_H */ | 160 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 96bbda1ddb83..88f7be399432 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c | |||
| @@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) | |||
| 81 | /* | 81 | /* |
| 82 | * check if cgrp is already defined, if so we reuse it | 82 | * check if cgrp is already defined, if so we reuse it |
| 83 | */ | 83 | */ |
| 84 | list_for_each_entry(counter, &evlist->entries, node) { | 84 | evlist__for_each(evlist, counter) { |
| 85 | cgrp = counter->cgrp; | 85 | cgrp = counter->cgrp; |
| 86 | if (!cgrp) | 86 | if (!cgrp) |
| 87 | continue; | 87 | continue; |
| @@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) | |||
| 110 | * if add cgroup N, then need to find event N | 110 | * if add cgroup N, then need to find event N |
| 111 | */ | 111 | */ |
| 112 | n = 0; | 112 | n = 0; |
| 113 | list_for_each_entry(counter, &evlist->entries, node) { | 113 | evlist__for_each(evlist, counter) { |
| 114 | if (n == nr_cgroups) | 114 | if (n == nr_cgroups) |
| 115 | goto found; | 115 | goto found; |
| 116 | n++; | 116 | n++; |
| @@ -133,7 +133,7 @@ void close_cgroup(struct cgroup_sel *cgrp) | |||
| 133 | /* XXX: not reentrant */ | 133 | /* XXX: not reentrant */ |
| 134 | if (--cgrp->refcnt == 0) { | 134 | if (--cgrp->refcnt == 0) { |
| 135 | close(cgrp->fd); | 135 | close(cgrp->fd); |
| 136 | free(cgrp->name); | 136 | zfree(&cgrp->name); |
| 137 | free(cgrp); | 137 | free(cgrp); |
| 138 | } | 138 | } |
| 139 | } | 139 | } |
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 66e44a5019d5..87b8672eb413 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
| 2 | #include "cache.h" | 2 | #include "cache.h" |
| 3 | #include "color.h" | 3 | #include "color.h" |
| 4 | #include <math.h> | ||
| 4 | 5 | ||
| 5 | int perf_use_color_default = -1; | 6 | int perf_use_color_default = -1; |
| 6 | 7 | ||
| @@ -298,10 +299,10 @@ const char *get_percent_color(double percent) | |||
| 298 | * entries in green - and keep the low overhead places | 299 | * entries in green - and keep the low overhead places |
| 299 | * normal: | 300 | * normal: |
| 300 | */ | 301 | */ |
| 301 | if (percent >= MIN_RED) | 302 | if (fabs(percent) >= MIN_RED) |
| 302 | color = PERF_COLOR_RED; | 303 | color = PERF_COLOR_RED; |
| 303 | else { | 304 | else { |
| 304 | if (percent > MIN_GREEN) | 305 | if (fabs(percent) > MIN_GREEN) |
| 305 | color = PERF_COLOR_GREEN; | 306 | color = PERF_COLOR_GREEN; |
| 306 | } | 307 | } |
| 307 | return color; | 308 | return color; |
| @@ -318,15 +319,19 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent) | |||
| 318 | return r; | 319 | return r; |
| 319 | } | 320 | } |
| 320 | 321 | ||
| 322 | int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) | ||
| 323 | { | ||
| 324 | const char *color = get_percent_color(value); | ||
| 325 | return color_snprintf(bf, size, color, fmt, value); | ||
| 326 | } | ||
| 327 | |||
| 321 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) | 328 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) |
| 322 | { | 329 | { |
| 323 | va_list args; | 330 | va_list args; |
| 324 | double percent; | 331 | double percent; |
| 325 | const char *color; | ||
| 326 | 332 | ||
| 327 | va_start(args, fmt); | 333 | va_start(args, fmt); |
| 328 | percent = va_arg(args, double); | 334 | percent = va_arg(args, double); |
| 329 | va_end(args); | 335 | va_end(args); |
| 330 | color = get_percent_color(percent); | 336 | return value_color_snprintf(bf, size, fmt, percent); |
| 331 | return color_snprintf(bf, size, color, fmt, percent); | ||
| 332 | } | 337 | } |
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index fced3840e99c..7ff30a62a132 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h | |||
| @@ -39,6 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); | |||
| 39 | int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); | 39 | int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); |
| 40 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); | 40 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); |
| 41 | int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); | 41 | int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); |
| 42 | int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); | ||
| 42 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); | 43 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); |
| 43 | int percent_color_fprintf(FILE *fp, const char *fmt, double percent); | 44 | int percent_color_fprintf(FILE *fp, const char *fmt, double percent); |
| 44 | const char *get_percent_color(double percent); | 45 | const char *get_percent_color(double percent); |
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c index ee0df0e24cdb..f9e777629e21 100644 --- a/tools/perf/util/comm.c +++ b/tools/perf/util/comm.c | |||
| @@ -21,7 +21,7 @@ static void comm_str__put(struct comm_str *cs) | |||
| 21 | { | 21 | { |
| 22 | if (!--cs->ref) { | 22 | if (!--cs->ref) { |
| 23 | rb_erase(&cs->rb_node, &comm_str_root); | 23 | rb_erase(&cs->rb_node, &comm_str_root); |
| 24 | free(cs->str); | 24 | zfree(&cs->str); |
| 25 | free(cs); | 25 | free(cs); |
| 26 | } | 26 | } |
| 27 | } | 27 | } |
| @@ -94,19 +94,20 @@ struct comm *comm__new(const char *str, u64 timestamp) | |||
| 94 | return comm; | 94 | return comm; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | void comm__override(struct comm *comm, const char *str, u64 timestamp) | 97 | int comm__override(struct comm *comm, const char *str, u64 timestamp) |
| 98 | { | 98 | { |
| 99 | struct comm_str *old = comm->comm_str; | 99 | struct comm_str *new, *old = comm->comm_str; |
| 100 | 100 | ||
| 101 | comm->comm_str = comm_str__findnew(str, &comm_str_root); | 101 | new = comm_str__findnew(str, &comm_str_root); |
| 102 | if (!comm->comm_str) { | 102 | if (!new) |
| 103 | comm->comm_str = old; | 103 | return -ENOMEM; |
| 104 | return; | ||
| 105 | } | ||
| 106 | 104 | ||
| 107 | comm->start = timestamp; | 105 | comm_str__get(new); |
| 108 | comm_str__get(comm->comm_str); | ||
| 109 | comm_str__put(old); | 106 | comm_str__put(old); |
| 107 | comm->comm_str = new; | ||
| 108 | comm->start = timestamp; | ||
| 109 | |||
| 110 | return 0; | ||
| 110 | } | 111 | } |
| 111 | 112 | ||
| 112 | void comm__free(struct comm *comm) | 113 | void comm__free(struct comm *comm) |
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h index 7a86e5656710..fac5bd51befc 100644 --- a/tools/perf/util/comm.h +++ b/tools/perf/util/comm.h | |||
| @@ -16,6 +16,6 @@ struct comm { | |||
| 16 | void comm__free(struct comm *comm); | 16 | void comm__free(struct comm *comm); |
| 17 | struct comm *comm__new(const char *str, u64 timestamp); | 17 | struct comm *comm__new(const char *str, u64 timestamp); |
| 18 | const char *comm__str(const struct comm *comm); | 18 | const char *comm__str(const struct comm *comm); |
| 19 | void comm__override(struct comm *comm, const char *str, u64 timestamp); | 19 | int comm__override(struct comm *comm, const char *str, u64 timestamp); |
| 20 | 20 | ||
| 21 | #endif /* __PERF_COMM_H */ | 21 | #endif /* __PERF_COMM_H */ |
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index 7d09faf85cf1..1fbcd8bdc11b 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c | |||
| @@ -118,3 +118,9 @@ void perf_data_file__close(struct perf_data_file *file) | |||
| 118 | { | 118 | { |
| 119 | close(file->fd); | 119 | close(file->fd); |
| 120 | } | 120 | } |
| 121 | |||
| 122 | ssize_t perf_data_file__write(struct perf_data_file *file, | ||
| 123 | void *buf, size_t size) | ||
| 124 | { | ||
| 125 | return writen(file->fd, buf, size); | ||
| 126 | } | ||
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h index 8c2df80152a5..2b15d0c95c7f 100644 --- a/tools/perf/util/data.h +++ b/tools/perf/util/data.h | |||
| @@ -9,12 +9,12 @@ enum perf_data_mode { | |||
| 9 | }; | 9 | }; |
| 10 | 10 | ||
| 11 | struct perf_data_file { | 11 | struct perf_data_file { |
| 12 | const char *path; | 12 | const char *path; |
| 13 | int fd; | 13 | int fd; |
| 14 | bool is_pipe; | 14 | bool is_pipe; |
| 15 | bool force; | 15 | bool force; |
| 16 | unsigned long size; | 16 | unsigned long size; |
| 17 | enum perf_data_mode mode; | 17 | enum perf_data_mode mode; |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | static inline bool perf_data_file__is_read(struct perf_data_file *file) | 20 | static inline bool perf_data_file__is_read(struct perf_data_file *file) |
| @@ -44,5 +44,7 @@ static inline unsigned long perf_data_file__size(struct perf_data_file *file) | |||
| 44 | 44 | ||
| 45 | int perf_data_file__open(struct perf_data_file *file); | 45 | int perf_data_file__open(struct perf_data_file *file); |
| 46 | void perf_data_file__close(struct perf_data_file *file); | 46 | void perf_data_file__close(struct perf_data_file *file); |
| 47 | ssize_t perf_data_file__write(struct perf_data_file *file, | ||
| 48 | void *buf, size_t size); | ||
| 47 | 49 | ||
| 48 | #endif /* __PERF_DATA_H */ | 50 | #endif /* __PERF_DATA_H */ |
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 399e74c34c1a..299b55586502 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
| @@ -16,23 +16,46 @@ | |||
| 16 | int verbose; | 16 | int verbose; |
| 17 | bool dump_trace = false, quiet = false; | 17 | bool dump_trace = false, quiet = false; |
| 18 | 18 | ||
| 19 | int eprintf(int level, const char *fmt, ...) | 19 | static int _eprintf(int level, const char *fmt, va_list args) |
| 20 | { | 20 | { |
| 21 | va_list args; | ||
| 22 | int ret = 0; | 21 | int ret = 0; |
| 23 | 22 | ||
| 24 | if (verbose >= level) { | 23 | if (verbose >= level) { |
| 25 | va_start(args, fmt); | ||
| 26 | if (use_browser >= 1) | 24 | if (use_browser >= 1) |
| 27 | ui_helpline__vshow(fmt, args); | 25 | ui_helpline__vshow(fmt, args); |
| 28 | else | 26 | else |
| 29 | ret = vfprintf(stderr, fmt, args); | 27 | ret = vfprintf(stderr, fmt, args); |
| 30 | va_end(args); | ||
| 31 | } | 28 | } |
| 32 | 29 | ||
| 33 | return ret; | 30 | return ret; |
| 34 | } | 31 | } |
| 35 | 32 | ||
| 33 | int eprintf(int level, const char *fmt, ...) | ||
| 34 | { | ||
| 35 | va_list args; | ||
| 36 | int ret; | ||
| 37 | |||
| 38 | va_start(args, fmt); | ||
| 39 | ret = _eprintf(level, fmt, args); | ||
| 40 | va_end(args); | ||
| 41 | |||
| 42 | return ret; | ||
| 43 | } | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Overloading libtraceevent standard info print | ||
| 47 | * function, display with -v in perf. | ||
| 48 | */ | ||
| 49 | void pr_stat(const char *fmt, ...) | ||
| 50 | { | ||
| 51 | va_list args; | ||
| 52 | |||
| 53 | va_start(args, fmt); | ||
| 54 | _eprintf(1, fmt, args); | ||
| 55 | va_end(args); | ||
| 56 | eprintf(1, "\n"); | ||
| 57 | } | ||
| 58 | |||
| 36 | int dump_printf(const char *fmt, ...) | 59 | int dump_printf(const char *fmt, ...) |
| 37 | { | 60 | { |
| 38 | va_list args; | 61 | va_list args; |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index efbd98805ad0..443694c36b03 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
| @@ -17,4 +17,6 @@ void trace_event(union perf_event *event); | |||
| 17 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); | 17 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); |
| 18 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); | 18 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); |
| 19 | 19 | ||
| 20 | void pr_stat(const char *fmt, ...); | ||
| 21 | |||
| 20 | #endif /* __PERF_DEBUG_H */ | 22 | #endif /* __PERF_DEBUG_H */ |
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index af4c687cc49b..4045d086d9d9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
| @@ -28,8 +28,9 @@ char dso__symtab_origin(const struct dso *dso) | |||
| 28 | return origin[dso->symtab_type]; | 28 | return origin[dso->symtab_type]; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | 31 | int dso__read_binary_type_filename(const struct dso *dso, |
| 32 | char *root_dir, char *file, size_t size) | 32 | enum dso_binary_type type, |
| 33 | char *root_dir, char *filename, size_t size) | ||
| 33 | { | 34 | { |
| 34 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 35 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
| 35 | int ret = 0; | 36 | int ret = 0; |
| @@ -38,36 +39,36 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
| 38 | case DSO_BINARY_TYPE__DEBUGLINK: { | 39 | case DSO_BINARY_TYPE__DEBUGLINK: { |
| 39 | char *debuglink; | 40 | char *debuglink; |
| 40 | 41 | ||
| 41 | strncpy(file, dso->long_name, size); | 42 | strncpy(filename, dso->long_name, size); |
| 42 | debuglink = file + dso->long_name_len; | 43 | debuglink = filename + dso->long_name_len; |
| 43 | while (debuglink != file && *debuglink != '/') | 44 | while (debuglink != filename && *debuglink != '/') |
| 44 | debuglink--; | 45 | debuglink--; |
| 45 | if (*debuglink == '/') | 46 | if (*debuglink == '/') |
| 46 | debuglink++; | 47 | debuglink++; |
| 47 | filename__read_debuglink(dso->long_name, debuglink, | 48 | filename__read_debuglink(dso->long_name, debuglink, |
| 48 | size - (debuglink - file)); | 49 | size - (debuglink - filename)); |
| 49 | } | 50 | } |
| 50 | break; | 51 | break; |
| 51 | case DSO_BINARY_TYPE__BUILD_ID_CACHE: | 52 | case DSO_BINARY_TYPE__BUILD_ID_CACHE: |
| 52 | /* skip the locally configured cache if a symfs is given */ | 53 | /* skip the locally configured cache if a symfs is given */ |
| 53 | if (symbol_conf.symfs[0] || | 54 | if (symbol_conf.symfs[0] || |
| 54 | (dso__build_id_filename(dso, file, size) == NULL)) | 55 | (dso__build_id_filename(dso, filename, size) == NULL)) |
| 55 | ret = -1; | 56 | ret = -1; |
| 56 | break; | 57 | break; |
| 57 | 58 | ||
| 58 | case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: | 59 | case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: |
| 59 | snprintf(file, size, "%s/usr/lib/debug%s.debug", | 60 | snprintf(filename, size, "%s/usr/lib/debug%s.debug", |
| 60 | symbol_conf.symfs, dso->long_name); | 61 | symbol_conf.symfs, dso->long_name); |
| 61 | break; | 62 | break; |
| 62 | 63 | ||
| 63 | case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: | 64 | case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: |
| 64 | snprintf(file, size, "%s/usr/lib/debug%s", | 65 | snprintf(filename, size, "%s/usr/lib/debug%s", |
| 65 | symbol_conf.symfs, dso->long_name); | 66 | symbol_conf.symfs, dso->long_name); |
| 66 | break; | 67 | break; |
| 67 | 68 | ||
| 68 | case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: | 69 | case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: |
| 69 | { | 70 | { |
| 70 | char *last_slash; | 71 | const char *last_slash; |
| 71 | size_t len; | 72 | size_t len; |
| 72 | size_t dir_size; | 73 | size_t dir_size; |
| 73 | 74 | ||
| @@ -75,14 +76,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
| 75 | while (last_slash != dso->long_name && *last_slash != '/') | 76 | while (last_slash != dso->long_name && *last_slash != '/') |
| 76 | last_slash--; | 77 | last_slash--; |
| 77 | 78 | ||
| 78 | len = scnprintf(file, size, "%s", symbol_conf.symfs); | 79 | len = scnprintf(filename, size, "%s", symbol_conf.symfs); |
| 79 | dir_size = last_slash - dso->long_name + 2; | 80 | dir_size = last_slash - dso->long_name + 2; |
| 80 | if (dir_size > (size - len)) { | 81 | if (dir_size > (size - len)) { |
| 81 | ret = -1; | 82 | ret = -1; |
| 82 | break; | 83 | break; |
| 83 | } | 84 | } |
| 84 | len += scnprintf(file + len, dir_size, "%s", dso->long_name); | 85 | len += scnprintf(filename + len, dir_size, "%s", dso->long_name); |
| 85 | len += scnprintf(file + len , size - len, ".debug%s", | 86 | len += scnprintf(filename + len , size - len, ".debug%s", |
| 86 | last_slash); | 87 | last_slash); |
| 87 | break; | 88 | break; |
| 88 | } | 89 | } |
| @@ -96,7 +97,7 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
| 96 | build_id__sprintf(dso->build_id, | 97 | build_id__sprintf(dso->build_id, |
| 97 | sizeof(dso->build_id), | 98 | sizeof(dso->build_id), |
| 98 | build_id_hex); | 99 | build_id_hex); |
| 99 | snprintf(file, size, | 100 | snprintf(filename, size, |
| 100 | "%s/usr/lib/debug/.build-id/%.2s/%s.debug", | 101 | "%s/usr/lib/debug/.build-id/%.2s/%s.debug", |
| 101 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); | 102 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); |
| 102 | break; | 103 | break; |
| @@ -104,23 +105,23 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
| 104 | case DSO_BINARY_TYPE__VMLINUX: | 105 | case DSO_BINARY_TYPE__VMLINUX: |
| 105 | case DSO_BINARY_TYPE__GUEST_VMLINUX: | 106 | case DSO_BINARY_TYPE__GUEST_VMLINUX: |
| 106 | case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: | 107 | case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: |
| 107 | snprintf(file, size, "%s%s", | 108 | snprintf(filename, size, "%s%s", |
| 108 | symbol_conf.symfs, dso->long_name); | 109 | symbol_conf.symfs, dso->long_name); |
| 109 | break; | 110 | break; |
| 110 | 111 | ||
| 111 | case DSO_BINARY_TYPE__GUEST_KMODULE: | 112 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
| 112 | snprintf(file, size, "%s%s%s", symbol_conf.symfs, | 113 | snprintf(filename, size, "%s%s%s", symbol_conf.symfs, |
| 113 | root_dir, dso->long_name); | 114 | root_dir, dso->long_name); |
| 114 | break; | 115 | break; |
| 115 | 116 | ||
| 116 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: | 117 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: |
| 117 | snprintf(file, size, "%s%s", symbol_conf.symfs, | 118 | snprintf(filename, size, "%s%s", symbol_conf.symfs, |
| 118 | dso->long_name); | 119 | dso->long_name); |
| 119 | break; | 120 | break; |
| 120 | 121 | ||
| 121 | case DSO_BINARY_TYPE__KCORE: | 122 | case DSO_BINARY_TYPE__KCORE: |
| 122 | case DSO_BINARY_TYPE__GUEST_KCORE: | 123 | case DSO_BINARY_TYPE__GUEST_KCORE: |
| 123 | snprintf(file, size, "%s", dso->long_name); | 124 | snprintf(filename, size, "%s", dso->long_name); |
| 124 | break; | 125 | break; |
| 125 | 126 | ||
| 126 | default: | 127 | default: |
| @@ -137,19 +138,18 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
| 137 | 138 | ||
| 138 | static int open_dso(struct dso *dso, struct machine *machine) | 139 | static int open_dso(struct dso *dso, struct machine *machine) |
| 139 | { | 140 | { |
| 140 | char *root_dir = (char *) ""; | ||
| 141 | char *name; | ||
| 142 | int fd; | 141 | int fd; |
| 142 | char *root_dir = (char *)""; | ||
| 143 | char *name = malloc(PATH_MAX); | ||
| 143 | 144 | ||
| 144 | name = malloc(PATH_MAX); | ||
| 145 | if (!name) | 145 | if (!name) |
| 146 | return -ENOMEM; | 146 | return -ENOMEM; |
| 147 | 147 | ||
| 148 | if (machine) | 148 | if (machine) |
| 149 | root_dir = machine->root_dir; | 149 | root_dir = machine->root_dir; |
| 150 | 150 | ||
| 151 | if (dso__binary_type_file(dso, dso->data_type, | 151 | if (dso__read_binary_type_filename(dso, dso->binary_type, |
| 152 | root_dir, name, PATH_MAX)) { | 152 | root_dir, name, PATH_MAX)) { |
| 153 | free(name); | 153 | free(name); |
| 154 | return -EINVAL; | 154 | return -EINVAL; |
| 155 | } | 155 | } |
| @@ -161,26 +161,26 @@ static int open_dso(struct dso *dso, struct machine *machine) | |||
| 161 | 161 | ||
| 162 | int dso__data_fd(struct dso *dso, struct machine *machine) | 162 | int dso__data_fd(struct dso *dso, struct machine *machine) |
| 163 | { | 163 | { |
| 164 | static enum dso_binary_type binary_type_data[] = { | 164 | enum dso_binary_type binary_type_data[] = { |
| 165 | DSO_BINARY_TYPE__BUILD_ID_CACHE, | 165 | DSO_BINARY_TYPE__BUILD_ID_CACHE, |
| 166 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 166 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
| 167 | DSO_BINARY_TYPE__NOT_FOUND, | 167 | DSO_BINARY_TYPE__NOT_FOUND, |
| 168 | }; | 168 | }; |
| 169 | int i = 0; | 169 | int i = 0; |
| 170 | 170 | ||
| 171 | if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND) | 171 | if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) |
| 172 | return open_dso(dso, machine); | 172 | return open_dso(dso, machine); |
| 173 | 173 | ||
| 174 | do { | 174 | do { |
| 175 | int fd; | 175 | int fd; |
| 176 | 176 | ||
| 177 | dso->data_type = binary_type_data[i++]; | 177 | dso->binary_type = binary_type_data[i++]; |
| 178 | 178 | ||
| 179 | fd = open_dso(dso, machine); | 179 | fd = open_dso(dso, machine); |
| 180 | if (fd >= 0) | 180 | if (fd >= 0) |
| 181 | return fd; | 181 | return fd; |
| 182 | 182 | ||
| 183 | } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND); | 183 | } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND); |
| 184 | 184 | ||
| 185 | return -EINVAL; | 185 | return -EINVAL; |
| 186 | } | 186 | } |
| @@ -200,11 +200,10 @@ dso_cache__free(struct rb_root *root) | |||
| 200 | } | 200 | } |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static struct dso_cache* | 203 | static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) |
| 204 | dso_cache__find(struct rb_root *root, u64 offset) | ||
| 205 | { | 204 | { |
| 206 | struct rb_node **p = &root->rb_node; | 205 | struct rb_node * const *p = &root->rb_node; |
| 207 | struct rb_node *parent = NULL; | 206 | const struct rb_node *parent = NULL; |
| 208 | struct dso_cache *cache; | 207 | struct dso_cache *cache; |
| 209 | 208 | ||
| 210 | while (*p != NULL) { | 209 | while (*p != NULL) { |
| @@ -379,32 +378,63 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, | |||
| 379 | * processing we had no idea this was the kernel dso. | 378 | * processing we had no idea this was the kernel dso. |
| 380 | */ | 379 | */ |
| 381 | if (dso != NULL) { | 380 | if (dso != NULL) { |
| 382 | dso__set_short_name(dso, short_name); | 381 | dso__set_short_name(dso, short_name, false); |
| 383 | dso->kernel = dso_type; | 382 | dso->kernel = dso_type; |
| 384 | } | 383 | } |
| 385 | 384 | ||
| 386 | return dso; | 385 | return dso; |
| 387 | } | 386 | } |
| 388 | 387 | ||
| 389 | void dso__set_long_name(struct dso *dso, char *name) | 388 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) |
| 390 | { | 389 | { |
| 391 | if (name == NULL) | 390 | if (name == NULL) |
| 392 | return; | 391 | return; |
| 393 | dso->long_name = name; | 392 | |
| 394 | dso->long_name_len = strlen(name); | 393 | if (dso->long_name_allocated) |
| 394 | free((char *)dso->long_name); | ||
| 395 | |||
| 396 | dso->long_name = name; | ||
| 397 | dso->long_name_len = strlen(name); | ||
| 398 | dso->long_name_allocated = name_allocated; | ||
| 395 | } | 399 | } |
| 396 | 400 | ||
| 397 | void dso__set_short_name(struct dso *dso, const char *name) | 401 | void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated) |
| 398 | { | 402 | { |
| 399 | if (name == NULL) | 403 | if (name == NULL) |
| 400 | return; | 404 | return; |
| 401 | dso->short_name = name; | 405 | |
| 402 | dso->short_name_len = strlen(name); | 406 | if (dso->short_name_allocated) |
| 407 | free((char *)dso->short_name); | ||
| 408 | |||
| 409 | dso->short_name = name; | ||
| 410 | dso->short_name_len = strlen(name); | ||
| 411 | dso->short_name_allocated = name_allocated; | ||
| 403 | } | 412 | } |
| 404 | 413 | ||
| 405 | static void dso__set_basename(struct dso *dso) | 414 | static void dso__set_basename(struct dso *dso) |
| 406 | { | 415 | { |
| 407 | dso__set_short_name(dso, basename(dso->long_name)); | 416 | /* |
| 417 | * basename() may modify path buffer, so we must pass | ||
| 418 | * a copy. | ||
| 419 | */ | ||
| 420 | char *base, *lname = strdup(dso->long_name); | ||
| 421 | |||
| 422 | if (!lname) | ||
| 423 | return; | ||
| 424 | |||
| 425 | /* | ||
| 426 | * basename() may return a pointer to internal | ||
| 427 | * storage which is reused in subsequent calls | ||
| 428 | * so copy the result. | ||
| 429 | */ | ||
| 430 | base = strdup(basename(lname)); | ||
| 431 | |||
| 432 | free(lname); | ||
| 433 | |||
| 434 | if (!base) | ||
| 435 | return; | ||
| 436 | |||
| 437 | dso__set_short_name(dso, base, true); | ||
| 408 | } | 438 | } |
| 409 | 439 | ||
| 410 | int dso__name_len(const struct dso *dso) | 440 | int dso__name_len(const struct dso *dso) |
| @@ -439,18 +469,19 @@ struct dso *dso__new(const char *name) | |||
| 439 | if (dso != NULL) { | 469 | if (dso != NULL) { |
| 440 | int i; | 470 | int i; |
| 441 | strcpy(dso->name, name); | 471 | strcpy(dso->name, name); |
| 442 | dso__set_long_name(dso, dso->name); | 472 | dso__set_long_name(dso, dso->name, false); |
| 443 | dso__set_short_name(dso, dso->name); | 473 | dso__set_short_name(dso, dso->name, false); |
| 444 | for (i = 0; i < MAP__NR_TYPES; ++i) | 474 | for (i = 0; i < MAP__NR_TYPES; ++i) |
| 445 | dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; | 475 | dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; |
| 446 | dso->cache = RB_ROOT; | 476 | dso->cache = RB_ROOT; |
| 447 | dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; | 477 | dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; |
| 448 | dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; | 478 | dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND; |
| 449 | dso->loaded = 0; | 479 | dso->loaded = 0; |
| 450 | dso->rel = 0; | 480 | dso->rel = 0; |
| 451 | dso->sorted_by_name = 0; | 481 | dso->sorted_by_name = 0; |
| 452 | dso->has_build_id = 0; | 482 | dso->has_build_id = 0; |
| 453 | dso->has_srcline = 1; | 483 | dso->has_srcline = 1; |
| 484 | dso->a2l_fails = 1; | ||
| 454 | dso->kernel = DSO_TYPE_USER; | 485 | dso->kernel = DSO_TYPE_USER; |
| 455 | dso->needs_swap = DSO_SWAP__UNSET; | 486 | dso->needs_swap = DSO_SWAP__UNSET; |
| 456 | INIT_LIST_HEAD(&dso->node); | 487 | INIT_LIST_HEAD(&dso->node); |
| @@ -464,11 +495,20 @@ void dso__delete(struct dso *dso) | |||
| 464 | int i; | 495 | int i; |
| 465 | for (i = 0; i < MAP__NR_TYPES; ++i) | 496 | for (i = 0; i < MAP__NR_TYPES; ++i) |
| 466 | symbols__delete(&dso->symbols[i]); | 497 | symbols__delete(&dso->symbols[i]); |
| 467 | if (dso->sname_alloc) | 498 | |
| 468 | free((char *)dso->short_name); | 499 | if (dso->short_name_allocated) { |
| 469 | if (dso->lname_alloc) | 500 | zfree((char **)&dso->short_name); |
| 470 | free(dso->long_name); | 501 | dso->short_name_allocated = false; |
| 502 | } | ||
| 503 | |||
| 504 | if (dso->long_name_allocated) { | ||
| 505 | zfree((char **)&dso->long_name); | ||
| 506 | dso->long_name_allocated = false; | ||
| 507 | } | ||
| 508 | |||
| 471 | dso_cache__free(&dso->cache); | 509 | dso_cache__free(&dso->cache); |
| 510 | dso__free_a2l(dso); | ||
| 511 | zfree(&dso->symsrc_filename); | ||
| 472 | free(dso); | 512 | free(dso); |
| 473 | } | 513 | } |
| 474 | 514 | ||
| @@ -543,7 +583,7 @@ void dsos__add(struct list_head *head, struct dso *dso) | |||
| 543 | list_add_tail(&dso->node, head); | 583 | list_add_tail(&dso->node, head); |
| 544 | } | 584 | } |
| 545 | 585 | ||
| 546 | struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short) | 586 | struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) |
| 547 | { | 587 | { |
| 548 | struct dso *pos; | 588 | struct dso *pos; |
| 549 | 589 | ||
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 9ac666abbe7e..cd7d6f078cdd 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
| @@ -77,23 +77,26 @@ struct dso { | |||
| 77 | struct rb_root symbols[MAP__NR_TYPES]; | 77 | struct rb_root symbols[MAP__NR_TYPES]; |
| 78 | struct rb_root symbol_names[MAP__NR_TYPES]; | 78 | struct rb_root symbol_names[MAP__NR_TYPES]; |
| 79 | struct rb_root cache; | 79 | struct rb_root cache; |
| 80 | void *a2l; | ||
| 81 | char *symsrc_filename; | ||
| 82 | unsigned int a2l_fails; | ||
| 80 | enum dso_kernel_type kernel; | 83 | enum dso_kernel_type kernel; |
| 81 | enum dso_swap_type needs_swap; | 84 | enum dso_swap_type needs_swap; |
| 82 | enum dso_binary_type symtab_type; | 85 | enum dso_binary_type symtab_type; |
| 83 | enum dso_binary_type data_type; | 86 | enum dso_binary_type binary_type; |
| 84 | u8 adjust_symbols:1; | 87 | u8 adjust_symbols:1; |
| 85 | u8 has_build_id:1; | 88 | u8 has_build_id:1; |
| 86 | u8 has_srcline:1; | 89 | u8 has_srcline:1; |
| 87 | u8 hit:1; | 90 | u8 hit:1; |
| 88 | u8 annotate_warned:1; | 91 | u8 annotate_warned:1; |
| 89 | u8 sname_alloc:1; | 92 | u8 short_name_allocated:1; |
| 90 | u8 lname_alloc:1; | 93 | u8 long_name_allocated:1; |
| 91 | u8 sorted_by_name; | 94 | u8 sorted_by_name; |
| 92 | u8 loaded; | 95 | u8 loaded; |
| 93 | u8 rel; | 96 | u8 rel; |
| 94 | u8 build_id[BUILD_ID_SIZE]; | 97 | u8 build_id[BUILD_ID_SIZE]; |
| 95 | const char *short_name; | 98 | const char *short_name; |
| 96 | char *long_name; | 99 | const char *long_name; |
| 97 | u16 long_name_len; | 100 | u16 long_name_len; |
| 98 | u16 short_name_len; | 101 | u16 short_name_len; |
| 99 | char name[0]; | 102 | char name[0]; |
| @@ -107,8 +110,8 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type) | |||
| 107 | struct dso *dso__new(const char *name); | 110 | struct dso *dso__new(const char *name); |
| 108 | void dso__delete(struct dso *dso); | 111 | void dso__delete(struct dso *dso); |
| 109 | 112 | ||
| 110 | void dso__set_short_name(struct dso *dso, const char *name); | 113 | void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated); |
| 111 | void dso__set_long_name(struct dso *dso, char *name); | 114 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated); |
| 112 | 115 | ||
| 113 | int dso__name_len(const struct dso *dso); | 116 | int dso__name_len(const struct dso *dso); |
| 114 | 117 | ||
| @@ -125,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso, | |||
| 125 | int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); | 128 | int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); |
| 126 | 129 | ||
| 127 | char dso__symtab_origin(const struct dso *dso); | 130 | char dso__symtab_origin(const struct dso *dso); |
| 128 | int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | 131 | int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, |
| 129 | char *root_dir, char *file, size_t size); | 132 | char *root_dir, char *filename, size_t size); |
| 130 | 133 | ||
| 131 | int dso__data_fd(struct dso *dso, struct machine *machine); | 134 | int dso__data_fd(struct dso *dso, struct machine *machine); |
| 132 | ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, | 135 | ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, |
| @@ -140,7 +143,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, | |||
| 140 | const char *short_name, int dso_type); | 143 | const char *short_name, int dso_type); |
| 141 | 144 | ||
| 142 | void dsos__add(struct list_head *head, struct dso *dso); | 145 | void dsos__add(struct list_head *head, struct dso *dso); |
| 143 | struct dso *dsos__find(struct list_head *head, const char *name, | 146 | struct dso *dsos__find(const struct list_head *head, const char *name, |
| 144 | bool cmp_short); | 147 | bool cmp_short); |
| 145 | struct dso *__dsos__findnew(struct list_head *head, const char *name); | 148 | struct dso *__dsos__findnew(struct list_head *head, const char *name); |
| 146 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); | 149 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); |
| @@ -156,14 +159,16 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); | |||
| 156 | 159 | ||
| 157 | static inline bool dso__is_vmlinux(struct dso *dso) | 160 | static inline bool dso__is_vmlinux(struct dso *dso) |
| 158 | { | 161 | { |
| 159 | return dso->data_type == DSO_BINARY_TYPE__VMLINUX || | 162 | return dso->binary_type == DSO_BINARY_TYPE__VMLINUX || |
| 160 | dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX; | 163 | dso->binary_type == DSO_BINARY_TYPE__GUEST_VMLINUX; |
| 161 | } | 164 | } |
| 162 | 165 | ||
| 163 | static inline bool dso__is_kcore(struct dso *dso) | 166 | static inline bool dso__is_kcore(struct dso *dso) |
| 164 | { | 167 | { |
| 165 | return dso->data_type == DSO_BINARY_TYPE__KCORE || | 168 | return dso->binary_type == DSO_BINARY_TYPE__KCORE || |
| 166 | dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; | 169 | dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE; |
| 167 | } | 170 | } |
| 168 | 171 | ||
| 172 | void dso__free_a2l(struct dso *dso); | ||
| 173 | |||
| 169 | #endif /* __PERF_DSO */ | 174 | #endif /* __PERF_DSO */ |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index bb788c109fe6..1fc1c2f04772 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "strlist.h" | 7 | #include "strlist.h" |
| 8 | #include "thread.h" | 8 | #include "thread.h" |
| 9 | #include "thread_map.h" | 9 | #include "thread_map.h" |
| 10 | #include "symbol/kallsyms.h" | ||
| 10 | 11 | ||
| 11 | static const char *perf_event__names[] = { | 12 | static const char *perf_event__names[] = { |
| 12 | [0] = "TOTAL", | 13 | [0] = "TOTAL", |
| @@ -105,8 +106,12 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
| 105 | 106 | ||
| 106 | memset(&event->comm, 0, sizeof(event->comm)); | 107 | memset(&event->comm, 0, sizeof(event->comm)); |
| 107 | 108 | ||
| 108 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, | 109 | if (machine__is_host(machine)) |
| 109 | sizeof(event->comm.comm)); | 110 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, |
| 111 | sizeof(event->comm.comm)); | ||
| 112 | else | ||
| 113 | tgid = machine->pid; | ||
| 114 | |||
| 110 | if (tgid < 0) | 115 | if (tgid < 0) |
| 111 | goto out; | 116 | goto out; |
| 112 | 117 | ||
| @@ -128,7 +133,11 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
| 128 | goto out; | 133 | goto out; |
| 129 | } | 134 | } |
| 130 | 135 | ||
| 131 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | 136 | if (machine__is_default_guest(machine)) |
| 137 | return 0; | ||
| 138 | |||
| 139 | snprintf(filename, sizeof(filename), "%s/proc/%d/task", | ||
| 140 | machine->root_dir, pid); | ||
| 132 | 141 | ||
| 133 | tasks = opendir(filename); | 142 | tasks = opendir(filename); |
| 134 | if (tasks == NULL) { | 143 | if (tasks == NULL) { |
| @@ -166,18 +175,22 @@ out: | |||
| 166 | return tgid; | 175 | return tgid; |
| 167 | } | 176 | } |
| 168 | 177 | ||
| 169 | static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | 178 | int perf_event__synthesize_mmap_events(struct perf_tool *tool, |
| 170 | union perf_event *event, | 179 | union perf_event *event, |
| 171 | pid_t pid, pid_t tgid, | 180 | pid_t pid, pid_t tgid, |
| 172 | perf_event__handler_t process, | 181 | perf_event__handler_t process, |
| 173 | struct machine *machine, | 182 | struct machine *machine, |
| 174 | bool mmap_data) | 183 | bool mmap_data) |
| 175 | { | 184 | { |
| 176 | char filename[PATH_MAX]; | 185 | char filename[PATH_MAX]; |
| 177 | FILE *fp; | 186 | FILE *fp; |
| 178 | int rc = 0; | 187 | int rc = 0; |
| 179 | 188 | ||
| 180 | snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); | 189 | if (machine__is_default_guest(machine)) |
| 190 | return 0; | ||
| 191 | |||
| 192 | snprintf(filename, sizeof(filename), "%s/proc/%d/maps", | ||
| 193 | machine->root_dir, pid); | ||
| 181 | 194 | ||
| 182 | fp = fopen(filename, "r"); | 195 | fp = fopen(filename, "r"); |
| 183 | if (fp == NULL) { | 196 | if (fp == NULL) { |
| @@ -217,7 +230,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
| 217 | /* | 230 | /* |
| 218 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | 231 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c |
| 219 | */ | 232 | */ |
| 220 | event->header.misc = PERF_RECORD_MISC_USER; | 233 | if (machine__is_host(machine)) |
| 234 | event->header.misc = PERF_RECORD_MISC_USER; | ||
| 235 | else | ||
| 236 | event->header.misc = PERF_RECORD_MISC_GUEST_USER; | ||
| 221 | 237 | ||
| 222 | if (prot[2] != 'x') { | 238 | if (prot[2] != 'x') { |
| 223 | if (!mmap_data || prot[0] != 'r') | 239 | if (!mmap_data || prot[0] != 'r') |
| @@ -386,6 +402,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, | |||
| 386 | struct machine *machine, bool mmap_data) | 402 | struct machine *machine, bool mmap_data) |
| 387 | { | 403 | { |
| 388 | DIR *proc; | 404 | DIR *proc; |
| 405 | char proc_path[PATH_MAX]; | ||
| 389 | struct dirent dirent, *next; | 406 | struct dirent dirent, *next; |
| 390 | union perf_event *comm_event, *mmap_event; | 407 | union perf_event *comm_event, *mmap_event; |
| 391 | int err = -1; | 408 | int err = -1; |
| @@ -398,7 +415,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool, | |||
| 398 | if (mmap_event == NULL) | 415 | if (mmap_event == NULL) |
| 399 | goto out_free_comm; | 416 | goto out_free_comm; |
| 400 | 417 | ||
| 401 | proc = opendir("/proc"); | 418 | if (machine__is_default_guest(machine)) |
| 419 | return 0; | ||
| 420 | |||
| 421 | snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); | ||
| 422 | proc = opendir(proc_path); | ||
| 423 | |||
| 402 | if (proc == NULL) | 424 | if (proc == NULL) |
| 403 | goto out_free_mmap; | 425 | goto out_free_mmap; |
| 404 | 426 | ||
| @@ -637,6 +659,7 @@ void thread__find_addr_map(struct thread *thread, | |||
| 637 | struct map_groups *mg = &thread->mg; | 659 | struct map_groups *mg = &thread->mg; |
| 638 | bool load_map = false; | 660 | bool load_map = false; |
| 639 | 661 | ||
| 662 | al->machine = machine; | ||
| 640 | al->thread = thread; | 663 | al->thread = thread; |
| 641 | al->addr = addr; | 664 | al->addr = addr; |
| 642 | al->cpumode = cpumode; | 665 | al->cpumode = cpumode; |
| @@ -657,15 +680,10 @@ void thread__find_addr_map(struct thread *thread, | |||
| 657 | al->level = 'g'; | 680 | al->level = 'g'; |
| 658 | mg = &machine->kmaps; | 681 | mg = &machine->kmaps; |
| 659 | load_map = true; | 682 | load_map = true; |
| 683 | } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) { | ||
| 684 | al->level = 'u'; | ||
| 660 | } else { | 685 | } else { |
| 661 | /* | 686 | al->level = 'H'; |
| 662 | * 'u' means guest os user space. | ||
| 663 | * TODO: We don't support guest user space. Might support late. | ||
| 664 | */ | ||
| 665 | if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) | ||
| 666 | al->level = 'u'; | ||
| 667 | else | ||
| 668 | al->level = 'H'; | ||
| 669 | al->map = NULL; | 687 | al->map = NULL; |
| 670 | 688 | ||
| 671 | if ((cpumode == PERF_RECORD_MISC_GUEST_USER || | 689 | if ((cpumode == PERF_RECORD_MISC_GUEST_USER || |
| @@ -732,8 +750,7 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
| 732 | if (thread == NULL) | 750 | if (thread == NULL) |
| 733 | return -1; | 751 | return -1; |
| 734 | 752 | ||
| 735 | if (symbol_conf.comm_list && | 753 | if (thread__is_filtered(thread)) |
| 736 | !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) | ||
| 737 | goto out_filtered; | 754 | goto out_filtered; |
| 738 | 755 | ||
| 739 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); | 756 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 30fec9901e44..faf6e219be21 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
| @@ -266,6 +266,13 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
| 266 | const struct perf_sample *sample, | 266 | const struct perf_sample *sample, |
| 267 | bool swapped); | 267 | bool swapped); |
| 268 | 268 | ||
| 269 | int perf_event__synthesize_mmap_events(struct perf_tool *tool, | ||
| 270 | union perf_event *event, | ||
| 271 | pid_t pid, pid_t tgid, | ||
| 272 | perf_event__handler_t process, | ||
| 273 | struct machine *machine, | ||
| 274 | bool mmap_data); | ||
| 275 | |||
| 269 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); | 276 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); |
| 270 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); | 277 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); |
| 271 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); | 278 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index bbc746aa5716..40bd2c04df8a 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * Released under the GPL v2. (and only v2, not any later version) | 7 | * Released under the GPL v2. (and only v2, not any later version) |
| 8 | */ | 8 | */ |
| 9 | #include "util.h" | 9 | #include "util.h" |
| 10 | #include <lk/debugfs.h> | 10 | #include <api/fs/debugfs.h> |
| 11 | #include <poll.h> | 11 | #include <poll.h> |
| 12 | #include "cpumap.h" | 12 | #include "cpumap.h" |
| 13 | #include "thread_map.h" | 13 | #include "thread_map.h" |
| @@ -81,7 +81,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist) | |||
| 81 | { | 81 | { |
| 82 | struct perf_evsel *evsel; | 82 | struct perf_evsel *evsel; |
| 83 | 83 | ||
| 84 | list_for_each_entry(evsel, &evlist->entries, node) | 84 | evlist__for_each(evlist, evsel) |
| 85 | perf_evsel__calc_id_pos(evsel); | 85 | perf_evsel__calc_id_pos(evsel); |
| 86 | 86 | ||
| 87 | perf_evlist__set_id_pos(evlist); | 87 | perf_evlist__set_id_pos(evlist); |
| @@ -91,7 +91,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist) | |||
| 91 | { | 91 | { |
| 92 | struct perf_evsel *pos, *n; | 92 | struct perf_evsel *pos, *n; |
| 93 | 93 | ||
| 94 | list_for_each_entry_safe(pos, n, &evlist->entries, node) { | 94 | evlist__for_each_safe(evlist, n, pos) { |
| 95 | list_del_init(&pos->node); | 95 | list_del_init(&pos->node); |
| 96 | perf_evsel__delete(pos); | 96 | perf_evsel__delete(pos); |
| 97 | } | 97 | } |
| @@ -101,14 +101,18 @@ static void perf_evlist__purge(struct perf_evlist *evlist) | |||
| 101 | 101 | ||
| 102 | void perf_evlist__exit(struct perf_evlist *evlist) | 102 | void perf_evlist__exit(struct perf_evlist *evlist) |
| 103 | { | 103 | { |
| 104 | free(evlist->mmap); | 104 | zfree(&evlist->mmap); |
| 105 | free(evlist->pollfd); | 105 | zfree(&evlist->pollfd); |
| 106 | evlist->mmap = NULL; | ||
| 107 | evlist->pollfd = NULL; | ||
| 108 | } | 106 | } |
| 109 | 107 | ||
| 110 | void perf_evlist__delete(struct perf_evlist *evlist) | 108 | void perf_evlist__delete(struct perf_evlist *evlist) |
| 111 | { | 109 | { |
| 110 | perf_evlist__munmap(evlist); | ||
| 111 | perf_evlist__close(evlist); | ||
| 112 | cpu_map__delete(evlist->cpus); | ||
| 113 | thread_map__delete(evlist->threads); | ||
| 114 | evlist->cpus = NULL; | ||
| 115 | evlist->threads = NULL; | ||
| 112 | perf_evlist__purge(evlist); | 116 | perf_evlist__purge(evlist); |
| 113 | perf_evlist__exit(evlist); | 117 | perf_evlist__exit(evlist); |
| 114 | free(evlist); | 118 | free(evlist); |
| @@ -144,7 +148,7 @@ void __perf_evlist__set_leader(struct list_head *list) | |||
| 144 | 148 | ||
| 145 | leader->nr_members = evsel->idx - leader->idx + 1; | 149 | leader->nr_members = evsel->idx - leader->idx + 1; |
| 146 | 150 | ||
| 147 | list_for_each_entry(evsel, list, node) { | 151 | __evlist__for_each(list, evsel) { |
| 148 | evsel->leader = leader; | 152 | evsel->leader = leader; |
| 149 | } | 153 | } |
| 150 | } | 154 | } |
| @@ -203,7 +207,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, | |||
| 203 | return 0; | 207 | return 0; |
| 204 | 208 | ||
| 205 | out_delete_partial_list: | 209 | out_delete_partial_list: |
| 206 | list_for_each_entry_safe(evsel, n, &head, node) | 210 | __evlist__for_each_safe(&head, n, evsel) |
| 207 | perf_evsel__delete(evsel); | 211 | perf_evsel__delete(evsel); |
| 208 | return -1; | 212 | return -1; |
| 209 | } | 213 | } |
| @@ -224,7 +228,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) | |||
| 224 | { | 228 | { |
| 225 | struct perf_evsel *evsel; | 229 | struct perf_evsel *evsel; |
| 226 | 230 | ||
| 227 | list_for_each_entry(evsel, &evlist->entries, node) { | 231 | evlist__for_each(evlist, evsel) { |
| 228 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && | 232 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && |
| 229 | (int)evsel->attr.config == id) | 233 | (int)evsel->attr.config == id) |
| 230 | return evsel; | 234 | return evsel; |
| @@ -239,7 +243,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, | |||
| 239 | { | 243 | { |
| 240 | struct perf_evsel *evsel; | 244 | struct perf_evsel *evsel; |
| 241 | 245 | ||
| 242 | list_for_each_entry(evsel, &evlist->entries, node) { | 246 | evlist__for_each(evlist, evsel) { |
| 243 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && | 247 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && |
| 244 | (strcmp(evsel->name, name) == 0)) | 248 | (strcmp(evsel->name, name) == 0)) |
| 245 | return evsel; | 249 | return evsel; |
| @@ -269,7 +273,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) | |||
| 269 | int nr_threads = thread_map__nr(evlist->threads); | 273 | int nr_threads = thread_map__nr(evlist->threads); |
| 270 | 274 | ||
| 271 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 275 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
| 272 | list_for_each_entry(pos, &evlist->entries, node) { | 276 | evlist__for_each(evlist, pos) { |
| 273 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 277 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
| 274 | continue; | 278 | continue; |
| 275 | for (thread = 0; thread < nr_threads; thread++) | 279 | for (thread = 0; thread < nr_threads; thread++) |
| @@ -287,7 +291,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) | |||
| 287 | int nr_threads = thread_map__nr(evlist->threads); | 291 | int nr_threads = thread_map__nr(evlist->threads); |
| 288 | 292 | ||
| 289 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 293 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
| 290 | list_for_each_entry(pos, &evlist->entries, node) { | 294 | evlist__for_each(evlist, pos) { |
| 291 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 295 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
| 292 | continue; | 296 | continue; |
| 293 | for (thread = 0; thread < nr_threads; thread++) | 297 | for (thread = 0; thread < nr_threads; thread++) |
| @@ -584,11 +588,13 @@ void perf_evlist__munmap(struct perf_evlist *evlist) | |||
| 584 | { | 588 | { |
| 585 | int i; | 589 | int i; |
| 586 | 590 | ||
| 591 | if (evlist->mmap == NULL) | ||
| 592 | return; | ||
| 593 | |||
| 587 | for (i = 0; i < evlist->nr_mmaps; i++) | 594 | for (i = 0; i < evlist->nr_mmaps; i++) |
| 588 | __perf_evlist__munmap(evlist, i); | 595 | __perf_evlist__munmap(evlist, i); |
| 589 | 596 | ||
| 590 | free(evlist->mmap); | 597 | zfree(&evlist->mmap); |
| 591 | evlist->mmap = NULL; | ||
| 592 | } | 598 | } |
| 593 | 599 | ||
| 594 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 600 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
| @@ -624,7 +630,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
| 624 | { | 630 | { |
| 625 | struct perf_evsel *evsel; | 631 | struct perf_evsel *evsel; |
| 626 | 632 | ||
| 627 | list_for_each_entry(evsel, &evlist->entries, node) { | 633 | evlist__for_each(evlist, evsel) { |
| 628 | int fd = FD(evsel, cpu, thread); | 634 | int fd = FD(evsel, cpu, thread); |
| 629 | 635 | ||
| 630 | if (*output == -1) { | 636 | if (*output == -1) { |
| @@ -732,11 +738,13 @@ static long parse_pages_arg(const char *str, unsigned long min, | |||
| 732 | return -EINVAL; | 738 | return -EINVAL; |
| 733 | } | 739 | } |
| 734 | 740 | ||
| 735 | if ((pages == 0) && (min == 0)) { | 741 | if (pages == 0 && min == 0) { |
| 736 | /* leave number of pages at 0 */ | 742 | /* leave number of pages at 0 */ |
| 737 | } else if (pages < (1UL << 31) && !is_power_of_2(pages)) { | 743 | } else if (!is_power_of_2(pages)) { |
| 738 | /* round pages up to next power of 2 */ | 744 | /* round pages up to next power of 2 */ |
| 739 | pages = next_pow2(pages); | 745 | pages = next_pow2_l(pages); |
| 746 | if (!pages) | ||
| 747 | return -EINVAL; | ||
| 740 | pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", | 748 | pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", |
| 741 | pages * page_size, pages); | 749 | pages * page_size, pages); |
| 742 | } | 750 | } |
| @@ -754,7 +762,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, | |||
| 754 | unsigned long max = UINT_MAX; | 762 | unsigned long max = UINT_MAX; |
| 755 | long pages; | 763 | long pages; |
| 756 | 764 | ||
| 757 | if (max < SIZE_MAX / page_size) | 765 | if (max > SIZE_MAX / page_size) |
| 758 | max = SIZE_MAX / page_size; | 766 | max = SIZE_MAX / page_size; |
| 759 | 767 | ||
| 760 | pages = parse_pages_arg(str, 1, max); | 768 | pages = parse_pages_arg(str, 1, max); |
| @@ -798,7 +806,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, | |||
| 798 | pr_debug("mmap size %zuB\n", evlist->mmap_len); | 806 | pr_debug("mmap size %zuB\n", evlist->mmap_len); |
| 799 | mask = evlist->mmap_len - page_size - 1; | 807 | mask = evlist->mmap_len - page_size - 1; |
| 800 | 808 | ||
| 801 | list_for_each_entry(evsel, &evlist->entries, node) { | 809 | evlist__for_each(evlist, evsel) { |
| 802 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 810 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
| 803 | evsel->sample_id == NULL && | 811 | evsel->sample_id == NULL && |
| 804 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) | 812 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) |
| @@ -819,11 +827,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | |||
| 819 | if (evlist->threads == NULL) | 827 | if (evlist->threads == NULL) |
| 820 | return -1; | 828 | return -1; |
| 821 | 829 | ||
| 822 | if (target->force_per_cpu) | 830 | if (target__uses_dummy_map(target)) |
| 823 | evlist->cpus = cpu_map__new(target->cpu_list); | ||
| 824 | else if (target__has_task(target)) | ||
| 825 | evlist->cpus = cpu_map__dummy_new(); | ||
| 826 | else if (!target__has_cpu(target) && !target->uses_mmap) | ||
| 827 | evlist->cpus = cpu_map__dummy_new(); | 831 | evlist->cpus = cpu_map__dummy_new(); |
| 828 | else | 832 | else |
| 829 | evlist->cpus = cpu_map__new(target->cpu_list); | 833 | evlist->cpus = cpu_map__new(target->cpu_list); |
| @@ -838,14 +842,6 @@ out_delete_threads: | |||
| 838 | return -1; | 842 | return -1; |
| 839 | } | 843 | } |
| 840 | 844 | ||
| 841 | void perf_evlist__delete_maps(struct perf_evlist *evlist) | ||
| 842 | { | ||
| 843 | cpu_map__delete(evlist->cpus); | ||
| 844 | thread_map__delete(evlist->threads); | ||
| 845 | evlist->cpus = NULL; | ||
| 846 | evlist->threads = NULL; | ||
| 847 | } | ||
| 848 | |||
| 849 | int perf_evlist__apply_filters(struct perf_evlist *evlist) | 845 | int perf_evlist__apply_filters(struct perf_evlist *evlist) |
| 850 | { | 846 | { |
| 851 | struct perf_evsel *evsel; | 847 | struct perf_evsel *evsel; |
| @@ -853,7 +849,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist) | |||
| 853 | const int ncpus = cpu_map__nr(evlist->cpus), | 849 | const int ncpus = cpu_map__nr(evlist->cpus), |
| 854 | nthreads = thread_map__nr(evlist->threads); | 850 | nthreads = thread_map__nr(evlist->threads); |
| 855 | 851 | ||
| 856 | list_for_each_entry(evsel, &evlist->entries, node) { | 852 | evlist__for_each(evlist, evsel) { |
| 857 | if (evsel->filter == NULL) | 853 | if (evsel->filter == NULL) |
| 858 | continue; | 854 | continue; |
| 859 | 855 | ||
| @@ -872,7 +868,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) | |||
| 872 | const int ncpus = cpu_map__nr(evlist->cpus), | 868 | const int ncpus = cpu_map__nr(evlist->cpus), |
| 873 | nthreads = thread_map__nr(evlist->threads); | 869 | nthreads = thread_map__nr(evlist->threads); |
| 874 | 870 | ||
| 875 | list_for_each_entry(evsel, &evlist->entries, node) { | 871 | evlist__for_each(evlist, evsel) { |
| 876 | err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); | 872 | err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); |
| 877 | if (err) | 873 | if (err) |
| 878 | break; | 874 | break; |
| @@ -891,7 +887,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) | |||
| 891 | if (evlist->id_pos < 0 || evlist->is_pos < 0) | 887 | if (evlist->id_pos < 0 || evlist->is_pos < 0) |
| 892 | return false; | 888 | return false; |
| 893 | 889 | ||
| 894 | list_for_each_entry(pos, &evlist->entries, node) { | 890 | evlist__for_each(evlist, pos) { |
| 895 | if (pos->id_pos != evlist->id_pos || | 891 | if (pos->id_pos != evlist->id_pos || |
| 896 | pos->is_pos != evlist->is_pos) | 892 | pos->is_pos != evlist->is_pos) |
| 897 | return false; | 893 | return false; |
| @@ -907,7 +903,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) | |||
| 907 | if (evlist->combined_sample_type) | 903 | if (evlist->combined_sample_type) |
| 908 | return evlist->combined_sample_type; | 904 | return evlist->combined_sample_type; |
| 909 | 905 | ||
| 910 | list_for_each_entry(evsel, &evlist->entries, node) | 906 | evlist__for_each(evlist, evsel) |
| 911 | evlist->combined_sample_type |= evsel->attr.sample_type; | 907 | evlist->combined_sample_type |= evsel->attr.sample_type; |
| 912 | 908 | ||
| 913 | return evlist->combined_sample_type; | 909 | return evlist->combined_sample_type; |
| @@ -925,7 +921,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist) | |||
| 925 | u64 read_format = first->attr.read_format; | 921 | u64 read_format = first->attr.read_format; |
| 926 | u64 sample_type = first->attr.sample_type; | 922 | u64 sample_type = first->attr.sample_type; |
| 927 | 923 | ||
| 928 | list_for_each_entry_continue(pos, &evlist->entries, node) { | 924 | evlist__for_each(evlist, pos) { |
| 929 | if (read_format != pos->attr.read_format) | 925 | if (read_format != pos->attr.read_format) |
| 930 | return false; | 926 | return false; |
| 931 | } | 927 | } |
| @@ -982,7 +978,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) | |||
| 982 | { | 978 | { |
| 983 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; | 979 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; |
| 984 | 980 | ||
| 985 | list_for_each_entry_continue(pos, &evlist->entries, node) { | 981 | evlist__for_each_continue(evlist, pos) { |
| 986 | if (first->attr.sample_id_all != pos->attr.sample_id_all) | 982 | if (first->attr.sample_id_all != pos->attr.sample_id_all) |
| 987 | return false; | 983 | return false; |
| 988 | } | 984 | } |
| @@ -1008,7 +1004,7 @@ void perf_evlist__close(struct perf_evlist *evlist) | |||
| 1008 | int ncpus = cpu_map__nr(evlist->cpus); | 1004 | int ncpus = cpu_map__nr(evlist->cpus); |
| 1009 | int nthreads = thread_map__nr(evlist->threads); | 1005 | int nthreads = thread_map__nr(evlist->threads); |
| 1010 | 1006 | ||
| 1011 | list_for_each_entry_reverse(evsel, &evlist->entries, node) | 1007 | evlist__for_each_reverse(evlist, evsel) |
| 1012 | perf_evsel__close(evsel, ncpus, nthreads); | 1008 | perf_evsel__close(evsel, ncpus, nthreads); |
| 1013 | } | 1009 | } |
| 1014 | 1010 | ||
| @@ -1019,7 +1015,7 @@ int perf_evlist__open(struct perf_evlist *evlist) | |||
| 1019 | 1015 | ||
| 1020 | perf_evlist__update_id_pos(evlist); | 1016 | perf_evlist__update_id_pos(evlist); |
| 1021 | 1017 | ||
| 1022 | list_for_each_entry(evsel, &evlist->entries, node) { | 1018 | evlist__for_each(evlist, evsel) { |
| 1023 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); | 1019 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); |
| 1024 | if (err < 0) | 1020 | if (err < 0) |
| 1025 | goto out_err; | 1021 | goto out_err; |
| @@ -1034,7 +1030,7 @@ out_err: | |||
| 1034 | 1030 | ||
| 1035 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, | 1031 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, |
| 1036 | const char *argv[], bool pipe_output, | 1032 | const char *argv[], bool pipe_output, |
| 1037 | bool want_signal) | 1033 | void (*exec_error)(int signo, siginfo_t *info, void *ucontext)) |
| 1038 | { | 1034 | { |
| 1039 | int child_ready_pipe[2], go_pipe[2]; | 1035 | int child_ready_pipe[2], go_pipe[2]; |
| 1040 | char bf; | 1036 | char bf; |
| @@ -1078,12 +1074,25 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar | |||
| 1078 | 1074 | ||
| 1079 | execvp(argv[0], (char **)argv); | 1075 | execvp(argv[0], (char **)argv); |
| 1080 | 1076 | ||
| 1081 | perror(argv[0]); | 1077 | if (exec_error) { |
| 1082 | if (want_signal) | 1078 | union sigval val; |
| 1083 | kill(getppid(), SIGUSR1); | 1079 | |
| 1080 | val.sival_int = errno; | ||
| 1081 | if (sigqueue(getppid(), SIGUSR1, val)) | ||
| 1082 | perror(argv[0]); | ||
| 1083 | } else | ||
| 1084 | perror(argv[0]); | ||
| 1084 | exit(-1); | 1085 | exit(-1); |
| 1085 | } | 1086 | } |
| 1086 | 1087 | ||
| 1088 | if (exec_error) { | ||
| 1089 | struct sigaction act = { | ||
| 1090 | .sa_flags = SA_SIGINFO, | ||
| 1091 | .sa_sigaction = exec_error, | ||
| 1092 | }; | ||
| 1093 | sigaction(SIGUSR1, &act, NULL); | ||
| 1094 | } | ||
| 1095 | |||
| 1087 | if (target__none(target)) | 1096 | if (target__none(target)) |
| 1088 | evlist->threads->map[0] = evlist->workload.pid; | 1097 | evlist->threads->map[0] = evlist->workload.pid; |
| 1089 | 1098 | ||
| @@ -1145,7 +1154,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) | |||
| 1145 | struct perf_evsel *evsel; | 1154 | struct perf_evsel *evsel; |
| 1146 | size_t printed = 0; | 1155 | size_t printed = 0; |
| 1147 | 1156 | ||
| 1148 | list_for_each_entry(evsel, &evlist->entries, node) { | 1157 | evlist__for_each(evlist, evsel) { |
| 1149 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", | 1158 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", |
| 1150 | perf_evsel__name(evsel)); | 1159 | perf_evsel__name(evsel)); |
| 1151 | } | 1160 | } |
| @@ -1193,8 +1202,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, | |||
| 1193 | "Error:\t%s.\n" | 1202 | "Error:\t%s.\n" |
| 1194 | "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); | 1203 | "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); |
| 1195 | 1204 | ||
| 1196 | if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) | 1205 | value = perf_event_paranoid(); |
| 1197 | break; | ||
| 1198 | 1206 | ||
| 1199 | printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); | 1207 | printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); |
| 1200 | 1208 | ||
| @@ -1215,3 +1223,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, | |||
| 1215 | 1223 | ||
| 1216 | return 0; | 1224 | return 0; |
| 1217 | } | 1225 | } |
| 1226 | |||
| 1227 | void perf_evlist__to_front(struct perf_evlist *evlist, | ||
| 1228 | struct perf_evsel *move_evsel) | ||
| 1229 | { | ||
| 1230 | struct perf_evsel *evsel, *n; | ||
| 1231 | LIST_HEAD(move); | ||
| 1232 | |||
| 1233 | if (move_evsel == perf_evlist__first(evlist)) | ||
| 1234 | return; | ||
| 1235 | |||
| 1236 | evlist__for_each_safe(evlist, n, evsel) { | ||
| 1237 | if (evsel->leader == move_evsel->leader) | ||
| 1238 | list_move_tail(&evsel->node, &move); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | list_splice(&move, &evlist->entries); | ||
| 1242 | } | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 649d6ea98a84..f5173cd63693 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | struct pollfd; | 12 | struct pollfd; |
| 13 | struct thread_map; | 13 | struct thread_map; |
| 14 | struct cpu_map; | 14 | struct cpu_map; |
| 15 | struct perf_record_opts; | 15 | struct record_opts; |
| 16 | 16 | ||
| 17 | #define PERF_EVLIST__HLIST_BITS 8 | 17 | #define PERF_EVLIST__HLIST_BITS 8 |
| 18 | #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) | 18 | #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) |
| @@ -97,14 +97,14 @@ void perf_evlist__close(struct perf_evlist *evlist); | |||
| 97 | 97 | ||
| 98 | void perf_evlist__set_id_pos(struct perf_evlist *evlist); | 98 | void perf_evlist__set_id_pos(struct perf_evlist *evlist); |
| 99 | bool perf_can_sample_identifier(void); | 99 | bool perf_can_sample_identifier(void); |
| 100 | void perf_evlist__config(struct perf_evlist *evlist, | 100 | void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); |
| 101 | struct perf_record_opts *opts); | 101 | int record_opts__config(struct record_opts *opts); |
| 102 | int perf_record_opts__config(struct perf_record_opts *opts); | ||
| 103 | 102 | ||
| 104 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, | 103 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, |
| 105 | struct target *target, | 104 | struct target *target, |
| 106 | const char *argv[], bool pipe_output, | 105 | const char *argv[], bool pipe_output, |
| 107 | bool want_signal); | 106 | void (*exec_error)(int signo, siginfo_t *info, |
| 107 | void *ucontext)); | ||
| 108 | int perf_evlist__start_workload(struct perf_evlist *evlist); | 108 | int perf_evlist__start_workload(struct perf_evlist *evlist); |
| 109 | 109 | ||
| 110 | int perf_evlist__parse_mmap_pages(const struct option *opt, | 110 | int perf_evlist__parse_mmap_pages(const struct option *opt, |
| @@ -135,7 +135,6 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, | |||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); | 137 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); |
| 138 | void perf_evlist__delete_maps(struct perf_evlist *evlist); | ||
| 139 | int perf_evlist__apply_filters(struct perf_evlist *evlist); | 138 | int perf_evlist__apply_filters(struct perf_evlist *evlist); |
| 140 | 139 | ||
| 141 | void __perf_evlist__set_leader(struct list_head *list); | 140 | void __perf_evlist__set_leader(struct list_head *list); |
| @@ -193,4 +192,74 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, | |||
| 193 | pc->data_tail = tail; | 192 | pc->data_tail = tail; |
| 194 | } | 193 | } |
| 195 | 194 | ||
| 195 | bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str); | ||
| 196 | void perf_evlist__to_front(struct perf_evlist *evlist, | ||
| 197 | struct perf_evsel *move_evsel); | ||
| 198 | |||
| 199 | /** | ||
| 200 | * __evlist__for_each - iterate thru all the evsels | ||
| 201 | * @list: list_head instance to iterate | ||
| 202 | * @evsel: struct evsel iterator | ||
| 203 | */ | ||
| 204 | #define __evlist__for_each(list, evsel) \ | ||
| 205 | list_for_each_entry(evsel, list, node) | ||
| 206 | |||
| 207 | /** | ||
| 208 | * evlist__for_each - iterate thru all the evsels | ||
| 209 | * @evlist: evlist instance to iterate | ||
| 210 | * @evsel: struct evsel iterator | ||
| 211 | */ | ||
| 212 | #define evlist__for_each(evlist, evsel) \ | ||
| 213 | __evlist__for_each(&(evlist)->entries, evsel) | ||
| 214 | |||
| 215 | /** | ||
| 216 | * __evlist__for_each_continue - continue iteration thru all the evsels | ||
| 217 | * @list: list_head instance to iterate | ||
| 218 | * @evsel: struct evsel iterator | ||
| 219 | */ | ||
| 220 | #define __evlist__for_each_continue(list, evsel) \ | ||
| 221 | list_for_each_entry_continue(evsel, list, node) | ||
| 222 | |||
| 223 | /** | ||
| 224 | * evlist__for_each_continue - continue iteration thru all the evsels | ||
| 225 | * @evlist: evlist instance to iterate | ||
| 226 | * @evsel: struct evsel iterator | ||
| 227 | */ | ||
| 228 | #define evlist__for_each_continue(evlist, evsel) \ | ||
| 229 | __evlist__for_each_continue(&(evlist)->entries, evsel) | ||
| 230 | |||
| 231 | /** | ||
| 232 | * __evlist__for_each_reverse - iterate thru all the evsels in reverse order | ||
| 233 | * @list: list_head instance to iterate | ||
| 234 | * @evsel: struct evsel iterator | ||
| 235 | */ | ||
| 236 | #define __evlist__for_each_reverse(list, evsel) \ | ||
| 237 | list_for_each_entry_reverse(evsel, list, node) | ||
| 238 | |||
| 239 | /** | ||
| 240 | * evlist__for_each_reverse - iterate thru all the evsels in reverse order | ||
| 241 | * @evlist: evlist instance to iterate | ||
| 242 | * @evsel: struct evsel iterator | ||
| 243 | */ | ||
| 244 | #define evlist__for_each_reverse(evlist, evsel) \ | ||
| 245 | __evlist__for_each_reverse(&(evlist)->entries, evsel) | ||
| 246 | |||
| 247 | /** | ||
| 248 | * __evlist__for_each_safe - safely iterate thru all the evsels | ||
| 249 | * @list: list_head instance to iterate | ||
| 250 | * @tmp: struct evsel temp iterator | ||
| 251 | * @evsel: struct evsel iterator | ||
| 252 | */ | ||
| 253 | #define __evlist__for_each_safe(list, tmp, evsel) \ | ||
| 254 | list_for_each_entry_safe(evsel, tmp, list, node) | ||
| 255 | |||
| 256 | /** | ||
| 257 | * evlist__for_each_safe - safely iterate thru all the evsels | ||
| 258 | * @evlist: evlist instance to iterate | ||
| 259 | * @evsel: struct evsel iterator | ||
| 260 | * @tmp: struct evsel temp iterator | ||
| 261 | */ | ||
| 262 | #define evlist__for_each_safe(evlist, tmp, evsel) \ | ||
| 263 | __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) | ||
| 264 | |||
| 196 | #endif /* __PERF_EVLIST_H */ | 265 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 46dd4c2a41ce..22e18a26b7e6 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <byteswap.h> | 10 | #include <byteswap.h> |
| 11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
| 12 | #include <lk/debugfs.h> | 12 | #include <api/fs/debugfs.h> |
| 13 | #include <traceevent/event-parse.h> | 13 | #include <traceevent/event-parse.h> |
| 14 | #include <linux/hw_breakpoint.h> | 14 | #include <linux/hw_breakpoint.h> |
| 15 | #include <linux/perf_event.h> | 15 | #include <linux/perf_event.h> |
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "target.h" | 23 | #include "target.h" |
| 24 | #include "perf_regs.h" | 24 | #include "perf_regs.h" |
| 25 | #include "debug.h" | 25 | #include "debug.h" |
| 26 | #include "trace-event.h" | ||
| 26 | 27 | ||
| 27 | static struct { | 28 | static struct { |
| 28 | bool sample_id_all; | 29 | bool sample_id_all; |
| @@ -162,6 +163,8 @@ void perf_evsel__init(struct perf_evsel *evsel, | |||
| 162 | evsel->idx = idx; | 163 | evsel->idx = idx; |
| 163 | evsel->attr = *attr; | 164 | evsel->attr = *attr; |
| 164 | evsel->leader = evsel; | 165 | evsel->leader = evsel; |
| 166 | evsel->unit = ""; | ||
| 167 | evsel->scale = 1.0; | ||
| 165 | INIT_LIST_HEAD(&evsel->node); | 168 | INIT_LIST_HEAD(&evsel->node); |
| 166 | hists__init(&evsel->hists); | 169 | hists__init(&evsel->hists); |
| 167 | evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); | 170 | evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); |
| @@ -178,47 +181,6 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) | |||
| 178 | return evsel; | 181 | return evsel; |
| 179 | } | 182 | } |
| 180 | 183 | ||
| 181 | struct event_format *event_format__new(const char *sys, const char *name) | ||
| 182 | { | ||
| 183 | int fd, n; | ||
| 184 | char *filename; | ||
| 185 | void *bf = NULL, *nbf; | ||
| 186 | size_t size = 0, alloc_size = 0; | ||
| 187 | struct event_format *format = NULL; | ||
| 188 | |||
| 189 | if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0) | ||
| 190 | goto out; | ||
| 191 | |||
| 192 | fd = open(filename, O_RDONLY); | ||
| 193 | if (fd < 0) | ||
| 194 | goto out_free_filename; | ||
| 195 | |||
| 196 | do { | ||
| 197 | if (size == alloc_size) { | ||
| 198 | alloc_size += BUFSIZ; | ||
| 199 | nbf = realloc(bf, alloc_size); | ||
| 200 | if (nbf == NULL) | ||
| 201 | goto out_free_bf; | ||
| 202 | bf = nbf; | ||
| 203 | } | ||
| 204 | |||
| 205 | n = read(fd, bf + size, alloc_size - size); | ||
| 206 | if (n < 0) | ||
| 207 | goto out_free_bf; | ||
| 208 | size += n; | ||
| 209 | } while (n > 0); | ||
| 210 | |||
| 211 | pevent_parse_format(&format, bf, size, sys); | ||
| 212 | |||
| 213 | out_free_bf: | ||
| 214 | free(bf); | ||
| 215 | close(fd); | ||
| 216 | out_free_filename: | ||
| 217 | free(filename); | ||
| 218 | out: | ||
| 219 | return format; | ||
| 220 | } | ||
| 221 | |||
| 222 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) | 184 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) |
| 223 | { | 185 | { |
| 224 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | 186 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); |
| @@ -233,7 +195,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int | |||
| 233 | if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) | 195 | if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) |
| 234 | goto out_free; | 196 | goto out_free; |
| 235 | 197 | ||
| 236 | evsel->tp_format = event_format__new(sys, name); | 198 | evsel->tp_format = trace_event__tp_format(sys, name); |
| 237 | if (evsel->tp_format == NULL) | 199 | if (evsel->tp_format == NULL) |
| 238 | goto out_free; | 200 | goto out_free; |
| 239 | 201 | ||
| @@ -246,7 +208,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int | |||
| 246 | return evsel; | 208 | return evsel; |
| 247 | 209 | ||
| 248 | out_free: | 210 | out_free: |
| 249 | free(evsel->name); | 211 | zfree(&evsel->name); |
| 250 | free(evsel); | 212 | free(evsel); |
| 251 | return NULL; | 213 | return NULL; |
| 252 | } | 214 | } |
| @@ -566,12 +528,12 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) | |||
| 566 | * enable/disable events specifically, as there's no | 528 | * enable/disable events specifically, as there's no |
| 567 | * initial traced exec call. | 529 | * initial traced exec call. |
| 568 | */ | 530 | */ |
| 569 | void perf_evsel__config(struct perf_evsel *evsel, | 531 | void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) |
| 570 | struct perf_record_opts *opts) | ||
| 571 | { | 532 | { |
| 572 | struct perf_evsel *leader = evsel->leader; | 533 | struct perf_evsel *leader = evsel->leader; |
| 573 | struct perf_event_attr *attr = &evsel->attr; | 534 | struct perf_event_attr *attr = &evsel->attr; |
| 574 | int track = !evsel->idx; /* only the first counter needs these */ | 535 | int track = !evsel->idx; /* only the first counter needs these */ |
| 536 | bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; | ||
| 575 | 537 | ||
| 576 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; | 538 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; |
| 577 | attr->inherit = !opts->no_inherit; | 539 | attr->inherit = !opts->no_inherit; |
| @@ -645,7 +607,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
| 645 | } | 607 | } |
| 646 | } | 608 | } |
| 647 | 609 | ||
| 648 | if (target__has_cpu(&opts->target) || opts->target.force_per_cpu) | 610 | if (target__has_cpu(&opts->target)) |
| 649 | perf_evsel__set_sample_bit(evsel, CPU); | 611 | perf_evsel__set_sample_bit(evsel, CPU); |
| 650 | 612 | ||
| 651 | if (opts->period) | 613 | if (opts->period) |
| @@ -653,7 +615,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
| 653 | 615 | ||
| 654 | if (!perf_missing_features.sample_id_all && | 616 | if (!perf_missing_features.sample_id_all && |
| 655 | (opts->sample_time || !opts->no_inherit || | 617 | (opts->sample_time || !opts->no_inherit || |
| 656 | target__has_cpu(&opts->target) || opts->target.force_per_cpu)) | 618 | target__has_cpu(&opts->target) || per_cpu)) |
| 657 | perf_evsel__set_sample_bit(evsel, TIME); | 619 | perf_evsel__set_sample_bit(evsel, TIME); |
| 658 | 620 | ||
| 659 | if (opts->raw_samples) { | 621 | if (opts->raw_samples) { |
| @@ -665,7 +627,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
| 665 | if (opts->sample_address) | 627 | if (opts->sample_address) |
| 666 | perf_evsel__set_sample_bit(evsel, DATA_SRC); | 628 | perf_evsel__set_sample_bit(evsel, DATA_SRC); |
| 667 | 629 | ||
| 668 | if (opts->no_delay) { | 630 | if (opts->no_buffering) { |
| 669 | attr->watermark = 0; | 631 | attr->watermark = 0; |
| 670 | attr->wakeup_events = 1; | 632 | attr->wakeup_events = 1; |
| 671 | } | 633 | } |
| @@ -696,7 +658,8 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
| 696 | * Setting enable_on_exec for independent events and | 658 | * Setting enable_on_exec for independent events and |
| 697 | * group leaders for traced executed by perf. | 659 | * group leaders for traced executed by perf. |
| 698 | */ | 660 | */ |
| 699 | if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) | 661 | if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) && |
| 662 | !opts->initial_delay) | ||
| 700 | attr->enable_on_exec = 1; | 663 | attr->enable_on_exec = 1; |
| 701 | } | 664 | } |
| 702 | 665 | ||
| @@ -788,8 +751,7 @@ void perf_evsel__free_id(struct perf_evsel *evsel) | |||
| 788 | { | 751 | { |
| 789 | xyarray__delete(evsel->sample_id); | 752 | xyarray__delete(evsel->sample_id); |
| 790 | evsel->sample_id = NULL; | 753 | evsel->sample_id = NULL; |
| 791 | free(evsel->id); | 754 | zfree(&evsel->id); |
| 792 | evsel->id = NULL; | ||
| 793 | } | 755 | } |
| 794 | 756 | ||
| 795 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 757 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
| @@ -805,7 +767,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
| 805 | 767 | ||
| 806 | void perf_evsel__free_counts(struct perf_evsel *evsel) | 768 | void perf_evsel__free_counts(struct perf_evsel *evsel) |
| 807 | { | 769 | { |
| 808 | free(evsel->counts); | 770 | zfree(&evsel->counts); |
| 809 | } | 771 | } |
| 810 | 772 | ||
| 811 | void perf_evsel__exit(struct perf_evsel *evsel) | 773 | void perf_evsel__exit(struct perf_evsel *evsel) |
| @@ -819,10 +781,10 @@ void perf_evsel__delete(struct perf_evsel *evsel) | |||
| 819 | { | 781 | { |
| 820 | perf_evsel__exit(evsel); | 782 | perf_evsel__exit(evsel); |
| 821 | close_cgroup(evsel->cgrp); | 783 | close_cgroup(evsel->cgrp); |
| 822 | free(evsel->group_name); | 784 | zfree(&evsel->group_name); |
| 823 | if (evsel->tp_format) | 785 | if (evsel->tp_format) |
| 824 | pevent_free_format(evsel->tp_format); | 786 | pevent_free_format(evsel->tp_format); |
| 825 | free(evsel->name); | 787 | zfree(&evsel->name); |
| 826 | free(evsel); | 788 | free(evsel); |
| 827 | } | 789 | } |
| 828 | 790 | ||
| @@ -1998,8 +1960,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, | |||
| 1998 | evsel->attr.type = PERF_TYPE_SOFTWARE; | 1960 | evsel->attr.type = PERF_TYPE_SOFTWARE; |
| 1999 | evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; | 1961 | evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; |
| 2000 | 1962 | ||
| 2001 | free(evsel->name); | 1963 | zfree(&evsel->name); |
| 2002 | evsel->name = NULL; | ||
| 2003 | return true; | 1964 | return true; |
| 2004 | } | 1965 | } |
| 2005 | 1966 | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1ea7c92e6e33..f1b325665aae 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -68,6 +68,8 @@ struct perf_evsel { | |||
| 68 | u32 ids; | 68 | u32 ids; |
| 69 | struct hists hists; | 69 | struct hists hists; |
| 70 | char *name; | 70 | char *name; |
| 71 | double scale; | ||
| 72 | const char *unit; | ||
| 71 | struct event_format *tp_format; | 73 | struct event_format *tp_format; |
| 72 | union { | 74 | union { |
| 73 | void *priv; | 75 | void *priv; |
| @@ -94,7 +96,7 @@ struct perf_evsel { | |||
| 94 | struct cpu_map; | 96 | struct cpu_map; |
| 95 | struct thread_map; | 97 | struct thread_map; |
| 96 | struct perf_evlist; | 98 | struct perf_evlist; |
| 97 | struct perf_record_opts; | 99 | struct record_opts; |
| 98 | 100 | ||
| 99 | struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); | 101 | struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); |
| 100 | 102 | ||
| @@ -118,7 +120,7 @@ void perf_evsel__exit(struct perf_evsel *evsel); | |||
| 118 | void perf_evsel__delete(struct perf_evsel *evsel); | 120 | void perf_evsel__delete(struct perf_evsel *evsel); |
| 119 | 121 | ||
| 120 | void perf_evsel__config(struct perf_evsel *evsel, | 122 | void perf_evsel__config(struct perf_evsel *evsel, |
| 121 | struct perf_record_opts *opts); | 123 | struct record_opts *opts); |
| 122 | 124 | ||
| 123 | int __perf_evsel__sample_size(u64 sample_type); | 125 | int __perf_evsel__sample_size(u64 sample_type); |
| 124 | void perf_evsel__calc_id_pos(struct perf_evsel *evsel); | 126 | void perf_evsel__calc_id_pos(struct perf_evsel *evsel); |
| @@ -138,6 +140,7 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX]; | |||
| 138 | int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, | 140 | int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, |
| 139 | char *bf, size_t size); | 141 | char *bf, size_t size); |
| 140 | const char *perf_evsel__name(struct perf_evsel *evsel); | 142 | const char *perf_evsel__name(struct perf_evsel *evsel); |
| 143 | |||
| 141 | const char *perf_evsel__group_name(struct perf_evsel *evsel); | 144 | const char *perf_evsel__group_name(struct perf_evsel *evsel); |
| 142 | int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); | 145 | int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); |
| 143 | 146 | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1cd035708931..bb3e0ede6183 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -177,7 +177,7 @@ perf_header__set_cmdline(int argc, const char **argv) | |||
| 177 | continue; \ | 177 | continue; \ |
| 178 | else | 178 | else |
| 179 | 179 | ||
| 180 | static int write_buildid(char *name, size_t name_len, u8 *build_id, | 180 | static int write_buildid(const char *name, size_t name_len, u8 *build_id, |
| 181 | pid_t pid, u16 misc, int fd) | 181 | pid_t pid, u16 misc, int fd) |
| 182 | { | 182 | { |
| 183 | int err; | 183 | int err; |
| @@ -209,7 +209,7 @@ static int __dsos__write_buildid_table(struct list_head *head, | |||
| 209 | 209 | ||
| 210 | dsos__for_each_with_build_id(pos, head) { | 210 | dsos__for_each_with_build_id(pos, head) { |
| 211 | int err; | 211 | int err; |
| 212 | char *name; | 212 | const char *name; |
| 213 | size_t name_len; | 213 | size_t name_len; |
| 214 | 214 | ||
| 215 | if (!pos->hit) | 215 | if (!pos->hit) |
| @@ -387,7 +387,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine, | |||
| 387 | { | 387 | { |
| 388 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; | 388 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; |
| 389 | bool is_vdso = is_vdso_map(dso->short_name); | 389 | bool is_vdso = is_vdso_map(dso->short_name); |
| 390 | char *name = dso->long_name; | 390 | const char *name = dso->long_name; |
| 391 | char nm[PATH_MAX]; | 391 | char nm[PATH_MAX]; |
| 392 | 392 | ||
| 393 | if (dso__is_kcore(dso)) { | 393 | if (dso__is_kcore(dso)) { |
| @@ -643,8 +643,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused, | |||
| 643 | if (ret < 0) | 643 | if (ret < 0) |
| 644 | return ret; | 644 | return ret; |
| 645 | 645 | ||
| 646 | list_for_each_entry(evsel, &evlist->entries, node) { | 646 | evlist__for_each(evlist, evsel) { |
| 647 | |||
| 648 | ret = do_write(fd, &evsel->attr, sz); | 647 | ret = do_write(fd, &evsel->attr, sz); |
| 649 | if (ret < 0) | 648 | if (ret < 0) |
| 650 | return ret; | 649 | return ret; |
| @@ -800,10 +799,10 @@ static void free_cpu_topo(struct cpu_topo *tp) | |||
| 800 | return; | 799 | return; |
| 801 | 800 | ||
| 802 | for (i = 0 ; i < tp->core_sib; i++) | 801 | for (i = 0 ; i < tp->core_sib; i++) |
| 803 | free(tp->core_siblings[i]); | 802 | zfree(&tp->core_siblings[i]); |
| 804 | 803 | ||
| 805 | for (i = 0 ; i < tp->thread_sib; i++) | 804 | for (i = 0 ; i < tp->thread_sib; i++) |
| 806 | free(tp->thread_siblings[i]); | 805 | zfree(&tp->thread_siblings[i]); |
| 807 | 806 | ||
| 808 | free(tp); | 807 | free(tp); |
| 809 | } | 808 | } |
| @@ -1092,7 +1091,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused, | |||
| 1092 | if (ret < 0) | 1091 | if (ret < 0) |
| 1093 | return ret; | 1092 | return ret; |
| 1094 | 1093 | ||
| 1095 | list_for_each_entry(evsel, &evlist->entries, node) { | 1094 | evlist__for_each(evlist, evsel) { |
| 1096 | if (perf_evsel__is_group_leader(evsel) && | 1095 | if (perf_evsel__is_group_leader(evsel) && |
| 1097 | evsel->nr_members > 1) { | 1096 | evsel->nr_members > 1) { |
| 1098 | const char *name = evsel->group_name ?: "{anon_group}"; | 1097 | const char *name = evsel->group_name ?: "{anon_group}"; |
| @@ -1232,10 +1231,8 @@ static void free_event_desc(struct perf_evsel *events) | |||
| 1232 | return; | 1231 | return; |
| 1233 | 1232 | ||
| 1234 | for (evsel = events; evsel->attr.size; evsel++) { | 1233 | for (evsel = events; evsel->attr.size; evsel++) { |
| 1235 | if (evsel->name) | 1234 | zfree(&evsel->name); |
| 1236 | free(evsel->name); | 1235 | zfree(&evsel->id); |
| 1237 | if (evsel->id) | ||
| 1238 | free(evsel->id); | ||
| 1239 | } | 1236 | } |
| 1240 | 1237 | ||
| 1241 | free(events); | 1238 | free(events); |
| @@ -1326,8 +1323,7 @@ read_event_desc(struct perf_header *ph, int fd) | |||
| 1326 | } | 1323 | } |
| 1327 | } | 1324 | } |
| 1328 | out: | 1325 | out: |
| 1329 | if (buf) | 1326 | free(buf); |
| 1330 | free(buf); | ||
| 1331 | return events; | 1327 | return events; |
| 1332 | error: | 1328 | error: |
| 1333 | if (events) | 1329 | if (events) |
| @@ -1490,7 +1486,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, | |||
| 1490 | 1486 | ||
| 1491 | session = container_of(ph, struct perf_session, header); | 1487 | session = container_of(ph, struct perf_session, header); |
| 1492 | 1488 | ||
| 1493 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 1489 | evlist__for_each(session->evlist, evsel) { |
| 1494 | if (perf_evsel__is_group_leader(evsel) && | 1490 | if (perf_evsel__is_group_leader(evsel) && |
| 1495 | evsel->nr_members > 1) { | 1491 | evsel->nr_members > 1) { |
| 1496 | fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", | 1492 | fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", |
| @@ -1709,7 +1705,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, | |||
| 1709 | struct perf_header *ph, int fd, | 1705 | struct perf_header *ph, int fd, |
| 1710 | void *data __maybe_unused) | 1706 | void *data __maybe_unused) |
| 1711 | { | 1707 | { |
| 1712 | size_t ret; | 1708 | ssize_t ret; |
| 1713 | u32 nr; | 1709 | u32 nr; |
| 1714 | 1710 | ||
| 1715 | ret = readn(fd, &nr, sizeof(nr)); | 1711 | ret = readn(fd, &nr, sizeof(nr)); |
| @@ -1753,7 +1749,7 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused, | |||
| 1753 | void *data __maybe_unused) | 1749 | void *data __maybe_unused) |
| 1754 | { | 1750 | { |
| 1755 | uint64_t mem; | 1751 | uint64_t mem; |
| 1756 | size_t ret; | 1752 | ssize_t ret; |
| 1757 | 1753 | ||
| 1758 | ret = readn(fd, &mem, sizeof(mem)); | 1754 | ret = readn(fd, &mem, sizeof(mem)); |
| 1759 | if (ret != sizeof(mem)) | 1755 | if (ret != sizeof(mem)) |
| @@ -1771,7 +1767,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) | |||
| 1771 | { | 1767 | { |
| 1772 | struct perf_evsel *evsel; | 1768 | struct perf_evsel *evsel; |
| 1773 | 1769 | ||
| 1774 | list_for_each_entry(evsel, &evlist->entries, node) { | 1770 | evlist__for_each(evlist, evsel) { |
| 1775 | if (evsel->idx == idx) | 1771 | if (evsel->idx == idx) |
| 1776 | return evsel; | 1772 | return evsel; |
| 1777 | } | 1773 | } |
| @@ -1822,7 +1818,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, | |||
| 1822 | struct perf_header *ph, int fd, | 1818 | struct perf_header *ph, int fd, |
| 1823 | void *data __maybe_unused) | 1819 | void *data __maybe_unused) |
| 1824 | { | 1820 | { |
| 1825 | size_t ret; | 1821 | ssize_t ret; |
| 1826 | char *str; | 1822 | char *str; |
| 1827 | u32 nr, i; | 1823 | u32 nr, i; |
| 1828 | struct strbuf sb; | 1824 | struct strbuf sb; |
| @@ -1858,7 +1854,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused | |||
| 1858 | struct perf_header *ph, int fd, | 1854 | struct perf_header *ph, int fd, |
| 1859 | void *data __maybe_unused) | 1855 | void *data __maybe_unused) |
| 1860 | { | 1856 | { |
| 1861 | size_t ret; | 1857 | ssize_t ret; |
| 1862 | u32 nr, i; | 1858 | u32 nr, i; |
| 1863 | char *str; | 1859 | char *str; |
| 1864 | struct strbuf sb; | 1860 | struct strbuf sb; |
| @@ -1914,7 +1910,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse | |||
| 1914 | struct perf_header *ph, int fd, | 1910 | struct perf_header *ph, int fd, |
| 1915 | void *data __maybe_unused) | 1911 | void *data __maybe_unused) |
| 1916 | { | 1912 | { |
| 1917 | size_t ret; | 1913 | ssize_t ret; |
| 1918 | u32 nr, node, i; | 1914 | u32 nr, node, i; |
| 1919 | char *str; | 1915 | char *str; |
| 1920 | uint64_t mem_total, mem_free; | 1916 | uint64_t mem_total, mem_free; |
| @@ -1974,7 +1970,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused | |||
| 1974 | struct perf_header *ph, int fd, | 1970 | struct perf_header *ph, int fd, |
| 1975 | void *data __maybe_unused) | 1971 | void *data __maybe_unused) |
| 1976 | { | 1972 | { |
| 1977 | size_t ret; | 1973 | ssize_t ret; |
| 1978 | char *name; | 1974 | char *name; |
| 1979 | u32 pmu_num; | 1975 | u32 pmu_num; |
| 1980 | u32 type; | 1976 | u32 type; |
| @@ -2074,7 +2070,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, | |||
| 2074 | session->evlist->nr_groups = nr_groups; | 2070 | session->evlist->nr_groups = nr_groups; |
| 2075 | 2071 | ||
| 2076 | i = nr = 0; | 2072 | i = nr = 0; |
| 2077 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 2073 | evlist__for_each(session->evlist, evsel) { |
| 2078 | if (evsel->idx == (int) desc[i].leader_idx) { | 2074 | if (evsel->idx == (int) desc[i].leader_idx) { |
| 2079 | evsel->leader = evsel; | 2075 | evsel->leader = evsel; |
| 2080 | /* {anon_group} is a dummy name */ | 2076 | /* {anon_group} is a dummy name */ |
| @@ -2108,7 +2104,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, | |||
| 2108 | ret = 0; | 2104 | ret = 0; |
| 2109 | out_free: | 2105 | out_free: |
| 2110 | for (i = 0; i < nr_groups; i++) | 2106 | for (i = 0; i < nr_groups; i++) |
| 2111 | free(desc[i].name); | 2107 | zfree(&desc[i].name); |
| 2112 | free(desc); | 2108 | free(desc); |
| 2113 | 2109 | ||
| 2114 | return ret; | 2110 | return ret; |
| @@ -2301,7 +2297,7 @@ int perf_session__write_header(struct perf_session *session, | |||
| 2301 | 2297 | ||
| 2302 | lseek(fd, sizeof(f_header), SEEK_SET); | 2298 | lseek(fd, sizeof(f_header), SEEK_SET); |
| 2303 | 2299 | ||
| 2304 | list_for_each_entry(evsel, &evlist->entries, node) { | 2300 | evlist__for_each(session->evlist, evsel) { |
| 2305 | evsel->id_offset = lseek(fd, 0, SEEK_CUR); | 2301 | evsel->id_offset = lseek(fd, 0, SEEK_CUR); |
| 2306 | err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); | 2302 | err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); |
| 2307 | if (err < 0) { | 2303 | if (err < 0) { |
| @@ -2312,7 +2308,7 @@ int perf_session__write_header(struct perf_session *session, | |||
| 2312 | 2308 | ||
| 2313 | attr_offset = lseek(fd, 0, SEEK_CUR); | 2309 | attr_offset = lseek(fd, 0, SEEK_CUR); |
| 2314 | 2310 | ||
| 2315 | list_for_each_entry(evsel, &evlist->entries, node) { | 2311 | evlist__for_each(evlist, evsel) { |
| 2316 | f_attr = (struct perf_file_attr){ | 2312 | f_attr = (struct perf_file_attr){ |
| 2317 | .attr = evsel->attr, | 2313 | .attr = evsel->attr, |
| 2318 | .ids = { | 2314 | .ids = { |
| @@ -2327,7 +2323,8 @@ int perf_session__write_header(struct perf_session *session, | |||
| 2327 | } | 2323 | } |
| 2328 | } | 2324 | } |
| 2329 | 2325 | ||
| 2330 | header->data_offset = lseek(fd, 0, SEEK_CUR); | 2326 | if (!header->data_offset) |
| 2327 | header->data_offset = lseek(fd, 0, SEEK_CUR); | ||
| 2331 | header->feat_offset = header->data_offset + header->data_size; | 2328 | header->feat_offset = header->data_offset + header->data_size; |
| 2332 | 2329 | ||
| 2333 | if (at_exit) { | 2330 | if (at_exit) { |
| @@ -2534,7 +2531,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz, | |||
| 2534 | int perf_file_header__read(struct perf_file_header *header, | 2531 | int perf_file_header__read(struct perf_file_header *header, |
| 2535 | struct perf_header *ph, int fd) | 2532 | struct perf_header *ph, int fd) |
| 2536 | { | 2533 | { |
| 2537 | int ret; | 2534 | ssize_t ret; |
| 2538 | 2535 | ||
| 2539 | lseek(fd, 0, SEEK_SET); | 2536 | lseek(fd, 0, SEEK_SET); |
| 2540 | 2537 | ||
| @@ -2628,7 +2625,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, | |||
| 2628 | struct perf_header *ph, int fd, | 2625 | struct perf_header *ph, int fd, |
| 2629 | bool repipe) | 2626 | bool repipe) |
| 2630 | { | 2627 | { |
| 2631 | int ret; | 2628 | ssize_t ret; |
| 2632 | 2629 | ||
| 2633 | ret = readn(fd, header, sizeof(*header)); | 2630 | ret = readn(fd, header, sizeof(*header)); |
| 2634 | if (ret <= 0) | 2631 | if (ret <= 0) |
| @@ -2669,7 +2666,7 @@ static int read_attr(int fd, struct perf_header *ph, | |||
| 2669 | struct perf_event_attr *attr = &f_attr->attr; | 2666 | struct perf_event_attr *attr = &f_attr->attr; |
| 2670 | size_t sz, left; | 2667 | size_t sz, left; |
| 2671 | size_t our_sz = sizeof(f_attr->attr); | 2668 | size_t our_sz = sizeof(f_attr->attr); |
| 2672 | int ret; | 2669 | ssize_t ret; |
| 2673 | 2670 | ||
| 2674 | memset(f_attr, 0, sizeof(*f_attr)); | 2671 | memset(f_attr, 0, sizeof(*f_attr)); |
| 2675 | 2672 | ||
| @@ -2744,7 +2741,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, | |||
| 2744 | { | 2741 | { |
| 2745 | struct perf_evsel *pos; | 2742 | struct perf_evsel *pos; |
| 2746 | 2743 | ||
| 2747 | list_for_each_entry(pos, &evlist->entries, node) { | 2744 | evlist__for_each(evlist, pos) { |
| 2748 | if (pos->attr.type == PERF_TYPE_TRACEPOINT && | 2745 | if (pos->attr.type == PERF_TYPE_TRACEPOINT && |
| 2749 | perf_evsel__prepare_tracepoint_event(pos, pevent)) | 2746 | perf_evsel__prepare_tracepoint_event(pos, pevent)) |
| 2750 | return -1; | 2747 | return -1; |
| @@ -2834,11 +2831,11 @@ int perf_session__read_header(struct perf_session *session) | |||
| 2834 | 2831 | ||
| 2835 | symbol_conf.nr_events = nr_attrs; | 2832 | symbol_conf.nr_events = nr_attrs; |
| 2836 | 2833 | ||
| 2837 | perf_header__process_sections(header, fd, &session->pevent, | 2834 | perf_header__process_sections(header, fd, &session->tevent, |
| 2838 | perf_file_section__process); | 2835 | perf_file_section__process); |
| 2839 | 2836 | ||
| 2840 | if (perf_evlist__prepare_tracepoint_events(session->evlist, | 2837 | if (perf_evlist__prepare_tracepoint_events(session->evlist, |
| 2841 | session->pevent)) | 2838 | session->tevent.pevent)) |
| 2842 | goto out_delete_evlist; | 2839 | goto out_delete_evlist; |
| 2843 | 2840 | ||
| 2844 | return 0; | 2841 | return 0; |
| @@ -2892,7 +2889,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, | |||
| 2892 | struct perf_evsel *evsel; | 2889 | struct perf_evsel *evsel; |
| 2893 | int err = 0; | 2890 | int err = 0; |
| 2894 | 2891 | ||
| 2895 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 2892 | evlist__for_each(session->evlist, evsel) { |
| 2896 | err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, | 2893 | err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, |
| 2897 | evsel->id, process); | 2894 | evsel->id, process); |
| 2898 | if (err) { | 2895 | if (err) { |
| @@ -3003,7 +3000,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, | |||
| 3003 | lseek(fd, offset + sizeof(struct tracing_data_event), | 3000 | lseek(fd, offset + sizeof(struct tracing_data_event), |
| 3004 | SEEK_SET); | 3001 | SEEK_SET); |
| 3005 | 3002 | ||
| 3006 | size_read = trace_report(fd, &session->pevent, | 3003 | size_read = trace_report(fd, &session->tevent, |
| 3007 | session->repipe); | 3004 | session->repipe); |
| 3008 | padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; | 3005 | padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; |
| 3009 | 3006 | ||
| @@ -3025,7 +3022,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, | |||
| 3025 | } | 3022 | } |
| 3026 | 3023 | ||
| 3027 | perf_evlist__prepare_tracepoint_events(session->evlist, | 3024 | perf_evlist__prepare_tracepoint_events(session->evlist, |
| 3028 | session->pevent); | 3025 | session->tevent.pevent); |
| 3029 | 3026 | ||
| 3030 | return size_read + padding; | 3027 | return size_read + padding; |
| 3031 | } | 3028 | } |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 307c9aed972e..a2d047bdf4ef 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
| @@ -77,16 +77,16 @@ struct perf_session_env { | |||
| 77 | unsigned long long total_mem; | 77 | unsigned long long total_mem; |
| 78 | 78 | ||
| 79 | int nr_cmdline; | 79 | int nr_cmdline; |
| 80 | char *cmdline; | ||
| 81 | int nr_sibling_cores; | 80 | int nr_sibling_cores; |
| 82 | char *sibling_cores; | ||
| 83 | int nr_sibling_threads; | 81 | int nr_sibling_threads; |
| 84 | char *sibling_threads; | ||
| 85 | int nr_numa_nodes; | 82 | int nr_numa_nodes; |
| 86 | char *numa_nodes; | ||
| 87 | int nr_pmu_mappings; | 83 | int nr_pmu_mappings; |
| 88 | char *pmu_mappings; | ||
| 89 | int nr_groups; | 84 | int nr_groups; |
| 85 | char *cmdline; | ||
| 86 | char *sibling_cores; | ||
| 87 | char *sibling_threads; | ||
| 88 | char *numa_nodes; | ||
| 89 | char *pmu_mappings; | ||
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | struct perf_header { | 92 | struct perf_header { |
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 8b1f6e891b8a..86c37c472263 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c | |||
| @@ -22,8 +22,8 @@ static void clean_cmdnames(struct cmdnames *cmds) | |||
| 22 | unsigned int i; | 22 | unsigned int i; |
| 23 | 23 | ||
| 24 | for (i = 0; i < cmds->cnt; ++i) | 24 | for (i = 0; i < cmds->cnt; ++i) |
| 25 | free(cmds->names[i]); | 25 | zfree(&cmds->names[i]); |
| 26 | free(cmds->names); | 26 | zfree(&cmds->names); |
| 27 | cmds->cnt = 0; | 27 | cmds->cnt = 0; |
| 28 | cmds->alloc = 0; | 28 | cmds->alloc = 0; |
| 29 | } | 29 | } |
| @@ -263,9 +263,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) | |||
| 263 | 263 | ||
| 264 | for (i = 0; i < old->cnt; i++) | 264 | for (i = 0; i < old->cnt; i++) |
| 265 | cmds->names[cmds->cnt++] = old->names[i]; | 265 | cmds->names[cmds->cnt++] = old->names[i]; |
| 266 | free(old->names); | 266 | zfree(&old->names); |
| 267 | old->cnt = 0; | 267 | old->cnt = 0; |
| 268 | old->names = NULL; | ||
| 269 | } | 268 | } |
| 270 | 269 | ||
| 271 | const char *help_unknown_cmd(const char *cmd) | 270 | const char *help_unknown_cmd(const char *cmd) |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 822903eaa201..e4e6249b87d4 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | #include "annotate.h" | ||
| 2 | #include "util.h" | 1 | #include "util.h" |
| 3 | #include "build-id.h" | 2 | #include "build-id.h" |
| 4 | #include "hist.h" | 3 | #include "hist.h" |
| @@ -182,21 +181,21 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows) | |||
| 182 | } | 181 | } |
| 183 | } | 182 | } |
| 184 | 183 | ||
| 185 | static void hist_entry__add_cpumode_period(struct hist_entry *he, | 184 | static void he_stat__add_cpumode_period(struct he_stat *he_stat, |
| 186 | unsigned int cpumode, u64 period) | 185 | unsigned int cpumode, u64 period) |
| 187 | { | 186 | { |
| 188 | switch (cpumode) { | 187 | switch (cpumode) { |
| 189 | case PERF_RECORD_MISC_KERNEL: | 188 | case PERF_RECORD_MISC_KERNEL: |
| 190 | he->stat.period_sys += period; | 189 | he_stat->period_sys += period; |
| 191 | break; | 190 | break; |
| 192 | case PERF_RECORD_MISC_USER: | 191 | case PERF_RECORD_MISC_USER: |
| 193 | he->stat.period_us += period; | 192 | he_stat->period_us += period; |
| 194 | break; | 193 | break; |
| 195 | case PERF_RECORD_MISC_GUEST_KERNEL: | 194 | case PERF_RECORD_MISC_GUEST_KERNEL: |
| 196 | he->stat.period_guest_sys += period; | 195 | he_stat->period_guest_sys += period; |
| 197 | break; | 196 | break; |
| 198 | case PERF_RECORD_MISC_GUEST_USER: | 197 | case PERF_RECORD_MISC_GUEST_USER: |
| 199 | he->stat.period_guest_us += period; | 198 | he_stat->period_guest_us += period; |
| 200 | break; | 199 | break; |
| 201 | default: | 200 | default: |
| 202 | break; | 201 | break; |
| @@ -223,10 +222,10 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) | |||
| 223 | dest->weight += src->weight; | 222 | dest->weight += src->weight; |
| 224 | } | 223 | } |
| 225 | 224 | ||
| 226 | static void hist_entry__decay(struct hist_entry *he) | 225 | static void he_stat__decay(struct he_stat *he_stat) |
| 227 | { | 226 | { |
| 228 | he->stat.period = (he->stat.period * 7) / 8; | 227 | he_stat->period = (he_stat->period * 7) / 8; |
| 229 | he->stat.nr_events = (he->stat.nr_events * 7) / 8; | 228 | he_stat->nr_events = (he_stat->nr_events * 7) / 8; |
| 230 | /* XXX need decay for weight too? */ | 229 | /* XXX need decay for weight too? */ |
| 231 | } | 230 | } |
| 232 | 231 | ||
| @@ -237,7 +236,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) | |||
| 237 | if (prev_period == 0) | 236 | if (prev_period == 0) |
| 238 | return true; | 237 | return true; |
| 239 | 238 | ||
| 240 | hist_entry__decay(he); | 239 | he_stat__decay(&he->stat); |
| 241 | 240 | ||
| 242 | if (!he->filtered) | 241 | if (!he->filtered) |
| 243 | hists->stats.total_period -= prev_period - he->stat.period; | 242 | hists->stats.total_period -= prev_period - he->stat.period; |
| @@ -342,15 +341,15 @@ static u8 symbol__parent_filter(const struct symbol *parent) | |||
| 342 | } | 341 | } |
| 343 | 342 | ||
| 344 | static struct hist_entry *add_hist_entry(struct hists *hists, | 343 | static struct hist_entry *add_hist_entry(struct hists *hists, |
| 345 | struct hist_entry *entry, | 344 | struct hist_entry *entry, |
| 346 | struct addr_location *al, | 345 | struct addr_location *al) |
| 347 | u64 period, | ||
| 348 | u64 weight) | ||
| 349 | { | 346 | { |
| 350 | struct rb_node **p; | 347 | struct rb_node **p; |
| 351 | struct rb_node *parent = NULL; | 348 | struct rb_node *parent = NULL; |
| 352 | struct hist_entry *he; | 349 | struct hist_entry *he; |
| 353 | int64_t cmp; | 350 | int64_t cmp; |
| 351 | u64 period = entry->stat.period; | ||
| 352 | u64 weight = entry->stat.weight; | ||
| 354 | 353 | ||
| 355 | p = &hists->entries_in->rb_node; | 354 | p = &hists->entries_in->rb_node; |
| 356 | 355 | ||
| @@ -373,7 +372,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, | |||
| 373 | * This mem info was allocated from machine__resolve_mem | 372 | * This mem info was allocated from machine__resolve_mem |
| 374 | * and will not be used anymore. | 373 | * and will not be used anymore. |
| 375 | */ | 374 | */ |
| 376 | free(entry->mem_info); | 375 | zfree(&entry->mem_info); |
| 377 | 376 | ||
| 378 | /* If the map of an existing hist_entry has | 377 | /* If the map of an existing hist_entry has |
| 379 | * become out-of-date due to an exec() or | 378 | * become out-of-date due to an exec() or |
| @@ -403,7 +402,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, | |||
| 403 | rb_link_node(&he->rb_node_in, parent, p); | 402 | rb_link_node(&he->rb_node_in, parent, p); |
| 404 | rb_insert_color(&he->rb_node_in, hists->entries_in); | 403 | rb_insert_color(&he->rb_node_in, hists->entries_in); |
| 405 | out: | 404 | out: |
| 406 | hist_entry__add_cpumode_period(he, al->cpumode, period); | 405 | he_stat__add_cpumode_period(&he->stat, al->cpumode, period); |
| 407 | return he; | 406 | return he; |
| 408 | } | 407 | } |
| 409 | 408 | ||
| @@ -437,7 +436,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists, | |||
| 437 | .transaction = transaction, | 436 | .transaction = transaction, |
| 438 | }; | 437 | }; |
| 439 | 438 | ||
| 440 | return add_hist_entry(hists, &entry, al, period, weight); | 439 | return add_hist_entry(hists, &entry, al); |
| 441 | } | 440 | } |
| 442 | 441 | ||
| 443 | int64_t | 442 | int64_t |
| @@ -476,8 +475,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) | |||
| 476 | 475 | ||
| 477 | void hist_entry__free(struct hist_entry *he) | 476 | void hist_entry__free(struct hist_entry *he) |
| 478 | { | 477 | { |
| 479 | free(he->branch_info); | 478 | zfree(&he->branch_info); |
| 480 | free(he->mem_info); | 479 | zfree(&he->mem_info); |
| 481 | free_srcline(he->srcline); | 480 | free_srcline(he->srcline); |
| 482 | free(he); | 481 | free(he); |
| 483 | } | 482 | } |
| @@ -807,16 +806,6 @@ void hists__filter_by_symbol(struct hists *hists) | |||
| 807 | } | 806 | } |
| 808 | } | 807 | } |
| 809 | 808 | ||
| 810 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) | ||
| 811 | { | ||
| 812 | return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); | ||
| 813 | } | ||
| 814 | |||
| 815 | int hist_entry__annotate(struct hist_entry *he, size_t privsize) | ||
| 816 | { | ||
| 817 | return symbol__annotate(he->ms.sym, he->ms.map, privsize); | ||
| 818 | } | ||
| 819 | |||
| 820 | void events_stats__inc(struct events_stats *stats, u32 type) | 809 | void events_stats__inc(struct events_stats *stats, u32 type) |
| 821 | { | 810 | { |
| 822 | ++stats->nr_events[0]; | 811 | ++stats->nr_events[0]; |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b621347a1585..a59743fa3ef7 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -111,9 +111,6 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); | |||
| 111 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | 111 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, |
| 112 | int max_cols, float min_pcnt, FILE *fp); | 112 | int max_cols, float min_pcnt, FILE *fp); |
| 113 | 113 | ||
| 114 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); | ||
| 115 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | ||
| 116 | |||
| 117 | void hists__filter_by_dso(struct hists *hists); | 114 | void hists__filter_by_dso(struct hists *hists); |
| 118 | void hists__filter_by_thread(struct hists *hists); | 115 | void hists__filter_by_thread(struct hists *hists); |
| 119 | void hists__filter_by_symbol(struct hists *hists); | 116 | void hists__filter_by_symbol(struct hists *hists); |
diff --git a/tools/perf/util/include/asm/bug.h b/tools/perf/util/include/asm/bug.h deleted file mode 100644 index 7fcc6810adc2..000000000000 --- a/tools/perf/util/include/asm/bug.h +++ /dev/null | |||
| @@ -1,22 +0,0 @@ | |||
| 1 | #ifndef _PERF_ASM_GENERIC_BUG_H | ||
| 2 | #define _PERF_ASM_GENERIC_BUG_H | ||
| 3 | |||
| 4 | #define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0) | ||
| 5 | |||
| 6 | #define WARN(condition, format...) ({ \ | ||
| 7 | int __ret_warn_on = !!(condition); \ | ||
| 8 | if (unlikely(__ret_warn_on)) \ | ||
| 9 | __WARN_printf(format); \ | ||
| 10 | unlikely(__ret_warn_on); \ | ||
| 11 | }) | ||
| 12 | |||
| 13 | #define WARN_ONCE(condition, format...) ({ \ | ||
| 14 | static int __warned; \ | ||
| 15 | int __ret_warn_once = !!(condition); \ | ||
| 16 | \ | ||
| 17 | if (unlikely(__ret_warn_once)) \ | ||
| 18 | if (WARN(!__warned, format)) \ | ||
| 19 | __warned = 1; \ | ||
| 20 | unlikely(__ret_warn_once); \ | ||
| 21 | }) | ||
| 22 | #endif | ||
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h deleted file mode 100644 index b003ad7200b2..000000000000 --- a/tools/perf/util/include/linux/compiler.h +++ /dev/null | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | #ifndef _PERF_LINUX_COMPILER_H_ | ||
| 2 | #define _PERF_LINUX_COMPILER_H_ | ||
| 3 | |||
| 4 | #ifndef __always_inline | ||
| 5 | # define __always_inline inline __attribute__((always_inline)) | ||
| 6 | #endif | ||
| 7 | |||
| 8 | #define __user | ||
| 9 | |||
| 10 | #ifndef __attribute_const__ | ||
| 11 | # define __attribute_const__ | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #ifndef __maybe_unused | ||
| 15 | # define __maybe_unused __attribute__((unused)) | ||
| 16 | #endif | ||
| 17 | |||
| 18 | #ifndef __packed | ||
| 19 | # define __packed __attribute__((__packed__)) | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #ifndef __force | ||
| 23 | # define __force | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #ifndef __weak | ||
| 27 | # define __weak __attribute__((weak)) | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #endif | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 84cdb072ac83..ded74590b92f 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "strlist.h" | 9 | #include "strlist.h" |
| 10 | #include "thread.h" | 10 | #include "thread.h" |
| 11 | #include <stdbool.h> | 11 | #include <stdbool.h> |
| 12 | #include <symbol/kallsyms.h> | ||
| 12 | #include "unwind.h" | 13 | #include "unwind.h" |
| 13 | 14 | ||
| 14 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | 15 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) |
| @@ -26,6 +27,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | |||
| 26 | machine->pid = pid; | 27 | machine->pid = pid; |
| 27 | 28 | ||
| 28 | machine->symbol_filter = NULL; | 29 | machine->symbol_filter = NULL; |
| 30 | machine->id_hdr_size = 0; | ||
| 29 | 31 | ||
| 30 | machine->root_dir = strdup(root_dir); | 32 | machine->root_dir = strdup(root_dir); |
| 31 | if (machine->root_dir == NULL) | 33 | if (machine->root_dir == NULL) |
| @@ -101,8 +103,7 @@ void machine__exit(struct machine *machine) | |||
| 101 | map_groups__exit(&machine->kmaps); | 103 | map_groups__exit(&machine->kmaps); |
| 102 | dsos__delete(&machine->user_dsos); | 104 | dsos__delete(&machine->user_dsos); |
| 103 | dsos__delete(&machine->kernel_dsos); | 105 | dsos__delete(&machine->kernel_dsos); |
| 104 | free(machine->root_dir); | 106 | zfree(&machine->root_dir); |
| 105 | machine->root_dir = NULL; | ||
| 106 | } | 107 | } |
| 107 | 108 | ||
| 108 | void machine__delete(struct machine *machine) | 109 | void machine__delete(struct machine *machine) |
| @@ -502,15 +503,11 @@ static u64 machine__get_kernel_start_addr(struct machine *machine) | |||
| 502 | char path[PATH_MAX]; | 503 | char path[PATH_MAX]; |
| 503 | struct process_args args; | 504 | struct process_args args; |
| 504 | 505 | ||
| 505 | if (machine__is_host(machine)) { | 506 | if (machine__is_default_guest(machine)) |
| 506 | filename = "/proc/kallsyms"; | 507 | filename = (char *)symbol_conf.default_guest_kallsyms; |
| 507 | } else { | 508 | else { |
| 508 | if (machine__is_default_guest(machine)) | 509 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); |
| 509 | filename = (char *)symbol_conf.default_guest_kallsyms; | 510 | filename = path; |
| 510 | else { | ||
| 511 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); | ||
| 512 | filename = path; | ||
| 513 | } | ||
| 514 | } | 511 | } |
| 515 | 512 | ||
| 516 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | 513 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) |
| @@ -565,11 +562,10 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
| 565 | * on one of them. | 562 | * on one of them. |
| 566 | */ | 563 | */ |
| 567 | if (type == MAP__FUNCTION) { | 564 | if (type == MAP__FUNCTION) { |
| 568 | free((char *)kmap->ref_reloc_sym->name); | 565 | zfree((char **)&kmap->ref_reloc_sym->name); |
| 569 | kmap->ref_reloc_sym->name = NULL; | 566 | zfree(&kmap->ref_reloc_sym); |
| 570 | free(kmap->ref_reloc_sym); | 567 | } else |
| 571 | } | 568 | kmap->ref_reloc_sym = NULL; |
| 572 | kmap->ref_reloc_sym = NULL; | ||
| 573 | } | 569 | } |
| 574 | 570 | ||
| 575 | map__delete(machine->vmlinux_maps[type]); | 571 | map__delete(machine->vmlinux_maps[type]); |
| @@ -767,8 +763,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, | |||
| 767 | ret = -1; | 763 | ret = -1; |
| 768 | goto out; | 764 | goto out; |
| 769 | } | 765 | } |
| 770 | dso__set_long_name(map->dso, long_name); | 766 | dso__set_long_name(map->dso, long_name, true); |
| 771 | map->dso->lname_alloc = 1; | ||
| 772 | dso__kernel_module_get_build_id(map->dso, ""); | 767 | dso__kernel_module_get_build_id(map->dso, ""); |
| 773 | } | 768 | } |
| 774 | } | 769 | } |
| @@ -939,8 +934,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
| 939 | if (name == NULL) | 934 | if (name == NULL) |
| 940 | goto out_problem; | 935 | goto out_problem; |
| 941 | 936 | ||
| 942 | map->dso->short_name = name; | 937 | dso__set_short_name(map->dso, name, true); |
| 943 | map->dso->sname_alloc = 1; | ||
| 944 | map->end = map->start + event->mmap.len; | 938 | map->end = map->start + event->mmap.len; |
| 945 | } else if (is_kernel_mmap) { | 939 | } else if (is_kernel_mmap) { |
| 946 | const char *symbol_name = (event->mmap.filename + | 940 | const char *symbol_name = (event->mmap.filename + |
| @@ -1320,8 +1314,6 @@ static int machine__resolve_callchain_sample(struct machine *machine, | |||
| 1320 | *root_al = al; | 1314 | *root_al = al; |
| 1321 | callchain_cursor_reset(&callchain_cursor); | 1315 | callchain_cursor_reset(&callchain_cursor); |
| 1322 | } | 1316 | } |
| 1323 | if (!symbol_conf.use_callchain) | ||
| 1324 | break; | ||
| 1325 | } | 1317 | } |
| 1326 | 1318 | ||
| 1327 | err = callchain_cursor_append(&callchain_cursor, | 1319 | err = callchain_cursor_append(&callchain_cursor, |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ef5bc913ca7a..9b9bd719aa19 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "strlist.h" | 11 | #include "strlist.h" |
| 12 | #include "vdso.h" | 12 | #include "vdso.h" |
| 13 | #include "build-id.h" | 13 | #include "build-id.h" |
| 14 | #include "util.h" | ||
| 14 | #include <linux/string.h> | 15 | #include <linux/string.h> |
| 15 | 16 | ||
| 16 | const char *map_type__name[MAP__NR_TYPES] = { | 17 | const char *map_type__name[MAP__NR_TYPES] = { |
| @@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp) | |||
| 252 | return fprintf(fp, "%s", dsoname); | 253 | return fprintf(fp, "%s", dsoname); |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 256 | int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, | ||
| 257 | FILE *fp) | ||
| 258 | { | ||
| 259 | char *srcline; | ||
| 260 | int ret = 0; | ||
| 261 | |||
| 262 | if (map && map->dso) { | ||
| 263 | srcline = get_srcline(map->dso, | ||
| 264 | map__rip_2objdump(map, addr)); | ||
| 265 | if (srcline != SRCLINE_UNKNOWN) | ||
| 266 | ret = fprintf(fp, "%s%s", prefix, srcline); | ||
| 267 | free_srcline(srcline); | ||
| 268 | } | ||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 255 | /** | 272 | /** |
| 256 | * map__rip_2objdump - convert symbol start address to objdump address. | 273 | * map__rip_2objdump - convert symbol start address to objdump address. |
| 257 | * @map: memory map | 274 | * @map: memory map |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index e4e259c3ba16..18068c6b71c1 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -103,6 +103,8 @@ struct map *map__clone(struct map *map); | |||
| 103 | int map__overlap(struct map *l, struct map *r); | 103 | int map__overlap(struct map *l, struct map *r); |
| 104 | size_t map__fprintf(struct map *map, FILE *fp); | 104 | size_t map__fprintf(struct map *map, FILE *fp); |
| 105 | size_t map__fprintf_dsoname(struct map *map, FILE *fp); | 105 | size_t map__fprintf_dsoname(struct map *map, FILE *fp); |
| 106 | int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, | ||
| 107 | FILE *fp); | ||
| 106 | 108 | ||
| 107 | int map__load(struct map *map, symbol_filter_t filter); | 109 | int map__load(struct map *map, symbol_filter_t filter); |
| 108 | struct symbol *map__find_symbol(struct map *map, | 110 | struct symbol *map__find_symbol(struct map *map, |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6de6f89c2a61..a7f1b6a91fdd 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "symbol.h" | 10 | #include "symbol.h" |
| 11 | #include "cache.h" | 11 | #include "cache.h" |
| 12 | #include "header.h" | 12 | #include "header.h" |
| 13 | #include <lk/debugfs.h> | 13 | #include <api/fs/debugfs.h> |
| 14 | #include "parse-events-bison.h" | 14 | #include "parse-events-bison.h" |
| 15 | #define YY_EXTRA_TYPE int | 15 | #define YY_EXTRA_TYPE int |
| 16 | #include "parse-events-flex.h" | 16 | #include "parse-events-flex.h" |
| @@ -204,7 +204,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) | |||
| 204 | } | 204 | } |
| 205 | path->name = malloc(MAX_EVENT_LENGTH); | 205 | path->name = malloc(MAX_EVENT_LENGTH); |
| 206 | if (!path->name) { | 206 | if (!path->name) { |
| 207 | free(path->system); | 207 | zfree(&path->system); |
| 208 | free(path); | 208 | free(path); |
| 209 | return NULL; | 209 | return NULL; |
| 210 | } | 210 | } |
| @@ -236,8 +236,8 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name) | |||
| 236 | path->name = strdup(str+1); | 236 | path->name = strdup(str+1); |
| 237 | 237 | ||
| 238 | if (path->system == NULL || path->name == NULL) { | 238 | if (path->system == NULL || path->name == NULL) { |
| 239 | free(path->system); | 239 | zfree(&path->system); |
| 240 | free(path->name); | 240 | zfree(&path->name); |
| 241 | free(path); | 241 | free(path); |
| 242 | path = NULL; | 242 | path = NULL; |
| 243 | } | 243 | } |
| @@ -269,9 +269,10 @@ const char *event_type(int type) | |||
| 269 | 269 | ||
| 270 | 270 | ||
| 271 | 271 | ||
| 272 | static int __add_event(struct list_head *list, int *idx, | 272 | static struct perf_evsel * |
| 273 | struct perf_event_attr *attr, | 273 | __add_event(struct list_head *list, int *idx, |
| 274 | char *name, struct cpu_map *cpus) | 274 | struct perf_event_attr *attr, |
| 275 | char *name, struct cpu_map *cpus) | ||
| 275 | { | 276 | { |
| 276 | struct perf_evsel *evsel; | 277 | struct perf_evsel *evsel; |
| 277 | 278 | ||
| @@ -279,19 +280,19 @@ static int __add_event(struct list_head *list, int *idx, | |||
| 279 | 280 | ||
| 280 | evsel = perf_evsel__new_idx(attr, (*idx)++); | 281 | evsel = perf_evsel__new_idx(attr, (*idx)++); |
| 281 | if (!evsel) | 282 | if (!evsel) |
| 282 | return -ENOMEM; | 283 | return NULL; |
| 283 | 284 | ||
| 284 | evsel->cpus = cpus; | 285 | evsel->cpus = cpus; |
| 285 | if (name) | 286 | if (name) |
| 286 | evsel->name = strdup(name); | 287 | evsel->name = strdup(name); |
| 287 | list_add_tail(&evsel->node, list); | 288 | list_add_tail(&evsel->node, list); |
| 288 | return 0; | 289 | return evsel; |
| 289 | } | 290 | } |
| 290 | 291 | ||
| 291 | static int add_event(struct list_head *list, int *idx, | 292 | static int add_event(struct list_head *list, int *idx, |
| 292 | struct perf_event_attr *attr, char *name) | 293 | struct perf_event_attr *attr, char *name) |
| 293 | { | 294 | { |
| 294 | return __add_event(list, idx, attr, name, NULL); | 295 | return __add_event(list, idx, attr, name, NULL) ? 0 : -ENOMEM; |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 297 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) | 298 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) |
| @@ -633,6 +634,9 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
| 633 | { | 634 | { |
| 634 | struct perf_event_attr attr; | 635 | struct perf_event_attr attr; |
| 635 | struct perf_pmu *pmu; | 636 | struct perf_pmu *pmu; |
| 637 | struct perf_evsel *evsel; | ||
| 638 | char *unit; | ||
| 639 | double scale; | ||
| 636 | 640 | ||
| 637 | pmu = perf_pmu__find(name); | 641 | pmu = perf_pmu__find(name); |
| 638 | if (!pmu) | 642 | if (!pmu) |
| @@ -640,7 +644,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
| 640 | 644 | ||
| 641 | memset(&attr, 0, sizeof(attr)); | 645 | memset(&attr, 0, sizeof(attr)); |
| 642 | 646 | ||
| 643 | if (perf_pmu__check_alias(pmu, head_config)) | 647 | if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) |
| 644 | return -EINVAL; | 648 | return -EINVAL; |
| 645 | 649 | ||
| 646 | /* | 650 | /* |
| @@ -652,8 +656,14 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
| 652 | if (perf_pmu__config(pmu, &attr, head_config)) | 656 | if (perf_pmu__config(pmu, &attr, head_config)) |
| 653 | return -EINVAL; | 657 | return -EINVAL; |
| 654 | 658 | ||
| 655 | return __add_event(list, idx, &attr, pmu_event_name(head_config), | 659 | evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), |
| 656 | pmu->cpus); | 660 | pmu->cpus); |
| 661 | if (evsel) { | ||
| 662 | evsel->unit = unit; | ||
| 663 | evsel->scale = scale; | ||
| 664 | } | ||
| 665 | |||
| 666 | return evsel ? 0 : -ENOMEM; | ||
| 657 | } | 667 | } |
| 658 | 668 | ||
| 659 | int parse_events__modifier_group(struct list_head *list, | 669 | int parse_events__modifier_group(struct list_head *list, |
| @@ -810,8 +820,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) | |||
| 810 | if (!add && get_event_modifier(&mod, str, NULL)) | 820 | if (!add && get_event_modifier(&mod, str, NULL)) |
| 811 | return -EINVAL; | 821 | return -EINVAL; |
| 812 | 822 | ||
| 813 | list_for_each_entry(evsel, list, node) { | 823 | __evlist__for_each(list, evsel) { |
| 814 | |||
| 815 | if (add && get_event_modifier(&mod, str, evsel)) | 824 | if (add && get_event_modifier(&mod, str, evsel)) |
| 816 | return -EINVAL; | 825 | return -EINVAL; |
| 817 | 826 | ||
| @@ -835,7 +844,7 @@ int parse_events_name(struct list_head *list, char *name) | |||
| 835 | { | 844 | { |
| 836 | struct perf_evsel *evsel; | 845 | struct perf_evsel *evsel; |
| 837 | 846 | ||
| 838 | list_for_each_entry(evsel, list, node) { | 847 | __evlist__for_each(list, evsel) { |
| 839 | if (!evsel->name) | 848 | if (!evsel->name) |
| 840 | evsel->name = strdup(name); | 849 | evsel->name = strdup(name); |
| 841 | } | 850 | } |
| @@ -907,7 +916,7 @@ int parse_events_terms(struct list_head *terms, const char *str) | |||
| 907 | ret = parse_events__scanner(str, &data, PE_START_TERMS); | 916 | ret = parse_events__scanner(str, &data, PE_START_TERMS); |
| 908 | if (!ret) { | 917 | if (!ret) { |
| 909 | list_splice(data.terms, terms); | 918 | list_splice(data.terms, terms); |
| 910 | free(data.terms); | 919 | zfree(&data.terms); |
| 911 | return 0; | 920 | return 0; |
| 912 | } | 921 | } |
| 913 | 922 | ||
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 31f404a032a9..d22e3f8017dc 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
| @@ -78,6 +78,8 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
| 78 | 78 | ||
| 79 | case OPTION_BOOLEAN: | 79 | case OPTION_BOOLEAN: |
| 80 | *(bool *)opt->value = unset ? false : true; | 80 | *(bool *)opt->value = unset ? false : true; |
| 81 | if (opt->set) | ||
| 82 | *(bool *)opt->set = true; | ||
| 81 | return 0; | 83 | return 0; |
| 82 | 84 | ||
| 83 | case OPTION_INCR: | 85 | case OPTION_INCR: |
| @@ -224,6 +226,24 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, | |||
| 224 | return 0; | 226 | return 0; |
| 225 | } | 227 | } |
| 226 | if (!rest) { | 228 | if (!rest) { |
| 229 | if (!prefixcmp(options->long_name, "no-")) { | ||
| 230 | /* | ||
| 231 | * The long name itself starts with "no-", so | ||
| 232 | * accept the option without "no-" so that users | ||
| 233 | * do not have to enter "no-no-" to get the | ||
| 234 | * negation. | ||
| 235 | */ | ||
| 236 | rest = skip_prefix(arg, options->long_name + 3); | ||
| 237 | if (rest) { | ||
| 238 | flags |= OPT_UNSET; | ||
| 239 | goto match; | ||
| 240 | } | ||
| 241 | /* Abbreviated case */ | ||
| 242 | if (!prefixcmp(options->long_name + 3, arg)) { | ||
| 243 | flags |= OPT_UNSET; | ||
| 244 | goto is_abbreviated; | ||
| 245 | } | ||
| 246 | } | ||
| 227 | /* abbreviated? */ | 247 | /* abbreviated? */ |
| 228 | if (!strncmp(options->long_name, arg, arg_end - arg)) { | 248 | if (!strncmp(options->long_name, arg, arg_end - arg)) { |
| 229 | is_abbreviated: | 249 | is_abbreviated: |
| @@ -259,6 +279,7 @@ is_abbreviated: | |||
| 259 | if (!rest) | 279 | if (!rest) |
| 260 | continue; | 280 | continue; |
| 261 | } | 281 | } |
| 282 | match: | ||
| 262 | if (*rest) { | 283 | if (*rest) { |
| 263 | if (*rest != '=') | 284 | if (*rest != '=') |
| 264 | continue; | 285 | continue; |
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b0241e28eaf7..cbf0149cf221 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
| @@ -82,6 +82,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset); | |||
| 82 | * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in | 82 | * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in |
| 83 | * the value when met. | 83 | * the value when met. |
| 84 | * CALLBACKS can use it like they want. | 84 | * CALLBACKS can use it like they want. |
| 85 | * | ||
| 86 | * `set`:: | ||
| 87 | * whether an option was set by the user | ||
| 85 | */ | 88 | */ |
| 86 | struct option { | 89 | struct option { |
| 87 | enum parse_opt_type type; | 90 | enum parse_opt_type type; |
| @@ -94,6 +97,7 @@ struct option { | |||
| 94 | int flags; | 97 | int flags; |
| 95 | parse_opt_cb *callback; | 98 | parse_opt_cb *callback; |
| 96 | intptr_t defval; | 99 | intptr_t defval; |
| 100 | bool *set; | ||
| 97 | }; | 101 | }; |
| 98 | 102 | ||
| 99 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) | 103 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) |
| @@ -103,6 +107,10 @@ struct option { | |||
| 103 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } | 107 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } |
| 104 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } | 108 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } |
| 105 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } | 109 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } |
| 110 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ | ||
| 111 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ | ||
| 112 | .value = check_vtype(v, bool *), .help = (h), \ | ||
| 113 | .set = check_vtype(os, bool *)} | ||
| 106 | #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } | 114 | #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } |
| 107 | #define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } | 115 | #define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } |
| 108 | #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } | 116 | #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index c232d8dd410b..d9cab4d27192 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
| @@ -1,19 +1,23 @@ | |||
| 1 | #include <linux/list.h> | 1 | #include <linux/list.h> |
| 2 | #include <sys/types.h> | 2 | #include <sys/types.h> |
| 3 | #include <sys/stat.h> | ||
| 4 | #include <unistd.h> | 3 | #include <unistd.h> |
| 5 | #include <stdio.h> | 4 | #include <stdio.h> |
| 6 | #include <dirent.h> | 5 | #include <dirent.h> |
| 7 | #include "fs.h" | 6 | #include "fs.h" |
| 7 | #include <locale.h> | ||
| 8 | #include "util.h" | 8 | #include "util.h" |
| 9 | #include "pmu.h" | 9 | #include "pmu.h" |
| 10 | #include "parse-events.h" | 10 | #include "parse-events.h" |
| 11 | #include "cpumap.h" | 11 | #include "cpumap.h" |
| 12 | 12 | ||
| 13 | #define UNIT_MAX_LEN 31 /* max length for event unit name */ | ||
| 14 | |||
| 13 | struct perf_pmu_alias { | 15 | struct perf_pmu_alias { |
| 14 | char *name; | 16 | char *name; |
| 15 | struct list_head terms; | 17 | struct list_head terms; |
| 16 | struct list_head list; | 18 | struct list_head list; |
| 19 | char unit[UNIT_MAX_LEN+1]; | ||
| 20 | double scale; | ||
| 17 | }; | 21 | }; |
| 18 | 22 | ||
| 19 | struct perf_pmu_format { | 23 | struct perf_pmu_format { |
| @@ -94,7 +98,80 @@ static int pmu_format(const char *name, struct list_head *format) | |||
| 94 | return 0; | 98 | return 0; |
| 95 | } | 99 | } |
| 96 | 100 | ||
| 97 | static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) | 101 | static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name) |
| 102 | { | ||
| 103 | struct stat st; | ||
| 104 | ssize_t sret; | ||
| 105 | char scale[128]; | ||
| 106 | int fd, ret = -1; | ||
| 107 | char path[PATH_MAX]; | ||
| 108 | char *lc; | ||
| 109 | |||
| 110 | snprintf(path, PATH_MAX, "%s/%s.scale", dir, name); | ||
| 111 | |||
| 112 | fd = open(path, O_RDONLY); | ||
| 113 | if (fd == -1) | ||
| 114 | return -1; | ||
| 115 | |||
| 116 | if (fstat(fd, &st) < 0) | ||
| 117 | goto error; | ||
| 118 | |||
| 119 | sret = read(fd, scale, sizeof(scale)-1); | ||
| 120 | if (sret < 0) | ||
| 121 | goto error; | ||
| 122 | |||
| 123 | scale[sret] = '\0'; | ||
| 124 | /* | ||
| 125 | * save current locale | ||
| 126 | */ | ||
| 127 | lc = setlocale(LC_NUMERIC, NULL); | ||
| 128 | |||
| 129 | /* | ||
| 130 | * force to C locale to ensure kernel | ||
| 131 | * scale string is converted correctly. | ||
| 132 | * kernel uses default C locale. | ||
| 133 | */ | ||
| 134 | setlocale(LC_NUMERIC, "C"); | ||
| 135 | |||
| 136 | alias->scale = strtod(scale, NULL); | ||
| 137 | |||
| 138 | /* restore locale */ | ||
| 139 | setlocale(LC_NUMERIC, lc); | ||
| 140 | |||
| 141 | ret = 0; | ||
| 142 | error: | ||
| 143 | close(fd); | ||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name) | ||
| 148 | { | ||
| 149 | char path[PATH_MAX]; | ||
| 150 | ssize_t sret; | ||
| 151 | int fd; | ||
| 152 | |||
| 153 | snprintf(path, PATH_MAX, "%s/%s.unit", dir, name); | ||
| 154 | |||
| 155 | fd = open(path, O_RDONLY); | ||
| 156 | if (fd == -1) | ||
| 157 | return -1; | ||
| 158 | |||
| 159 | sret = read(fd, alias->unit, UNIT_MAX_LEN); | ||
| 160 | if (sret < 0) | ||
| 161 | goto error; | ||
| 162 | |||
| 163 | close(fd); | ||
| 164 | |||
| 165 | alias->unit[sret] = '\0'; | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | error: | ||
| 169 | close(fd); | ||
| 170 | alias->unit[0] = '\0'; | ||
| 171 | return -1; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) | ||
| 98 | { | 175 | { |
| 99 | struct perf_pmu_alias *alias; | 176 | struct perf_pmu_alias *alias; |
| 100 | char buf[256]; | 177 | char buf[256]; |
| @@ -110,6 +187,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) | |||
| 110 | return -ENOMEM; | 187 | return -ENOMEM; |
| 111 | 188 | ||
| 112 | INIT_LIST_HEAD(&alias->terms); | 189 | INIT_LIST_HEAD(&alias->terms); |
| 190 | alias->scale = 1.0; | ||
| 191 | alias->unit[0] = '\0'; | ||
| 192 | |||
| 113 | ret = parse_events_terms(&alias->terms, buf); | 193 | ret = parse_events_terms(&alias->terms, buf); |
| 114 | if (ret) { | 194 | if (ret) { |
| 115 | free(alias); | 195 | free(alias); |
| @@ -117,7 +197,14 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) | |||
| 117 | } | 197 | } |
| 118 | 198 | ||
| 119 | alias->name = strdup(name); | 199 | alias->name = strdup(name); |
| 200 | /* | ||
| 201 | * load unit name and scale if available | ||
| 202 | */ | ||
| 203 | perf_pmu__parse_unit(alias, dir, name); | ||
| 204 | perf_pmu__parse_scale(alias, dir, name); | ||
| 205 | |||
| 120 | list_add_tail(&alias->list, list); | 206 | list_add_tail(&alias->list, list); |
| 207 | |||
| 121 | return 0; | 208 | return 0; |
| 122 | } | 209 | } |
| 123 | 210 | ||
| @@ -129,6 +216,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head) | |||
| 129 | { | 216 | { |
| 130 | struct dirent *evt_ent; | 217 | struct dirent *evt_ent; |
| 131 | DIR *event_dir; | 218 | DIR *event_dir; |
| 219 | size_t len; | ||
| 132 | int ret = 0; | 220 | int ret = 0; |
| 133 | 221 | ||
| 134 | event_dir = opendir(dir); | 222 | event_dir = opendir(dir); |
| @@ -143,13 +231,24 @@ static int pmu_aliases_parse(char *dir, struct list_head *head) | |||
| 143 | if (!strcmp(name, ".") || !strcmp(name, "..")) | 231 | if (!strcmp(name, ".") || !strcmp(name, "..")) |
| 144 | continue; | 232 | continue; |
| 145 | 233 | ||
| 234 | /* | ||
| 235 | * skip .unit and .scale info files | ||
| 236 | * parsed in perf_pmu__new_alias() | ||
| 237 | */ | ||
| 238 | len = strlen(name); | ||
| 239 | if (len > 5 && !strcmp(name + len - 5, ".unit")) | ||
| 240 | continue; | ||
| 241 | if (len > 6 && !strcmp(name + len - 6, ".scale")) | ||
| 242 | continue; | ||
| 243 | |||
| 146 | snprintf(path, PATH_MAX, "%s/%s", dir, name); | 244 | snprintf(path, PATH_MAX, "%s/%s", dir, name); |
| 147 | 245 | ||
| 148 | ret = -EINVAL; | 246 | ret = -EINVAL; |
| 149 | file = fopen(path, "r"); | 247 | file = fopen(path, "r"); |
| 150 | if (!file) | 248 | if (!file) |
| 151 | break; | 249 | break; |
| 152 | ret = perf_pmu__new_alias(head, name, file); | 250 | |
| 251 | ret = perf_pmu__new_alias(head, dir, name, file); | ||
| 153 | fclose(file); | 252 | fclose(file); |
| 154 | } | 253 | } |
| 155 | 254 | ||
| @@ -406,7 +505,7 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value) | |||
| 406 | 505 | ||
| 407 | /* | 506 | /* |
| 408 | * Setup one of config[12] attr members based on the | 507 | * Setup one of config[12] attr members based on the |
| 409 | * user input data - temr parameter. | 508 | * user input data - term parameter. |
| 410 | */ | 509 | */ |
| 411 | static int pmu_config_term(struct list_head *formats, | 510 | static int pmu_config_term(struct list_head *formats, |
| 412 | struct perf_event_attr *attr, | 511 | struct perf_event_attr *attr, |
| @@ -508,16 +607,42 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, | |||
| 508 | return NULL; | 607 | return NULL; |
| 509 | } | 608 | } |
| 510 | 609 | ||
| 610 | |||
| 611 | static int check_unit_scale(struct perf_pmu_alias *alias, | ||
| 612 | char **unit, double *scale) | ||
| 613 | { | ||
| 614 | /* | ||
| 615 | * Only one term in event definition can | ||
| 616 | * define unit and scale, fail if there's | ||
| 617 | * more than one. | ||
| 618 | */ | ||
| 619 | if ((*unit && alias->unit) || | ||
| 620 | (*scale && alias->scale)) | ||
| 621 | return -EINVAL; | ||
| 622 | |||
| 623 | if (alias->unit) | ||
| 624 | *unit = alias->unit; | ||
| 625 | |||
| 626 | if (alias->scale) | ||
| 627 | *scale = alias->scale; | ||
| 628 | |||
| 629 | return 0; | ||
| 630 | } | ||
| 631 | |||
| 511 | /* | 632 | /* |
| 512 | * Find alias in the terms list and replace it with the terms | 633 | * Find alias in the terms list and replace it with the terms |
| 513 | * defined for the alias | 634 | * defined for the alias |
| 514 | */ | 635 | */ |
| 515 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) | 636 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
| 637 | char **unit, double *scale) | ||
| 516 | { | 638 | { |
| 517 | struct parse_events_term *term, *h; | 639 | struct parse_events_term *term, *h; |
| 518 | struct perf_pmu_alias *alias; | 640 | struct perf_pmu_alias *alias; |
| 519 | int ret; | 641 | int ret; |
| 520 | 642 | ||
| 643 | *unit = NULL; | ||
| 644 | *scale = 0; | ||
| 645 | |||
| 521 | list_for_each_entry_safe(term, h, head_terms, list) { | 646 | list_for_each_entry_safe(term, h, head_terms, list) { |
| 522 | alias = pmu_find_alias(pmu, term); | 647 | alias = pmu_find_alias(pmu, term); |
| 523 | if (!alias) | 648 | if (!alias) |
| @@ -525,6 +650,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) | |||
| 525 | ret = pmu_alias_terms(alias, &term->list); | 650 | ret = pmu_alias_terms(alias, &term->list); |
| 526 | if (ret) | 651 | if (ret) |
| 527 | return ret; | 652 | return ret; |
| 653 | |||
| 654 | ret = check_unit_scale(alias, unit, scale); | ||
| 655 | if (ret) | ||
| 656 | return ret; | ||
| 657 | |||
| 528 | list_del(&term->list); | 658 | list_del(&term->list); |
| 529 | free(term); | 659 | free(term); |
| 530 | } | 660 | } |
| @@ -625,7 +755,7 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
| 625 | continue; | 755 | continue; |
| 626 | } | 756 | } |
| 627 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); | 757 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); |
| 628 | free(aliases[j]); | 758 | zfree(&aliases[j]); |
| 629 | printed++; | 759 | printed++; |
| 630 | } | 760 | } |
| 631 | if (printed) | 761 | if (printed) |
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 1179b26f244a..9183380e2038 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h | |||
| @@ -28,7 +28,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, | |||
| 28 | int perf_pmu__config_terms(struct list_head *formats, | 28 | int perf_pmu__config_terms(struct list_head *formats, |
| 29 | struct perf_event_attr *attr, | 29 | struct perf_event_attr *attr, |
| 30 | struct list_head *head_terms); | 30 | struct list_head *head_terms); |
| 31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms); | 31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
| 32 | char **unit, double *scale); | ||
| 32 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, | 33 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, |
| 33 | struct list_head *head_terms); | 34 | struct list_head *head_terms); |
| 34 | int perf_pmu_wrap(void); | 35 | int perf_pmu_wrap(void); |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9c6989ca2bea..a8a9b6cd93a8 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | #include "color.h" | 40 | #include "color.h" |
| 41 | #include "symbol.h" | 41 | #include "symbol.h" |
| 42 | #include "thread.h" | 42 | #include "thread.h" |
| 43 | #include <lk/debugfs.h> | 43 | #include <api/fs/debugfs.h> |
| 44 | #include "trace-event.h" /* For __maybe_unused */ | 44 | #include "trace-event.h" /* For __maybe_unused */ |
| 45 | #include "probe-event.h" | 45 | #include "probe-event.h" |
| 46 | #include "probe-finder.h" | 46 | #include "probe-finder.h" |
| @@ -72,6 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) | |||
| 72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | 72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); |
| 73 | static int convert_name_to_addr(struct perf_probe_event *pev, | 73 | static int convert_name_to_addr(struct perf_probe_event *pev, |
| 74 | const char *exec); | 74 | const char *exec); |
| 75 | static void clear_probe_trace_event(struct probe_trace_event *tev); | ||
| 75 | static struct machine machine; | 76 | static struct machine machine; |
| 76 | 77 | ||
| 77 | /* Initialize symbol maps and path of vmlinux/modules */ | 78 | /* Initialize symbol maps and path of vmlinux/modules */ |
| @@ -154,7 +155,7 @@ static struct dso *kernel_get_module_dso(const char *module) | |||
| 154 | 155 | ||
| 155 | vmlinux_name = symbol_conf.vmlinux_name; | 156 | vmlinux_name = symbol_conf.vmlinux_name; |
| 156 | if (vmlinux_name) { | 157 | if (vmlinux_name) { |
| 157 | if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) | 158 | if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0) |
| 158 | return NULL; | 159 | return NULL; |
| 159 | } else { | 160 | } else { |
| 160 | if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { | 161 | if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { |
| @@ -186,6 +187,37 @@ static int init_user_exec(void) | |||
| 186 | return ret; | 187 | return ret; |
| 187 | } | 188 | } |
| 188 | 189 | ||
| 190 | static int convert_exec_to_group(const char *exec, char **result) | ||
| 191 | { | ||
| 192 | char *ptr1, *ptr2, *exec_copy; | ||
| 193 | char buf[64]; | ||
| 194 | int ret; | ||
| 195 | |||
| 196 | exec_copy = strdup(exec); | ||
| 197 | if (!exec_copy) | ||
| 198 | return -ENOMEM; | ||
| 199 | |||
| 200 | ptr1 = basename(exec_copy); | ||
| 201 | if (!ptr1) { | ||
| 202 | ret = -EINVAL; | ||
| 203 | goto out; | ||
| 204 | } | ||
| 205 | |||
| 206 | ptr2 = strpbrk(ptr1, "-._"); | ||
| 207 | if (ptr2) | ||
| 208 | *ptr2 = '\0'; | ||
| 209 | ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); | ||
| 210 | if (ret < 0) | ||
| 211 | goto out; | ||
| 212 | |||
| 213 | *result = strdup(buf); | ||
| 214 | ret = *result ? 0 : -ENOMEM; | ||
| 215 | |||
| 216 | out: | ||
| 217 | free(exec_copy); | ||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 189 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, | 221 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, |
| 190 | struct perf_probe_point *pp) | 222 | struct perf_probe_point *pp) |
| 191 | { | 223 | { |
| @@ -261,6 +293,68 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
| 261 | return 0; | 293 | return 0; |
| 262 | } | 294 | } |
| 263 | 295 | ||
| 296 | static int get_text_start_address(const char *exec, unsigned long *address) | ||
| 297 | { | ||
| 298 | Elf *elf; | ||
| 299 | GElf_Ehdr ehdr; | ||
| 300 | GElf_Shdr shdr; | ||
| 301 | int fd, ret = -ENOENT; | ||
| 302 | |||
| 303 | fd = open(exec, O_RDONLY); | ||
| 304 | if (fd < 0) | ||
| 305 | return -errno; | ||
| 306 | |||
| 307 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
| 308 | if (elf == NULL) | ||
| 309 | return -EINVAL; | ||
| 310 | |||
| 311 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
| 312 | goto out; | ||
| 313 | |||
| 314 | if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL)) | ||
| 315 | goto out; | ||
| 316 | |||
| 317 | *address = shdr.sh_addr - shdr.sh_offset; | ||
| 318 | ret = 0; | ||
| 319 | out: | ||
| 320 | elf_end(elf); | ||
| 321 | return ret; | ||
| 322 | } | ||
| 323 | |||
| 324 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | ||
| 325 | int ntevs, const char *exec) | ||
| 326 | { | ||
| 327 | int i, ret = 0; | ||
| 328 | unsigned long offset, stext = 0; | ||
| 329 | char buf[32]; | ||
| 330 | |||
| 331 | if (!exec) | ||
| 332 | return 0; | ||
| 333 | |||
| 334 | ret = get_text_start_address(exec, &stext); | ||
| 335 | if (ret < 0) | ||
| 336 | return ret; | ||
| 337 | |||
| 338 | for (i = 0; i < ntevs && ret >= 0; i++) { | ||
| 339 | offset = tevs[i].point.address - stext; | ||
| 340 | offset += tevs[i].point.offset; | ||
| 341 | tevs[i].point.offset = 0; | ||
| 342 | zfree(&tevs[i].point.symbol); | ||
| 343 | ret = e_snprintf(buf, 32, "0x%lx", offset); | ||
| 344 | if (ret < 0) | ||
| 345 | break; | ||
| 346 | tevs[i].point.module = strdup(exec); | ||
| 347 | tevs[i].point.symbol = strdup(buf); | ||
| 348 | if (!tevs[i].point.symbol || !tevs[i].point.module) { | ||
| 349 | ret = -ENOMEM; | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | tevs[i].uprobes = true; | ||
| 353 | } | ||
| 354 | |||
| 355 | return ret; | ||
| 356 | } | ||
| 357 | |||
| 264 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | 358 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, |
| 265 | int ntevs, const char *module) | 359 | int ntevs, const char *module) |
| 266 | { | 360 | { |
| @@ -290,12 +384,18 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | |||
| 290 | } | 384 | } |
| 291 | } | 385 | } |
| 292 | 386 | ||
| 293 | if (tmp) | 387 | free(tmp); |
| 294 | free(tmp); | ||
| 295 | |||
| 296 | return ret; | 388 | return ret; |
| 297 | } | 389 | } |
| 298 | 390 | ||
| 391 | static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) | ||
| 392 | { | ||
| 393 | int i; | ||
| 394 | |||
| 395 | for (i = 0; i < ntevs; i++) | ||
| 396 | clear_probe_trace_event(tevs + i); | ||
| 397 | } | ||
| 398 | |||
| 299 | /* Try to find perf_probe_event with debuginfo */ | 399 | /* Try to find perf_probe_event with debuginfo */ |
| 300 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 400 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, |
| 301 | struct probe_trace_event **tevs, | 401 | struct probe_trace_event **tevs, |
| @@ -305,15 +405,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
| 305 | struct debuginfo *dinfo; | 405 | struct debuginfo *dinfo; |
| 306 | int ntevs, ret = 0; | 406 | int ntevs, ret = 0; |
| 307 | 407 | ||
| 308 | if (pev->uprobes) { | ||
| 309 | if (need_dwarf) { | ||
| 310 | pr_warning("Debuginfo-analysis is not yet supported" | ||
| 311 | " with -x/--exec option.\n"); | ||
| 312 | return -ENOSYS; | ||
| 313 | } | ||
| 314 | return convert_name_to_addr(pev, target); | ||
| 315 | } | ||
| 316 | |||
| 317 | dinfo = open_debuginfo(target); | 408 | dinfo = open_debuginfo(target); |
| 318 | 409 | ||
| 319 | if (!dinfo) { | 410 | if (!dinfo) { |
| @@ -332,9 +423,18 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
| 332 | 423 | ||
| 333 | if (ntevs > 0) { /* Succeeded to find trace events */ | 424 | if (ntevs > 0) { /* Succeeded to find trace events */ |
| 334 | pr_debug("find %d probe_trace_events.\n", ntevs); | 425 | pr_debug("find %d probe_trace_events.\n", ntevs); |
| 335 | if (target) | 426 | if (target) { |
| 336 | ret = add_module_to_probe_trace_events(*tevs, ntevs, | 427 | if (pev->uprobes) |
| 337 | target); | 428 | ret = add_exec_to_probe_trace_events(*tevs, |
| 429 | ntevs, target); | ||
| 430 | else | ||
| 431 | ret = add_module_to_probe_trace_events(*tevs, | ||
| 432 | ntevs, target); | ||
| 433 | } | ||
| 434 | if (ret < 0) { | ||
| 435 | clear_probe_trace_events(*tevs, ntevs); | ||
| 436 | zfree(tevs); | ||
| 437 | } | ||
| 338 | return ret < 0 ? ret : ntevs; | 438 | return ret < 0 ? ret : ntevs; |
| 339 | } | 439 | } |
| 340 | 440 | ||
| @@ -401,15 +501,13 @@ static int get_real_path(const char *raw_path, const char *comp_dir, | |||
| 401 | case EFAULT: | 501 | case EFAULT: |
| 402 | raw_path = strchr(++raw_path, '/'); | 502 | raw_path = strchr(++raw_path, '/'); |
| 403 | if (!raw_path) { | 503 | if (!raw_path) { |
| 404 | free(*new_path); | 504 | zfree(new_path); |
| 405 | *new_path = NULL; | ||
| 406 | return -ENOENT; | 505 | return -ENOENT; |
| 407 | } | 506 | } |
| 408 | continue; | 507 | continue; |
| 409 | 508 | ||
| 410 | default: | 509 | default: |
| 411 | free(*new_path); | 510 | zfree(new_path); |
| 412 | *new_path = NULL; | ||
| 413 | return -errno; | 511 | return -errno; |
| 414 | } | 512 | } |
| 415 | } | 513 | } |
| @@ -580,7 +678,7 @@ static int show_available_vars_at(struct debuginfo *dinfo, | |||
| 580 | */ | 678 | */ |
| 581 | fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, | 679 | fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, |
| 582 | vl->point.offset); | 680 | vl->point.offset); |
| 583 | free(vl->point.symbol); | 681 | zfree(&vl->point.symbol); |
| 584 | nvars = 0; | 682 | nvars = 0; |
| 585 | if (vl->vars) { | 683 | if (vl->vars) { |
| 586 | strlist__for_each(node, vl->vars) { | 684 | strlist__for_each(node, vl->vars) { |
| @@ -647,16 +745,14 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
| 647 | 745 | ||
| 648 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 746 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, |
| 649 | struct probe_trace_event **tevs __maybe_unused, | 747 | struct probe_trace_event **tevs __maybe_unused, |
| 650 | int max_tevs __maybe_unused, const char *target) | 748 | int max_tevs __maybe_unused, |
| 749 | const char *target __maybe_unused) | ||
| 651 | { | 750 | { |
| 652 | if (perf_probe_event_need_dwarf(pev)) { | 751 | if (perf_probe_event_need_dwarf(pev)) { |
| 653 | pr_warning("Debuginfo-analysis is not supported.\n"); | 752 | pr_warning("Debuginfo-analysis is not supported.\n"); |
| 654 | return -ENOSYS; | 753 | return -ENOSYS; |
| 655 | } | 754 | } |
| 656 | 755 | ||
| 657 | if (pev->uprobes) | ||
| 658 | return convert_name_to_addr(pev, target); | ||
| 659 | |||
| 660 | return 0; | 756 | return 0; |
| 661 | } | 757 | } |
| 662 | 758 | ||
| @@ -678,6 +774,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused, | |||
| 678 | } | 774 | } |
| 679 | #endif | 775 | #endif |
| 680 | 776 | ||
| 777 | void line_range__clear(struct line_range *lr) | ||
| 778 | { | ||
| 779 | struct line_node *ln; | ||
| 780 | |||
| 781 | free(lr->function); | ||
| 782 | free(lr->file); | ||
| 783 | free(lr->path); | ||
| 784 | free(lr->comp_dir); | ||
| 785 | while (!list_empty(&lr->line_list)) { | ||
| 786 | ln = list_first_entry(&lr->line_list, struct line_node, list); | ||
| 787 | list_del(&ln->list); | ||
| 788 | free(ln); | ||
| 789 | } | ||
| 790 | memset(lr, 0, sizeof(*lr)); | ||
| 791 | } | ||
| 792 | |||
| 793 | void line_range__init(struct line_range *lr) | ||
| 794 | { | ||
| 795 | memset(lr, 0, sizeof(*lr)); | ||
| 796 | INIT_LIST_HEAD(&lr->line_list); | ||
| 797 | } | ||
| 798 | |||
| 681 | static int parse_line_num(char **ptr, int *val, const char *what) | 799 | static int parse_line_num(char **ptr, int *val, const char *what) |
| 682 | { | 800 | { |
| 683 | const char *start = *ptr; | 801 | const char *start = *ptr; |
| @@ -1278,8 +1396,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) | |||
| 1278 | error: | 1396 | error: |
| 1279 | pr_debug("Failed to synthesize perf probe point: %s\n", | 1397 | pr_debug("Failed to synthesize perf probe point: %s\n", |
| 1280 | strerror(-ret)); | 1398 | strerror(-ret)); |
| 1281 | if (buf) | 1399 | free(buf); |
| 1282 | free(buf); | ||
| 1283 | return NULL; | 1400 | return NULL; |
| 1284 | } | 1401 | } |
| 1285 | 1402 | ||
| @@ -1480,34 +1597,25 @@ void clear_perf_probe_event(struct perf_probe_event *pev) | |||
| 1480 | struct perf_probe_arg_field *field, *next; | 1597 | struct perf_probe_arg_field *field, *next; |
| 1481 | int i; | 1598 | int i; |
| 1482 | 1599 | ||
| 1483 | if (pev->event) | 1600 | free(pev->event); |
| 1484 | free(pev->event); | 1601 | free(pev->group); |
| 1485 | if (pev->group) | 1602 | free(pp->file); |
| 1486 | free(pev->group); | 1603 | free(pp->function); |
| 1487 | if (pp->file) | 1604 | free(pp->lazy_line); |
| 1488 | free(pp->file); | 1605 | |
| 1489 | if (pp->function) | ||
| 1490 | free(pp->function); | ||
| 1491 | if (pp->lazy_line) | ||
| 1492 | free(pp->lazy_line); | ||
| 1493 | for (i = 0; i < pev->nargs; i++) { | 1606 | for (i = 0; i < pev->nargs; i++) { |
| 1494 | if (pev->args[i].name) | 1607 | free(pev->args[i].name); |
| 1495 | free(pev->args[i].name); | 1608 | free(pev->args[i].var); |
| 1496 | if (pev->args[i].var) | 1609 | free(pev->args[i].type); |
| 1497 | free(pev->args[i].var); | ||
| 1498 | if (pev->args[i].type) | ||
| 1499 | free(pev->args[i].type); | ||
| 1500 | field = pev->args[i].field; | 1610 | field = pev->args[i].field; |
| 1501 | while (field) { | 1611 | while (field) { |
| 1502 | next = field->next; | 1612 | next = field->next; |
| 1503 | if (field->name) | 1613 | zfree(&field->name); |
| 1504 | free(field->name); | ||
| 1505 | free(field); | 1614 | free(field); |
| 1506 | field = next; | 1615 | field = next; |
| 1507 | } | 1616 | } |
| 1508 | } | 1617 | } |
| 1509 | if (pev->args) | 1618 | free(pev->args); |
| 1510 | free(pev->args); | ||
| 1511 | memset(pev, 0, sizeof(*pev)); | 1619 | memset(pev, 0, sizeof(*pev)); |
| 1512 | } | 1620 | } |
| 1513 | 1621 | ||
| @@ -1516,21 +1624,14 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) | |||
| 1516 | struct probe_trace_arg_ref *ref, *next; | 1624 | struct probe_trace_arg_ref *ref, *next; |
| 1517 | int i; | 1625 | int i; |
| 1518 | 1626 | ||
| 1519 | if (tev->event) | 1627 | free(tev->event); |
| 1520 | free(tev->event); | 1628 | free(tev->group); |
| 1521 | if (tev->group) | 1629 | free(tev->point.symbol); |
| 1522 | free(tev->group); | 1630 | free(tev->point.module); |
| 1523 | if (tev->point.symbol) | ||
| 1524 | free(tev->point.symbol); | ||
| 1525 | if (tev->point.module) | ||
| 1526 | free(tev->point.module); | ||
| 1527 | for (i = 0; i < tev->nargs; i++) { | 1631 | for (i = 0; i < tev->nargs; i++) { |
| 1528 | if (tev->args[i].name) | 1632 | free(tev->args[i].name); |
| 1529 | free(tev->args[i].name); | 1633 | free(tev->args[i].value); |
| 1530 | if (tev->args[i].value) | 1634 | free(tev->args[i].type); |
| 1531 | free(tev->args[i].value); | ||
| 1532 | if (tev->args[i].type) | ||
| 1533 | free(tev->args[i].type); | ||
| 1534 | ref = tev->args[i].ref; | 1635 | ref = tev->args[i].ref; |
| 1535 | while (ref) { | 1636 | while (ref) { |
| 1536 | next = ref->next; | 1637 | next = ref->next; |
| @@ -1538,8 +1639,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) | |||
| 1538 | ref = next; | 1639 | ref = next; |
| 1539 | } | 1640 | } |
| 1540 | } | 1641 | } |
| 1541 | if (tev->args) | 1642 | free(tev->args); |
| 1542 | free(tev->args); | ||
| 1543 | memset(tev, 0, sizeof(*tev)); | 1643 | memset(tev, 0, sizeof(*tev)); |
| 1544 | } | 1644 | } |
| 1545 | 1645 | ||
| @@ -1913,14 +2013,29 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
| 1913 | int max_tevs, const char *target) | 2013 | int max_tevs, const char *target) |
| 1914 | { | 2014 | { |
| 1915 | struct symbol *sym; | 2015 | struct symbol *sym; |
| 1916 | int ret = 0, i; | 2016 | int ret, i; |
| 1917 | struct probe_trace_event *tev; | 2017 | struct probe_trace_event *tev; |
| 1918 | 2018 | ||
| 2019 | if (pev->uprobes && !pev->group) { | ||
| 2020 | /* Replace group name if not given */ | ||
| 2021 | ret = convert_exec_to_group(target, &pev->group); | ||
| 2022 | if (ret != 0) { | ||
| 2023 | pr_warning("Failed to make a group name.\n"); | ||
| 2024 | return ret; | ||
| 2025 | } | ||
| 2026 | } | ||
| 2027 | |||
| 1919 | /* Convert perf_probe_event with debuginfo */ | 2028 | /* Convert perf_probe_event with debuginfo */ |
| 1920 | ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); | 2029 | ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); |
| 1921 | if (ret != 0) | 2030 | if (ret != 0) |
| 1922 | return ret; /* Found in debuginfo or got an error */ | 2031 | return ret; /* Found in debuginfo or got an error */ |
| 1923 | 2032 | ||
| 2033 | if (pev->uprobes) { | ||
| 2034 | ret = convert_name_to_addr(pev, target); | ||
| 2035 | if (ret < 0) | ||
| 2036 | return ret; | ||
| 2037 | } | ||
| 2038 | |||
| 1924 | /* Allocate trace event buffer */ | 2039 | /* Allocate trace event buffer */ |
| 1925 | tev = *tevs = zalloc(sizeof(struct probe_trace_event)); | 2040 | tev = *tevs = zalloc(sizeof(struct probe_trace_event)); |
| 1926 | if (tev == NULL) | 2041 | if (tev == NULL) |
| @@ -2056,7 +2171,7 @@ end: | |||
| 2056 | for (i = 0; i < npevs; i++) { | 2171 | for (i = 0; i < npevs; i++) { |
| 2057 | for (j = 0; j < pkgs[i].ntevs; j++) | 2172 | for (j = 0; j < pkgs[i].ntevs; j++) |
| 2058 | clear_probe_trace_event(&pkgs[i].tevs[j]); | 2173 | clear_probe_trace_event(&pkgs[i].tevs[j]); |
| 2059 | free(pkgs[i].tevs); | 2174 | zfree(&pkgs[i].tevs); |
| 2060 | } | 2175 | } |
| 2061 | free(pkgs); | 2176 | free(pkgs); |
| 2062 | 2177 | ||
| @@ -2281,7 +2396,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
| 2281 | struct perf_probe_point *pp = &pev->point; | 2396 | struct perf_probe_point *pp = &pev->point; |
| 2282 | struct symbol *sym; | 2397 | struct symbol *sym; |
| 2283 | struct map *map = NULL; | 2398 | struct map *map = NULL; |
| 2284 | char *function = NULL, *name = NULL; | 2399 | char *function = NULL; |
| 2285 | int ret = -EINVAL; | 2400 | int ret = -EINVAL; |
| 2286 | unsigned long long vaddr = 0; | 2401 | unsigned long long vaddr = 0; |
| 2287 | 2402 | ||
| @@ -2297,12 +2412,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
| 2297 | goto out; | 2412 | goto out; |
| 2298 | } | 2413 | } |
| 2299 | 2414 | ||
| 2300 | name = realpath(exec, NULL); | 2415 | map = dso__new_map(exec); |
| 2301 | if (!name) { | ||
| 2302 | pr_warning("Cannot find realpath for %s.\n", exec); | ||
| 2303 | goto out; | ||
| 2304 | } | ||
| 2305 | map = dso__new_map(name); | ||
| 2306 | if (!map) { | 2416 | if (!map) { |
| 2307 | pr_warning("Cannot find appropriate DSO for %s.\n", exec); | 2417 | pr_warning("Cannot find appropriate DSO for %s.\n", exec); |
| 2308 | goto out; | 2418 | goto out; |
| @@ -2367,7 +2477,5 @@ out: | |||
| 2367 | } | 2477 | } |
| 2368 | if (function) | 2478 | if (function) |
| 2369 | free(function); | 2479 | free(function); |
| 2370 | if (name) | ||
| 2371 | free(name); | ||
| 2372 | return ret; | 2480 | return ret; |
| 2373 | } | 2481 | } |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index f9f3de8b4220..fcaf7273e85a 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
| @@ -12,6 +12,7 @@ struct probe_trace_point { | |||
| 12 | char *symbol; /* Base symbol */ | 12 | char *symbol; /* Base symbol */ |
| 13 | char *module; /* Module name */ | 13 | char *module; /* Module name */ |
| 14 | unsigned long offset; /* Offset from symbol */ | 14 | unsigned long offset; /* Offset from symbol */ |
| 15 | unsigned long address; /* Actual address of the trace point */ | ||
| 15 | bool retprobe; /* Return probe flag */ | 16 | bool retprobe; /* Return probe flag */ |
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| @@ -119,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev); | |||
| 119 | /* Command string to line-range */ | 120 | /* Command string to line-range */ |
| 120 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); | 121 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); |
| 121 | 122 | ||
| 123 | /* Release line range members */ | ||
| 124 | extern void line_range__clear(struct line_range *lr); | ||
| 125 | |||
| 126 | /* Initialize line range */ | ||
| 127 | extern void line_range__init(struct line_range *lr); | ||
| 128 | |||
| 122 | /* Internal use: Return kernel/module path */ | 129 | /* Internal use: Return kernel/module path */ |
| 123 | extern const char *kernel_get_module_path(const char *module); | 130 | extern const char *kernel_get_module_path(const char *module); |
| 124 | 131 | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ffb657ffd327..061edb162b5b 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -226,10 +226,8 @@ struct debuginfo *debuginfo__new(const char *path) | |||
| 226 | if (!dbg) | 226 | if (!dbg) |
| 227 | return NULL; | 227 | return NULL; |
| 228 | 228 | ||
| 229 | if (debuginfo__init_offline_dwarf(dbg, path) < 0) { | 229 | if (debuginfo__init_offline_dwarf(dbg, path) < 0) |
| 230 | free(dbg); | 230 | zfree(&dbg); |
| 231 | dbg = NULL; | ||
| 232 | } | ||
| 233 | 231 | ||
| 234 | return dbg; | 232 | return dbg; |
| 235 | } | 233 | } |
| @@ -241,10 +239,8 @@ struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) | |||
| 241 | if (!dbg) | 239 | if (!dbg) |
| 242 | return NULL; | 240 | return NULL; |
| 243 | 241 | ||
| 244 | if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) { | 242 | if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) |
| 245 | free(dbg); | 243 | zfree(&dbg); |
| 246 | dbg = NULL; | ||
| 247 | } | ||
| 248 | 244 | ||
| 249 | return dbg; | 245 | return dbg; |
| 250 | } | 246 | } |
| @@ -729,6 +725,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | |||
| 729 | return -ENOENT; | 725 | return -ENOENT; |
| 730 | } | 726 | } |
| 731 | tp->offset = (unsigned long)(paddr - sym.st_value); | 727 | tp->offset = (unsigned long)(paddr - sym.st_value); |
| 728 | tp->address = (unsigned long)paddr; | ||
| 732 | tp->symbol = strdup(symbol); | 729 | tp->symbol = strdup(symbol); |
| 733 | if (!tp->symbol) | 730 | if (!tp->symbol) |
| 734 | return -ENOMEM; | 731 | return -ENOMEM; |
| @@ -1301,8 +1298,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, | |||
| 1301 | 1298 | ||
| 1302 | ret = debuginfo__find_probes(dbg, &tf.pf); | 1299 | ret = debuginfo__find_probes(dbg, &tf.pf); |
| 1303 | if (ret < 0) { | 1300 | if (ret < 0) { |
| 1304 | free(*tevs); | 1301 | zfree(tevs); |
| 1305 | *tevs = NULL; | ||
| 1306 | return ret; | 1302 | return ret; |
| 1307 | } | 1303 | } |
| 1308 | 1304 | ||
| @@ -1413,13 +1409,10 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, | |||
| 1413 | if (ret < 0) { | 1409 | if (ret < 0) { |
| 1414 | /* Free vlist for error */ | 1410 | /* Free vlist for error */ |
| 1415 | while (af.nvls--) { | 1411 | while (af.nvls--) { |
| 1416 | if (af.vls[af.nvls].point.symbol) | 1412 | zfree(&af.vls[af.nvls].point.symbol); |
| 1417 | free(af.vls[af.nvls].point.symbol); | 1413 | strlist__delete(af.vls[af.nvls].vars); |
| 1418 | if (af.vls[af.nvls].vars) | ||
| 1419 | strlist__delete(af.vls[af.nvls].vars); | ||
| 1420 | } | 1414 | } |
| 1421 | free(af.vls); | 1415 | zfree(vls); |
| 1422 | *vls = NULL; | ||
| 1423 | return ret; | 1416 | return ret; |
| 1424 | } | 1417 | } |
| 1425 | 1418 | ||
| @@ -1523,10 +1516,7 @@ post: | |||
| 1523 | if (fname) { | 1516 | if (fname) { |
| 1524 | ppt->file = strdup(fname); | 1517 | ppt->file = strdup(fname); |
| 1525 | if (ppt->file == NULL) { | 1518 | if (ppt->file == NULL) { |
| 1526 | if (ppt->function) { | 1519 | zfree(&ppt->function); |
| 1527 | free(ppt->function); | ||
| 1528 | ppt->function = NULL; | ||
| 1529 | } | ||
| 1530 | ret = -ENOMEM; | 1520 | ret = -ENOMEM; |
| 1531 | goto end; | 1521 | goto end; |
| 1532 | } | 1522 | } |
| @@ -1580,8 +1570,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) | |||
| 1580 | else | 1570 | else |
| 1581 | ret = 0; /* Lines are not found */ | 1571 | ret = 0; /* Lines are not found */ |
| 1582 | else { | 1572 | else { |
| 1583 | free(lf->lr->path); | 1573 | zfree(&lf->lr->path); |
| 1584 | lf->lr->path = NULL; | ||
| 1585 | } | 1574 | } |
| 1586 | return ret; | 1575 | return ret; |
| 1587 | } | 1576 | } |
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 239036fb2b2c..595bfc73d2ed 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
| @@ -18,4 +18,5 @@ util/cgroup.c | |||
| 18 | util/rblist.c | 18 | util/rblist.c |
| 19 | util/strlist.c | 19 | util/strlist.c |
| 20 | util/fs.c | 20 | util/fs.c |
| 21 | util/trace-event.c | ||
| 21 | ../../lib/rbtree.c | 22 | ../../lib/rbtree.c |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 4bf8ace7f511..122669c18ff4 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
| @@ -908,9 +908,10 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) | |||
| 908 | if (i >= pevlist->evlist.nr_entries) | 908 | if (i >= pevlist->evlist.nr_entries) |
| 909 | return NULL; | 909 | return NULL; |
| 910 | 910 | ||
| 911 | list_for_each_entry(pos, &pevlist->evlist.entries, node) | 911 | evlist__for_each(&pevlist->evlist, pos) { |
| 912 | if (i-- == 0) | 912 | if (i-- == 0) |
| 913 | break; | 913 | break; |
| 914 | } | ||
| 914 | 915 | ||
| 915 | return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); | 916 | return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); |
| 916 | } | 917 | } |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index c8845b107f60..373762501dad 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
| @@ -74,8 +74,7 @@ bool perf_can_sample_identifier(void) | |||
| 74 | return perf_probe_api(perf_probe_sample_identifier); | 74 | return perf_probe_api(perf_probe_sample_identifier); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | void perf_evlist__config(struct perf_evlist *evlist, | 77 | void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) |
| 78 | struct perf_record_opts *opts) | ||
| 79 | { | 78 | { |
| 80 | struct perf_evsel *evsel; | 79 | struct perf_evsel *evsel; |
| 81 | bool use_sample_identifier = false; | 80 | bool use_sample_identifier = false; |
| @@ -90,19 +89,19 @@ void perf_evlist__config(struct perf_evlist *evlist, | |||
| 90 | if (evlist->cpus->map[0] < 0) | 89 | if (evlist->cpus->map[0] < 0) |
| 91 | opts->no_inherit = true; | 90 | opts->no_inherit = true; |
| 92 | 91 | ||
| 93 | list_for_each_entry(evsel, &evlist->entries, node) | 92 | evlist__for_each(evlist, evsel) |
| 94 | perf_evsel__config(evsel, opts); | 93 | perf_evsel__config(evsel, opts); |
| 95 | 94 | ||
| 96 | if (evlist->nr_entries > 1) { | 95 | if (evlist->nr_entries > 1) { |
| 97 | struct perf_evsel *first = perf_evlist__first(evlist); | 96 | struct perf_evsel *first = perf_evlist__first(evlist); |
| 98 | 97 | ||
| 99 | list_for_each_entry(evsel, &evlist->entries, node) { | 98 | evlist__for_each(evlist, evsel) { |
| 100 | if (evsel->attr.sample_type == first->attr.sample_type) | 99 | if (evsel->attr.sample_type == first->attr.sample_type) |
| 101 | continue; | 100 | continue; |
| 102 | use_sample_identifier = perf_can_sample_identifier(); | 101 | use_sample_identifier = perf_can_sample_identifier(); |
| 103 | break; | 102 | break; |
| 104 | } | 103 | } |
| 105 | list_for_each_entry(evsel, &evlist->entries, node) | 104 | evlist__for_each(evlist, evsel) |
| 106 | perf_evsel__set_sample_id(evsel, use_sample_identifier); | 105 | perf_evsel__set_sample_id(evsel, use_sample_identifier); |
| 107 | } | 106 | } |
| 108 | 107 | ||
| @@ -123,7 +122,7 @@ static int get_max_rate(unsigned int *rate) | |||
| 123 | return filename__read_int(path, (int *) rate); | 122 | return filename__read_int(path, (int *) rate); |
| 124 | } | 123 | } |
| 125 | 124 | ||
| 126 | static int perf_record_opts__config_freq(struct perf_record_opts *opts) | 125 | static int record_opts__config_freq(struct record_opts *opts) |
| 127 | { | 126 | { |
| 128 | bool user_freq = opts->user_freq != UINT_MAX; | 127 | bool user_freq = opts->user_freq != UINT_MAX; |
| 129 | unsigned int max_rate; | 128 | unsigned int max_rate; |
| @@ -173,7 +172,44 @@ static int perf_record_opts__config_freq(struct perf_record_opts *opts) | |||
| 173 | return 0; | 172 | return 0; |
| 174 | } | 173 | } |
| 175 | 174 | ||
| 176 | int perf_record_opts__config(struct perf_record_opts *opts) | 175 | int record_opts__config(struct record_opts *opts) |
| 177 | { | 176 | { |
| 178 | return perf_record_opts__config_freq(opts); | 177 | return record_opts__config_freq(opts); |
| 178 | } | ||
| 179 | |||
| 180 | bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) | ||
| 181 | { | ||
| 182 | struct perf_evlist *temp_evlist; | ||
| 183 | struct perf_evsel *evsel; | ||
| 184 | int err, fd, cpu; | ||
| 185 | bool ret = false; | ||
| 186 | |||
| 187 | temp_evlist = perf_evlist__new(); | ||
| 188 | if (!temp_evlist) | ||
| 189 | return false; | ||
| 190 | |||
| 191 | err = parse_events(temp_evlist, str); | ||
| 192 | if (err) | ||
| 193 | goto out_delete; | ||
| 194 | |||
| 195 | evsel = perf_evlist__last(temp_evlist); | ||
| 196 | |||
| 197 | if (!evlist || cpu_map__empty(evlist->cpus)) { | ||
| 198 | struct cpu_map *cpus = cpu_map__new(NULL); | ||
| 199 | |||
| 200 | cpu = cpus ? cpus->map[0] : 0; | ||
| 201 | cpu_map__delete(cpus); | ||
| 202 | } else { | ||
| 203 | cpu = evlist->cpus->map[0]; | ||
| 204 | } | ||
| 205 | |||
| 206 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); | ||
| 207 | if (fd >= 0) { | ||
| 208 | close(fd); | ||
| 209 | ret = true; | ||
| 210 | } | ||
| 211 | |||
| 212 | out_delete: | ||
| 213 | perf_evlist__delete(temp_evlist); | ||
| 214 | return ret; | ||
| 179 | } | 215 | } |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index d5e5969f6fea..e108207c5de0 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
| @@ -194,8 +194,7 @@ static void define_event_symbols(struct event_format *event, | |||
| 194 | zero_flag_atom = 0; | 194 | zero_flag_atom = 0; |
| 195 | break; | 195 | break; |
| 196 | case PRINT_FIELD: | 196 | case PRINT_FIELD: |
| 197 | if (cur_field_name) | 197 | free(cur_field_name); |
| 198 | free(cur_field_name); | ||
| 199 | cur_field_name = strdup(args->field.name); | 198 | cur_field_name = strdup(args->field.name); |
| 200 | break; | 199 | break; |
| 201 | case PRINT_FLAGS: | 200 | case PRINT_FLAGS: |
| @@ -257,12 +256,9 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
| 257 | return event; | 256 | return event; |
| 258 | } | 257 | } |
| 259 | 258 | ||
| 260 | static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, | 259 | static void perl_process_tracepoint(struct perf_sample *sample, |
| 261 | struct perf_sample *sample, | ||
| 262 | struct perf_evsel *evsel, | 260 | struct perf_evsel *evsel, |
| 263 | struct machine *machine __maybe_unused, | 261 | struct thread *thread) |
| 264 | struct thread *thread, | ||
| 265 | struct addr_location *al) | ||
| 266 | { | 262 | { |
| 267 | struct format_field *field; | 263 | struct format_field *field; |
| 268 | static char handler[256]; | 264 | static char handler[256]; |
| @@ -349,10 +345,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, | |||
| 349 | 345 | ||
| 350 | static void perl_process_event_generic(union perf_event *event, | 346 | static void perl_process_event_generic(union perf_event *event, |
| 351 | struct perf_sample *sample, | 347 | struct perf_sample *sample, |
| 352 | struct perf_evsel *evsel, | 348 | struct perf_evsel *evsel) |
| 353 | struct machine *machine __maybe_unused, | ||
| 354 | struct thread *thread __maybe_unused, | ||
| 355 | struct addr_location *al __maybe_unused) | ||
| 356 | { | 349 | { |
| 357 | dSP; | 350 | dSP; |
| 358 | 351 | ||
| @@ -377,12 +370,11 @@ static void perl_process_event_generic(union perf_event *event, | |||
| 377 | static void perl_process_event(union perf_event *event, | 370 | static void perl_process_event(union perf_event *event, |
| 378 | struct perf_sample *sample, | 371 | struct perf_sample *sample, |
| 379 | struct perf_evsel *evsel, | 372 | struct perf_evsel *evsel, |
| 380 | struct machine *machine, | ||
| 381 | struct thread *thread, | 373 | struct thread *thread, |
| 382 | struct addr_location *al) | 374 | struct addr_location *al __maybe_unused) |
| 383 | { | 375 | { |
| 384 | perl_process_tracepoint(event, sample, evsel, machine, thread, al); | 376 | perl_process_tracepoint(sample, evsel, thread); |
| 385 | perl_process_event_generic(event, sample, evsel, machine, thread, al); | 377 | perl_process_event_generic(event, sample, evsel); |
| 386 | } | 378 | } |
| 387 | 379 | ||
| 388 | static void run_start_sub(void) | 380 | static void run_start_sub(void) |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 53c20e7fd900..cd9774df3750 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
| @@ -161,8 +161,7 @@ static void define_event_symbols(struct event_format *event, | |||
| 161 | zero_flag_atom = 0; | 161 | zero_flag_atom = 0; |
| 162 | break; | 162 | break; |
| 163 | case PRINT_FIELD: | 163 | case PRINT_FIELD: |
| 164 | if (cur_field_name) | 164 | free(cur_field_name); |
| 165 | free(cur_field_name); | ||
| 166 | cur_field_name = strdup(args->field.name); | 165 | cur_field_name = strdup(args->field.name); |
| 167 | break; | 166 | break; |
| 168 | case PRINT_FLAGS: | 167 | case PRINT_FLAGS: |
| @@ -231,13 +230,10 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
| 231 | return event; | 230 | return event; |
| 232 | } | 231 | } |
| 233 | 232 | ||
| 234 | static void python_process_tracepoint(union perf_event *perf_event | 233 | static void python_process_tracepoint(struct perf_sample *sample, |
| 235 | __maybe_unused, | 234 | struct perf_evsel *evsel, |
| 236 | struct perf_sample *sample, | 235 | struct thread *thread, |
| 237 | struct perf_evsel *evsel, | 236 | struct addr_location *al) |
| 238 | struct machine *machine __maybe_unused, | ||
| 239 | struct thread *thread, | ||
| 240 | struct addr_location *al) | ||
| 241 | { | 237 | { |
| 242 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 238 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; |
| 243 | static char handler_name[256]; | 239 | static char handler_name[256]; |
| @@ -351,11 +347,8 @@ static void python_process_tracepoint(union perf_event *perf_event | |||
| 351 | Py_DECREF(t); | 347 | Py_DECREF(t); |
| 352 | } | 348 | } |
| 353 | 349 | ||
| 354 | static void python_process_general_event(union perf_event *perf_event | 350 | static void python_process_general_event(struct perf_sample *sample, |
| 355 | __maybe_unused, | ||
| 356 | struct perf_sample *sample, | ||
| 357 | struct perf_evsel *evsel, | 351 | struct perf_evsel *evsel, |
| 358 | struct machine *machine __maybe_unused, | ||
| 359 | struct thread *thread, | 352 | struct thread *thread, |
| 360 | struct addr_location *al) | 353 | struct addr_location *al) |
| 361 | { | 354 | { |
| @@ -411,22 +404,19 @@ exit: | |||
| 411 | Py_DECREF(t); | 404 | Py_DECREF(t); |
| 412 | } | 405 | } |
| 413 | 406 | ||
| 414 | static void python_process_event(union perf_event *perf_event, | 407 | static void python_process_event(union perf_event *event __maybe_unused, |
| 415 | struct perf_sample *sample, | 408 | struct perf_sample *sample, |
| 416 | struct perf_evsel *evsel, | 409 | struct perf_evsel *evsel, |
| 417 | struct machine *machine, | ||
| 418 | struct thread *thread, | 410 | struct thread *thread, |
| 419 | struct addr_location *al) | 411 | struct addr_location *al) |
| 420 | { | 412 | { |
| 421 | switch (evsel->attr.type) { | 413 | switch (evsel->attr.type) { |
| 422 | case PERF_TYPE_TRACEPOINT: | 414 | case PERF_TYPE_TRACEPOINT: |
| 423 | python_process_tracepoint(perf_event, sample, evsel, | 415 | python_process_tracepoint(sample, evsel, thread, al); |
| 424 | machine, thread, al); | ||
| 425 | break; | 416 | break; |
| 426 | /* Reserve for future process_hw/sw/raw APIs */ | 417 | /* Reserve for future process_hw/sw/raw APIs */ |
| 427 | default: | 418 | default: |
| 428 | python_process_general_event(perf_event, sample, evsel, | 419 | python_process_general_event(sample, evsel, thread, al); |
| 429 | machine, thread, al); | ||
| 430 | } | 420 | } |
| 431 | } | 421 | } |
| 432 | 422 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f36d24a02445..7acc03e8f3b2 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -132,18 +132,18 @@ static void perf_session__delete_threads(struct perf_session *session) | |||
| 132 | 132 | ||
| 133 | static void perf_session_env__delete(struct perf_session_env *env) | 133 | static void perf_session_env__delete(struct perf_session_env *env) |
| 134 | { | 134 | { |
| 135 | free(env->hostname); | 135 | zfree(&env->hostname); |
| 136 | free(env->os_release); | 136 | zfree(&env->os_release); |
| 137 | free(env->version); | 137 | zfree(&env->version); |
| 138 | free(env->arch); | 138 | zfree(&env->arch); |
| 139 | free(env->cpu_desc); | 139 | zfree(&env->cpu_desc); |
| 140 | free(env->cpuid); | 140 | zfree(&env->cpuid); |
| 141 | 141 | ||
| 142 | free(env->cmdline); | 142 | zfree(&env->cmdline); |
| 143 | free(env->sibling_cores); | 143 | zfree(&env->sibling_cores); |
| 144 | free(env->sibling_threads); | 144 | zfree(&env->sibling_threads); |
| 145 | free(env->numa_nodes); | 145 | zfree(&env->numa_nodes); |
| 146 | free(env->pmu_mappings); | 146 | zfree(&env->pmu_mappings); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | void perf_session__delete(struct perf_session *session) | 149 | void perf_session__delete(struct perf_session *session) |
| @@ -247,27 +247,6 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
| 247 | } | 247 | } |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | void mem_bswap_32(void *src, int byte_size) | ||
| 251 | { | ||
| 252 | u32 *m = src; | ||
| 253 | while (byte_size > 0) { | ||
| 254 | *m = bswap_32(*m); | ||
| 255 | byte_size -= sizeof(u32); | ||
| 256 | ++m; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | void mem_bswap_64(void *src, int byte_size) | ||
| 261 | { | ||
| 262 | u64 *m = src; | ||
| 263 | |||
| 264 | while (byte_size > 0) { | ||
| 265 | *m = bswap_64(*m); | ||
| 266 | byte_size -= sizeof(u64); | ||
| 267 | ++m; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | static void swap_sample_id_all(union perf_event *event, void *data) | 250 | static void swap_sample_id_all(union perf_event *event, void *data) |
| 272 | { | 251 | { |
| 273 | void *end = (void *) event + event->header.size; | 252 | void *end = (void *) event + event->header.size; |
| @@ -851,6 +830,7 @@ static struct machine * | |||
| 851 | struct perf_sample *sample) | 830 | struct perf_sample *sample) |
| 852 | { | 831 | { |
| 853 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 832 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
| 833 | struct machine *machine; | ||
| 854 | 834 | ||
| 855 | if (perf_guest && | 835 | if (perf_guest && |
| 856 | ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || | 836 | ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || |
| @@ -863,7 +843,11 @@ static struct machine * | |||
| 863 | else | 843 | else |
| 864 | pid = sample->pid; | 844 | pid = sample->pid; |
| 865 | 845 | ||
| 866 | return perf_session__findnew_machine(session, pid); | 846 | machine = perf_session__find_machine(session, pid); |
| 847 | if (!machine) | ||
| 848 | machine = perf_session__findnew_machine(session, | ||
| 849 | DEFAULT_GUEST_KERNEL_ID); | ||
| 850 | return machine; | ||
| 867 | } | 851 | } |
| 868 | 852 | ||
| 869 | return &session->machines.host; | 853 | return &session->machines.host; |
| @@ -1158,7 +1142,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session, | |||
| 1158 | void *buf = NULL; | 1142 | void *buf = NULL; |
| 1159 | int skip = 0; | 1143 | int skip = 0; |
| 1160 | u64 head; | 1144 | u64 head; |
| 1161 | int err; | 1145 | ssize_t err; |
| 1162 | void *p; | 1146 | void *p; |
| 1163 | 1147 | ||
| 1164 | perf_tool__fill_defaults(tool); | 1148 | perf_tool__fill_defaults(tool); |
| @@ -1400,7 +1384,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg) | |||
| 1400 | { | 1384 | { |
| 1401 | struct perf_evsel *evsel; | 1385 | struct perf_evsel *evsel; |
| 1402 | 1386 | ||
| 1403 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 1387 | evlist__for_each(session->evlist, evsel) { |
| 1404 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT) | 1388 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT) |
| 1405 | return true; | 1389 | return true; |
| 1406 | } | 1390 | } |
| @@ -1458,7 +1442,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) | |||
| 1458 | 1442 | ||
| 1459 | ret += events_stats__fprintf(&session->stats, fp); | 1443 | ret += events_stats__fprintf(&session->stats, fp); |
| 1460 | 1444 | ||
| 1461 | list_for_each_entry(pos, &session->evlist->entries, node) { | 1445 | evlist__for_each(session->evlist, pos) { |
| 1462 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); | 1446 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); |
| 1463 | ret += events_stats__fprintf(&pos->hists.stats, fp); | 1447 | ret += events_stats__fprintf(&pos->hists.stats, fp); |
| 1464 | } | 1448 | } |
| @@ -1480,35 +1464,30 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | |||
| 1480 | { | 1464 | { |
| 1481 | struct perf_evsel *pos; | 1465 | struct perf_evsel *pos; |
| 1482 | 1466 | ||
| 1483 | list_for_each_entry(pos, &session->evlist->entries, node) { | 1467 | evlist__for_each(session->evlist, pos) { |
| 1484 | if (pos->attr.type == type) | 1468 | if (pos->attr.type == type) |
| 1485 | return pos; | 1469 | return pos; |
| 1486 | } | 1470 | } |
| 1487 | return NULL; | 1471 | return NULL; |
| 1488 | } | 1472 | } |
| 1489 | 1473 | ||
| 1490 | void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | 1474 | void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, |
| 1491 | struct perf_sample *sample, struct machine *machine, | 1475 | struct addr_location *al, |
| 1492 | unsigned int print_opts, unsigned int stack_depth) | 1476 | unsigned int print_opts, unsigned int stack_depth) |
| 1493 | { | 1477 | { |
| 1494 | struct addr_location al; | ||
| 1495 | struct callchain_cursor_node *node; | 1478 | struct callchain_cursor_node *node; |
| 1496 | int print_ip = print_opts & PRINT_IP_OPT_IP; | 1479 | int print_ip = print_opts & PRINT_IP_OPT_IP; |
| 1497 | int print_sym = print_opts & PRINT_IP_OPT_SYM; | 1480 | int print_sym = print_opts & PRINT_IP_OPT_SYM; |
| 1498 | int print_dso = print_opts & PRINT_IP_OPT_DSO; | 1481 | int print_dso = print_opts & PRINT_IP_OPT_DSO; |
| 1499 | int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; | 1482 | int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; |
| 1500 | int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; | 1483 | int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; |
| 1484 | int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; | ||
| 1501 | char s = print_oneline ? ' ' : '\t'; | 1485 | char s = print_oneline ? ' ' : '\t'; |
| 1502 | 1486 | ||
| 1503 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | ||
| 1504 | error("problem processing %d event, skipping it.\n", | ||
| 1505 | event->header.type); | ||
| 1506 | return; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | if (symbol_conf.use_callchain && sample->callchain) { | 1487 | if (symbol_conf.use_callchain && sample->callchain) { |
| 1488 | struct addr_location node_al; | ||
| 1510 | 1489 | ||
| 1511 | if (machine__resolve_callchain(machine, evsel, al.thread, | 1490 | if (machine__resolve_callchain(al->machine, evsel, al->thread, |
| 1512 | sample, NULL, NULL, | 1491 | sample, NULL, NULL, |
| 1513 | PERF_MAX_STACK_DEPTH) != 0) { | 1492 | PERF_MAX_STACK_DEPTH) != 0) { |
| 1514 | if (verbose) | 1493 | if (verbose) |
| @@ -1517,20 +1496,31 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | |||
| 1517 | } | 1496 | } |
| 1518 | callchain_cursor_commit(&callchain_cursor); | 1497 | callchain_cursor_commit(&callchain_cursor); |
| 1519 | 1498 | ||
| 1499 | if (print_symoffset) | ||
| 1500 | node_al = *al; | ||
| 1501 | |||
| 1520 | while (stack_depth) { | 1502 | while (stack_depth) { |
| 1503 | u64 addr = 0; | ||
| 1504 | |||
| 1521 | node = callchain_cursor_current(&callchain_cursor); | 1505 | node = callchain_cursor_current(&callchain_cursor); |
| 1522 | if (!node) | 1506 | if (!node) |
| 1523 | break; | 1507 | break; |
| 1524 | 1508 | ||
| 1509 | if (node->sym && node->sym->ignore) | ||
| 1510 | goto next; | ||
| 1511 | |||
| 1525 | if (print_ip) | 1512 | if (print_ip) |
| 1526 | printf("%c%16" PRIx64, s, node->ip); | 1513 | printf("%c%16" PRIx64, s, node->ip); |
| 1527 | 1514 | ||
| 1515 | if (node->map) | ||
| 1516 | addr = node->map->map_ip(node->map, node->ip); | ||
| 1517 | |||
| 1528 | if (print_sym) { | 1518 | if (print_sym) { |
| 1529 | printf(" "); | 1519 | printf(" "); |
| 1530 | if (print_symoffset) { | 1520 | if (print_symoffset) { |
| 1531 | al.addr = node->ip; | 1521 | node_al.addr = addr; |
| 1532 | al.map = node->map; | 1522 | node_al.map = node->map; |
| 1533 | symbol__fprintf_symname_offs(node->sym, &al, stdout); | 1523 | symbol__fprintf_symname_offs(node->sym, &node_al, stdout); |
| 1534 | } else | 1524 | } else |
| 1535 | symbol__fprintf_symname(node->sym, stdout); | 1525 | symbol__fprintf_symname(node->sym, stdout); |
| 1536 | } | 1526 | } |
| @@ -1541,32 +1531,42 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | |||
| 1541 | printf(")"); | 1531 | printf(")"); |
| 1542 | } | 1532 | } |
| 1543 | 1533 | ||
| 1534 | if (print_srcline) | ||
| 1535 | map__fprintf_srcline(node->map, addr, "\n ", | ||
| 1536 | stdout); | ||
| 1537 | |||
| 1544 | if (!print_oneline) | 1538 | if (!print_oneline) |
| 1545 | printf("\n"); | 1539 | printf("\n"); |
| 1546 | 1540 | ||
| 1547 | callchain_cursor_advance(&callchain_cursor); | ||
| 1548 | |||
| 1549 | stack_depth--; | 1541 | stack_depth--; |
| 1542 | next: | ||
| 1543 | callchain_cursor_advance(&callchain_cursor); | ||
| 1550 | } | 1544 | } |
| 1551 | 1545 | ||
| 1552 | } else { | 1546 | } else { |
| 1547 | if (al->sym && al->sym->ignore) | ||
| 1548 | return; | ||
| 1549 | |||
| 1553 | if (print_ip) | 1550 | if (print_ip) |
| 1554 | printf("%16" PRIx64, sample->ip); | 1551 | printf("%16" PRIx64, sample->ip); |
| 1555 | 1552 | ||
| 1556 | if (print_sym) { | 1553 | if (print_sym) { |
| 1557 | printf(" "); | 1554 | printf(" "); |
| 1558 | if (print_symoffset) | 1555 | if (print_symoffset) |
| 1559 | symbol__fprintf_symname_offs(al.sym, &al, | 1556 | symbol__fprintf_symname_offs(al->sym, al, |
| 1560 | stdout); | 1557 | stdout); |
| 1561 | else | 1558 | else |
| 1562 | symbol__fprintf_symname(al.sym, stdout); | 1559 | symbol__fprintf_symname(al->sym, stdout); |
| 1563 | } | 1560 | } |
| 1564 | 1561 | ||
| 1565 | if (print_dso) { | 1562 | if (print_dso) { |
| 1566 | printf(" ("); | 1563 | printf(" ("); |
| 1567 | map__fprintf_dsoname(al.map, stdout); | 1564 | map__fprintf_dsoname(al->map, stdout); |
| 1568 | printf(")"); | 1565 | printf(")"); |
| 1569 | } | 1566 | } |
| 1567 | |||
| 1568 | if (print_srcline) | ||
| 1569 | map__fprintf_srcline(al->map, al->addr, "\n ", stdout); | ||
| 1570 | } | 1570 | } |
| 1571 | } | 1571 | } |
| 1572 | 1572 | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 50f640958f0f..3140f8ae6148 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef __PERF_SESSION_H | 1 | #ifndef __PERF_SESSION_H |
| 2 | #define __PERF_SESSION_H | 2 | #define __PERF_SESSION_H |
| 3 | 3 | ||
| 4 | #include "trace-event.h" | ||
| 4 | #include "hist.h" | 5 | #include "hist.h" |
| 5 | #include "event.h" | 6 | #include "event.h" |
| 6 | #include "header.h" | 7 | #include "header.h" |
| @@ -32,7 +33,7 @@ struct perf_session { | |||
| 32 | struct perf_header header; | 33 | struct perf_header header; |
| 33 | struct machines machines; | 34 | struct machines machines; |
| 34 | struct perf_evlist *evlist; | 35 | struct perf_evlist *evlist; |
| 35 | struct pevent *pevent; | 36 | struct trace_event tevent; |
| 36 | struct events_stats stats; | 37 | struct events_stats stats; |
| 37 | bool repipe; | 38 | bool repipe; |
| 38 | struct ordered_samples ordered_samples; | 39 | struct ordered_samples ordered_samples; |
| @@ -44,6 +45,7 @@ struct perf_session { | |||
| 44 | #define PRINT_IP_OPT_DSO (1<<2) | 45 | #define PRINT_IP_OPT_DSO (1<<2) |
| 45 | #define PRINT_IP_OPT_SYMOFFSET (1<<3) | 46 | #define PRINT_IP_OPT_SYMOFFSET (1<<3) |
| 46 | #define PRINT_IP_OPT_ONELINE (1<<4) | 47 | #define PRINT_IP_OPT_ONELINE (1<<4) |
| 48 | #define PRINT_IP_OPT_SRCLINE (1<<5) | ||
| 47 | 49 | ||
| 48 | struct perf_tool; | 50 | struct perf_tool; |
| 49 | 51 | ||
| @@ -72,8 +74,6 @@ int perf_session__resolve_callchain(struct perf_session *session, | |||
| 72 | 74 | ||
| 73 | bool perf_session__has_traces(struct perf_session *session, const char *msg); | 75 | bool perf_session__has_traces(struct perf_session *session, const char *msg); |
| 74 | 76 | ||
| 75 | void mem_bswap_64(void *src, int byte_size); | ||
| 76 | void mem_bswap_32(void *src, int byte_size); | ||
| 77 | void perf_event__attr_swap(struct perf_event_attr *attr); | 77 | void perf_event__attr_swap(struct perf_event_attr *attr); |
| 78 | 78 | ||
| 79 | int perf_session__create_kernel_maps(struct perf_session *session); | 79 | int perf_session__create_kernel_maps(struct perf_session *session); |
| @@ -105,8 +105,8 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); | |||
| 105 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | 105 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, |
| 106 | unsigned int type); | 106 | unsigned int type); |
| 107 | 107 | ||
| 108 | void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | 108 | void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, |
| 109 | struct perf_sample *sample, struct machine *machine, | 109 | struct addr_location *al, |
| 110 | unsigned int print_opts, unsigned int stack_depth); | 110 | unsigned int print_opts, unsigned int stack_depth); |
| 111 | 111 | ||
| 112 | int perf_session__cpu_bitmap(struct perf_session *session, | 112 | int perf_session__cpu_bitmap(struct perf_session *session, |
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 58ea5ca6c255..d0aee4b9dfd4 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py | |||
| @@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' | |||
| 25 | build_lib = getenv('PYTHON_EXTBUILD_LIB') | 25 | build_lib = getenv('PYTHON_EXTBUILD_LIB') |
| 26 | build_tmp = getenv('PYTHON_EXTBUILD_TMP') | 26 | build_tmp = getenv('PYTHON_EXTBUILD_TMP') |
| 27 | libtraceevent = getenv('LIBTRACEEVENT') | 27 | libtraceevent = getenv('LIBTRACEEVENT') |
| 28 | liblk = getenv('LIBLK') | 28 | libapikfs = getenv('LIBAPIKFS') |
| 29 | 29 | ||
| 30 | ext_sources = [f.strip() for f in file('util/python-ext-sources') | 30 | ext_sources = [f.strip() for f in file('util/python-ext-sources') |
| 31 | if len(f.strip()) > 0 and f[0] != '#'] | 31 | if len(f.strip()) > 0 and f[0] != '#'] |
| @@ -34,7 +34,7 @@ perf = Extension('perf', | |||
| 34 | sources = ext_sources, | 34 | sources = ext_sources, |
| 35 | include_dirs = ['util/include'], | 35 | include_dirs = ['util/include'], |
| 36 | extra_compile_args = cflags, | 36 | extra_compile_args = cflags, |
| 37 | extra_objects = [libtraceevent, liblk], | 37 | extra_objects = [libtraceevent, libapikfs], |
| 38 | ) | 38 | ) |
| 39 | 39 | ||
| 40 | setup(name='perf', | 40 | setup(name='perf', |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0bb1f4494a..635cd8f8b22e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
| @@ -13,6 +13,7 @@ int have_ignore_callees = 0; | |||
| 13 | int sort__need_collapse = 0; | 13 | int sort__need_collapse = 0; |
| 14 | int sort__has_parent = 0; | 14 | int sort__has_parent = 0; |
| 15 | int sort__has_sym = 0; | 15 | int sort__has_sym = 0; |
| 16 | int sort__has_dso = 0; | ||
| 16 | enum sort_mode sort__mode = SORT_MODE__NORMAL; | 17 | enum sort_mode sort__mode = SORT_MODE__NORMAL; |
| 17 | 18 | ||
| 18 | enum sort_type sort__first_dimension; | 19 | enum sort_type sort__first_dimension; |
| @@ -161,6 +162,11 @@ struct sort_entry sort_dso = { | |||
| 161 | 162 | ||
| 162 | /* --sort symbol */ | 163 | /* --sort symbol */ |
| 163 | 164 | ||
| 165 | static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip) | ||
| 166 | { | ||
| 167 | return (int64_t)(right_ip - left_ip); | ||
| 168 | } | ||
| 169 | |||
| 164 | static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) | 170 | static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) |
| 165 | { | 171 | { |
| 166 | u64 ip_l, ip_r; | 172 | u64 ip_l, ip_r; |
| @@ -183,15 +189,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 183 | int64_t ret; | 189 | int64_t ret; |
| 184 | 190 | ||
| 185 | if (!left->ms.sym && !right->ms.sym) | 191 | if (!left->ms.sym && !right->ms.sym) |
| 186 | return right->level - left->level; | 192 | return _sort__addr_cmp(left->ip, right->ip); |
| 187 | 193 | ||
| 188 | /* | 194 | /* |
| 189 | * comparing symbol address alone is not enough since it's a | 195 | * comparing symbol address alone is not enough since it's a |
| 190 | * relative address within a dso. | 196 | * relative address within a dso. |
| 191 | */ | 197 | */ |
| 192 | ret = sort__dso_cmp(left, right); | 198 | if (!sort__has_dso) { |
| 193 | if (ret != 0) | 199 | ret = sort__dso_cmp(left, right); |
| 194 | return ret; | 200 | if (ret != 0) |
| 201 | return ret; | ||
| 202 | } | ||
| 195 | 203 | ||
| 196 | return _sort__sym_cmp(left->ms.sym, right->ms.sym); | 204 | return _sort__sym_cmp(left->ms.sym, right->ms.sym); |
| 197 | } | 205 | } |
| @@ -372,7 +380,7 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 372 | struct addr_map_symbol *from_r = &right->branch_info->from; | 380 | struct addr_map_symbol *from_r = &right->branch_info->from; |
| 373 | 381 | ||
| 374 | if (!from_l->sym && !from_r->sym) | 382 | if (!from_l->sym && !from_r->sym) |
| 375 | return right->level - left->level; | 383 | return _sort__addr_cmp(from_l->addr, from_r->addr); |
| 376 | 384 | ||
| 377 | return _sort__sym_cmp(from_l->sym, from_r->sym); | 385 | return _sort__sym_cmp(from_l->sym, from_r->sym); |
| 378 | } | 386 | } |
| @@ -384,7 +392,7 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 384 | struct addr_map_symbol *to_r = &right->branch_info->to; | 392 | struct addr_map_symbol *to_r = &right->branch_info->to; |
| 385 | 393 | ||
| 386 | if (!to_l->sym && !to_r->sym) | 394 | if (!to_l->sym && !to_r->sym) |
| 387 | return right->level - left->level; | 395 | return _sort__addr_cmp(to_l->addr, to_r->addr); |
| 388 | 396 | ||
| 389 | return _sort__sym_cmp(to_l->sym, to_r->sym); | 397 | return _sort__sym_cmp(to_l->sym, to_r->sym); |
| 390 | } | 398 | } |
| @@ -1056,6 +1064,8 @@ int sort_dimension__add(const char *tok) | |||
| 1056 | sort__has_parent = 1; | 1064 | sort__has_parent = 1; |
| 1057 | } else if (sd->entry == &sort_sym) { | 1065 | } else if (sd->entry == &sort_sym) { |
| 1058 | sort__has_sym = 1; | 1066 | sort__has_sym = 1; |
| 1067 | } else if (sd->entry == &sort_dso) { | ||
| 1068 | sort__has_dso = 1; | ||
| 1059 | } | 1069 | } |
| 1060 | 1070 | ||
| 1061 | __sort_dimension__add(sd, i); | 1071 | __sort_dimension__add(sd, i); |
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index d11aefbc4b8d..f3e4bc5fe5d2 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
| @@ -129,7 +129,7 @@ static struct a2l_data *addr2line_init(const char *path) | |||
| 129 | 129 | ||
| 130 | out: | 130 | out: |
| 131 | if (a2l) { | 131 | if (a2l) { |
| 132 | free((void *)a2l->input); | 132 | zfree((char **)&a2l->input); |
| 133 | free(a2l); | 133 | free(a2l); |
| 134 | } | 134 | } |
| 135 | bfd_close(abfd); | 135 | bfd_close(abfd); |
| @@ -140,24 +140,30 @@ static void addr2line_cleanup(struct a2l_data *a2l) | |||
| 140 | { | 140 | { |
| 141 | if (a2l->abfd) | 141 | if (a2l->abfd) |
| 142 | bfd_close(a2l->abfd); | 142 | bfd_close(a2l->abfd); |
| 143 | free((void *)a2l->input); | 143 | zfree((char **)&a2l->input); |
| 144 | free(a2l->syms); | 144 | zfree(&a2l->syms); |
| 145 | free(a2l); | 145 | free(a2l); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static int addr2line(const char *dso_name, unsigned long addr, | 148 | static int addr2line(const char *dso_name, unsigned long addr, |
| 149 | char **file, unsigned int *line) | 149 | char **file, unsigned int *line, struct dso *dso) |
| 150 | { | 150 | { |
| 151 | int ret = 0; | 151 | int ret = 0; |
| 152 | struct a2l_data *a2l; | 152 | struct a2l_data *a2l = dso->a2l; |
| 153 | |||
| 154 | if (!a2l) { | ||
| 155 | dso->a2l = addr2line_init(dso_name); | ||
| 156 | a2l = dso->a2l; | ||
| 157 | } | ||
| 153 | 158 | ||
| 154 | a2l = addr2line_init(dso_name); | ||
| 155 | if (a2l == NULL) { | 159 | if (a2l == NULL) { |
| 156 | pr_warning("addr2line_init failed for %s\n", dso_name); | 160 | pr_warning("addr2line_init failed for %s\n", dso_name); |
| 157 | return 0; | 161 | return 0; |
| 158 | } | 162 | } |
| 159 | 163 | ||
| 160 | a2l->addr = addr; | 164 | a2l->addr = addr; |
| 165 | a2l->found = false; | ||
| 166 | |||
| 161 | bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); | 167 | bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); |
| 162 | 168 | ||
| 163 | if (a2l->found && a2l->filename) { | 169 | if (a2l->found && a2l->filename) { |
| @@ -168,14 +174,26 @@ static int addr2line(const char *dso_name, unsigned long addr, | |||
| 168 | ret = 1; | 174 | ret = 1; |
| 169 | } | 175 | } |
| 170 | 176 | ||
| 171 | addr2line_cleanup(a2l); | ||
| 172 | return ret; | 177 | return ret; |
| 173 | } | 178 | } |
| 174 | 179 | ||
| 180 | void dso__free_a2l(struct dso *dso) | ||
| 181 | { | ||
| 182 | struct a2l_data *a2l = dso->a2l; | ||
| 183 | |||
| 184 | if (!a2l) | ||
| 185 | return; | ||
| 186 | |||
| 187 | addr2line_cleanup(a2l); | ||
| 188 | |||
| 189 | dso->a2l = NULL; | ||
| 190 | } | ||
| 191 | |||
| 175 | #else /* HAVE_LIBBFD_SUPPORT */ | 192 | #else /* HAVE_LIBBFD_SUPPORT */ |
| 176 | 193 | ||
| 177 | static int addr2line(const char *dso_name, unsigned long addr, | 194 | static int addr2line(const char *dso_name, unsigned long addr, |
| 178 | char **file, unsigned int *line_nr) | 195 | char **file, unsigned int *line_nr, |
| 196 | struct dso *dso __maybe_unused) | ||
| 179 | { | 197 | { |
| 180 | FILE *fp; | 198 | FILE *fp; |
| 181 | char cmd[PATH_MAX]; | 199 | char cmd[PATH_MAX]; |
| @@ -219,42 +237,58 @@ out: | |||
| 219 | pclose(fp); | 237 | pclose(fp); |
| 220 | return ret; | 238 | return ret; |
| 221 | } | 239 | } |
| 240 | |||
| 241 | void dso__free_a2l(struct dso *dso __maybe_unused) | ||
| 242 | { | ||
| 243 | } | ||
| 244 | |||
| 222 | #endif /* HAVE_LIBBFD_SUPPORT */ | 245 | #endif /* HAVE_LIBBFD_SUPPORT */ |
| 223 | 246 | ||
| 247 | /* | ||
| 248 | * Number of addr2line failures (without success) before disabling it for that | ||
| 249 | * dso. | ||
| 250 | */ | ||
| 251 | #define A2L_FAIL_LIMIT 123 | ||
| 252 | |||
| 224 | char *get_srcline(struct dso *dso, unsigned long addr) | 253 | char *get_srcline(struct dso *dso, unsigned long addr) |
| 225 | { | 254 | { |
| 226 | char *file = NULL; | 255 | char *file = NULL; |
| 227 | unsigned line = 0; | 256 | unsigned line = 0; |
| 228 | char *srcline; | 257 | char *srcline; |
| 229 | char *dso_name = dso->long_name; | 258 | const char *dso_name; |
| 230 | size_t size; | ||
| 231 | 259 | ||
| 232 | if (!dso->has_srcline) | 260 | if (!dso->has_srcline) |
| 233 | return SRCLINE_UNKNOWN; | 261 | return SRCLINE_UNKNOWN; |
| 234 | 262 | ||
| 263 | if (dso->symsrc_filename) | ||
| 264 | dso_name = dso->symsrc_filename; | ||
| 265 | else | ||
| 266 | dso_name = dso->long_name; | ||
| 267 | |||
| 235 | if (dso_name[0] == '[') | 268 | if (dso_name[0] == '[') |
| 236 | goto out; | 269 | goto out; |
| 237 | 270 | ||
| 238 | if (!strncmp(dso_name, "/tmp/perf-", 10)) | 271 | if (!strncmp(dso_name, "/tmp/perf-", 10)) |
| 239 | goto out; | 272 | goto out; |
| 240 | 273 | ||
| 241 | if (!addr2line(dso_name, addr, &file, &line)) | 274 | if (!addr2line(dso_name, addr, &file, &line, dso)) |
| 242 | goto out; | 275 | goto out; |
| 243 | 276 | ||
| 244 | /* just calculate actual length */ | 277 | if (asprintf(&srcline, "%s:%u", file, line) < 0) { |
| 245 | size = snprintf(NULL, 0, "%s:%u", file, line) + 1; | 278 | free(file); |
| 279 | goto out; | ||
| 280 | } | ||
| 246 | 281 | ||
| 247 | srcline = malloc(size); | 282 | dso->a2l_fails = 0; |
| 248 | if (srcline) | ||
| 249 | snprintf(srcline, size, "%s:%u", file, line); | ||
| 250 | else | ||
| 251 | srcline = SRCLINE_UNKNOWN; | ||
| 252 | 283 | ||
| 253 | free(file); | 284 | free(file); |
| 254 | return srcline; | 285 | return srcline; |
| 255 | 286 | ||
| 256 | out: | 287 | out: |
| 257 | dso->has_srcline = 0; | 288 | if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) { |
| 289 | dso->has_srcline = 0; | ||
| 290 | dso__free_a2l(dso); | ||
| 291 | } | ||
| 258 | return SRCLINE_UNKNOWN; | 292 | return SRCLINE_UNKNOWN; |
| 259 | } | 293 | } |
| 260 | 294 | ||
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index cfa906882e2c..4abe23550c73 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
| @@ -28,7 +28,7 @@ void strbuf_init(struct strbuf *sb, ssize_t hint) | |||
| 28 | void strbuf_release(struct strbuf *sb) | 28 | void strbuf_release(struct strbuf *sb) |
| 29 | { | 29 | { |
| 30 | if (sb->alloc) { | 30 | if (sb->alloc) { |
| 31 | free(sb->buf); | 31 | zfree(&sb->buf); |
| 32 | strbuf_init(sb, 0); | 32 | strbuf_init(sb, 0); |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c index 3edd0538161f..79a757a2a15c 100644 --- a/tools/perf/util/strfilter.c +++ b/tools/perf/util/strfilter.c | |||
| @@ -14,7 +14,7 @@ static void strfilter_node__delete(struct strfilter_node *node) | |||
| 14 | { | 14 | { |
| 15 | if (node) { | 15 | if (node) { |
| 16 | if (node->p && !is_operator(*node->p)) | 16 | if (node->p && !is_operator(*node->p)) |
| 17 | free((char *)node->p); | 17 | zfree((char **)&node->p); |
| 18 | strfilter_node__delete(node->l); | 18 | strfilter_node__delete(node->l); |
| 19 | strfilter_node__delete(node->r); | 19 | strfilter_node__delete(node->r); |
| 20 | free(node); | 20 | free(node); |
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index f0b0c008c507..2553e5b55b89 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c | |||
| @@ -128,7 +128,7 @@ void argv_free(char **argv) | |||
| 128 | { | 128 | { |
| 129 | char **p; | 129 | char **p; |
| 130 | for (p = argv; *p; p++) | 130 | for (p = argv; *p; p++) |
| 131 | free(*p); | 131 | zfree(p); |
| 132 | 132 | ||
| 133 | free(argv); | 133 | free(argv); |
| 134 | } | 134 | } |
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index eabdce0a2daa..71f9d102b96f 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include "strlist.h" | 7 | #include "strlist.h" |
| 8 | #include "util.h" | ||
| 8 | #include <errno.h> | 9 | #include <errno.h> |
| 9 | #include <stdio.h> | 10 | #include <stdio.h> |
| 10 | #include <stdlib.h> | 11 | #include <stdlib.h> |
| @@ -38,7 +39,7 @@ out_delete: | |||
| 38 | static void str_node__delete(struct str_node *snode, bool dupstr) | 39 | static void str_node__delete(struct str_node *snode, bool dupstr) |
| 39 | { | 40 | { |
| 40 | if (dupstr) | 41 | if (dupstr) |
| 41 | free((void *)snode->s); | 42 | zfree((char **)&snode->s); |
| 42 | free(snode); | 43 | free(snode); |
| 43 | } | 44 | } |
| 44 | 45 | ||
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 96c866045d60..43262b83c541 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c | |||
| @@ -17,8 +17,12 @@ | |||
| 17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
| 18 | #include <unistd.h> | 18 | #include <unistd.h> |
| 19 | #include <string.h> | 19 | #include <string.h> |
| 20 | #include <linux/bitops.h> | ||
| 20 | 21 | ||
| 22 | #include "perf.h" | ||
| 21 | #include "svghelper.h" | 23 | #include "svghelper.h" |
| 24 | #include "util.h" | ||
| 25 | #include "cpumap.h" | ||
| 22 | 26 | ||
| 23 | static u64 first_time, last_time; | 27 | static u64 first_time, last_time; |
| 24 | static u64 turbo_frequency, max_freq; | 28 | static u64 turbo_frequency, max_freq; |
| @@ -28,6 +32,8 @@ static u64 turbo_frequency, max_freq; | |||
| 28 | #define SLOT_HEIGHT 25.0 | 32 | #define SLOT_HEIGHT 25.0 |
| 29 | 33 | ||
| 30 | int svg_page_width = 1000; | 34 | int svg_page_width = 1000; |
| 35 | u64 svg_highlight; | ||
| 36 | const char *svg_highlight_name; | ||
| 31 | 37 | ||
| 32 | #define MIN_TEXT_SIZE 0.01 | 38 | #define MIN_TEXT_SIZE 0.01 |
| 33 | 39 | ||
| @@ -39,9 +45,14 @@ static double cpu2slot(int cpu) | |||
| 39 | return 2 * cpu + 1; | 45 | return 2 * cpu + 1; |
| 40 | } | 46 | } |
| 41 | 47 | ||
| 48 | static int *topology_map; | ||
| 49 | |||
| 42 | static double cpu2y(int cpu) | 50 | static double cpu2y(int cpu) |
| 43 | { | 51 | { |
| 44 | return cpu2slot(cpu) * SLOT_MULT; | 52 | if (topology_map) |
| 53 | return cpu2slot(topology_map[cpu]) * SLOT_MULT; | ||
| 54 | else | ||
| 55 | return cpu2slot(cpu) * SLOT_MULT; | ||
| 45 | } | 56 | } |
| 46 | 57 | ||
| 47 | static double time2pixels(u64 __time) | 58 | static double time2pixels(u64 __time) |
| @@ -95,6 +106,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) | |||
| 95 | 106 | ||
| 96 | total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; | 107 | total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; |
| 97 | fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); | 108 | fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); |
| 109 | fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); | ||
| 98 | fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); | 110 | fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); |
| 99 | 111 | ||
| 100 | fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); | 112 | fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); |
| @@ -103,6 +115,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) | |||
| 103 | fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); | 115 | fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); |
| 104 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 116 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
| 105 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 117 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
| 118 | fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | ||
| 106 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 119 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
| 107 | fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 120 | fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
| 108 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 121 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
| @@ -128,14 +141,42 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type) | |||
| 128 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); | 141 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); |
| 129 | } | 142 | } |
| 130 | 143 | ||
| 131 | void svg_sample(int Yslot, int cpu, u64 start, u64 end) | 144 | static char *time_to_string(u64 duration); |
| 145 | void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) | ||
| 146 | { | ||
| 147 | if (!svgfile) | ||
| 148 | return; | ||
| 149 | |||
| 150 | fprintf(svgfile, "<g>\n"); | ||
| 151 | fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu, | ||
| 152 | time_to_string(end - start)); | ||
| 153 | if (backtrace) | ||
| 154 | fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace); | ||
| 155 | svg_box(Yslot, start, end, "blocked"); | ||
| 156 | fprintf(svgfile, "</g>\n"); | ||
| 157 | } | ||
| 158 | |||
| 159 | void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) | ||
| 132 | { | 160 | { |
| 133 | double text_size; | 161 | double text_size; |
| 162 | const char *type; | ||
| 163 | |||
| 134 | if (!svgfile) | 164 | if (!svgfile) |
| 135 | return; | 165 | return; |
| 136 | 166 | ||
| 137 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", | 167 | if (svg_highlight && end - start > svg_highlight) |
| 138 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); | 168 | type = "sample_hi"; |
| 169 | else | ||
| 170 | type = "sample"; | ||
| 171 | fprintf(svgfile, "<g>\n"); | ||
| 172 | |||
| 173 | fprintf(svgfile, "<title>#%d running %s</title>\n", | ||
| 174 | cpu, time_to_string(end - start)); | ||
| 175 | if (backtrace) | ||
| 176 | fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); | ||
| 177 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", | ||
| 178 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, | ||
| 179 | type); | ||
| 139 | 180 | ||
| 140 | text_size = (time2pixels(end)-time2pixels(start)); | 181 | text_size = (time2pixels(end)-time2pixels(start)); |
| 141 | if (cpu > 9) | 182 | if (cpu > 9) |
| @@ -148,6 +189,7 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end) | |||
| 148 | fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", | 189 | fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", |
| 149 | time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); | 190 | time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); |
| 150 | 191 | ||
| 192 | fprintf(svgfile, "</g>\n"); | ||
| 151 | } | 193 | } |
| 152 | 194 | ||
| 153 | static char *time_to_string(u64 duration) | 195 | static char *time_to_string(u64 duration) |
| @@ -168,7 +210,7 @@ static char *time_to_string(u64 duration) | |||
| 168 | return text; | 210 | return text; |
| 169 | } | 211 | } |
| 170 | 212 | ||
| 171 | void svg_waiting(int Yslot, u64 start, u64 end) | 213 | void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) |
| 172 | { | 214 | { |
| 173 | char *text; | 215 | char *text; |
| 174 | const char *style; | 216 | const char *style; |
| @@ -192,6 +234,9 @@ void svg_waiting(int Yslot, u64 start, u64 end) | |||
| 192 | font_size = round_text_size(font_size); | 234 | font_size = round_text_size(font_size); |
| 193 | 235 | ||
| 194 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); | 236 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); |
| 237 | fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start)); | ||
| 238 | if (backtrace) | ||
| 239 | fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace); | ||
| 195 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | 240 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", |
| 196 | time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); | 241 | time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); |
| 197 | if (font_size > MIN_TEXT_SIZE) | 242 | if (font_size > MIN_TEXT_SIZE) |
| @@ -242,28 +287,42 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) | |||
| 242 | max_freq = __max_freq; | 287 | max_freq = __max_freq; |
| 243 | turbo_frequency = __turbo_freq; | 288 | turbo_frequency = __turbo_freq; |
| 244 | 289 | ||
| 290 | fprintf(svgfile, "<g>\n"); | ||
| 291 | |||
| 245 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n", | 292 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n", |
| 246 | time2pixels(first_time), | 293 | time2pixels(first_time), |
| 247 | time2pixels(last_time)-time2pixels(first_time), | 294 | time2pixels(last_time)-time2pixels(first_time), |
| 248 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); | 295 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); |
| 249 | 296 | ||
| 250 | sprintf(cpu_string, "CPU %i", (int)cpu+1); | 297 | sprintf(cpu_string, "CPU %i", (int)cpu); |
| 251 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", | 298 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", |
| 252 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); | 299 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); |
| 253 | 300 | ||
| 254 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", | 301 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", |
| 255 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); | 302 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); |
| 303 | |||
| 304 | fprintf(svgfile, "</g>\n"); | ||
| 256 | } | 305 | } |
| 257 | 306 | ||
| 258 | void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name) | 307 | void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace) |
| 259 | { | 308 | { |
| 260 | double width; | 309 | double width; |
| 310 | const char *type; | ||
| 261 | 311 | ||
| 262 | if (!svgfile) | 312 | if (!svgfile) |
| 263 | return; | 313 | return; |
| 264 | 314 | ||
| 315 | if (svg_highlight && end - start >= svg_highlight) | ||
| 316 | type = "sample_hi"; | ||
| 317 | else if (svg_highlight_name && strstr(name, svg_highlight_name)) | ||
| 318 | type = "sample_hi"; | ||
| 319 | else | ||
| 320 | type = "sample"; | ||
| 265 | 321 | ||
| 266 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); | 322 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); |
| 323 | fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start)); | ||
| 324 | if (backtrace) | ||
| 325 | fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); | ||
| 267 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | 326 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", |
| 268 | time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); | 327 | time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); |
| 269 | width = time2pixels(end)-time2pixels(start); | 328 | width = time2pixels(end)-time2pixels(start); |
| @@ -288,6 +347,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type) | |||
| 288 | return; | 347 | return; |
| 289 | 348 | ||
| 290 | 349 | ||
| 350 | fprintf(svgfile, "<g>\n"); | ||
| 351 | |||
| 291 | if (type > 6) | 352 | if (type > 6) |
| 292 | type = 6; | 353 | type = 6; |
| 293 | sprintf(style, "c%i", type); | 354 | sprintf(style, "c%i", type); |
| @@ -306,6 +367,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type) | |||
| 306 | if (width > MIN_TEXT_SIZE) | 367 | if (width > MIN_TEXT_SIZE) |
| 307 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", | 368 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", |
| 308 | time2pixels(start), cpu2y(cpu)+width, width, type); | 369 | time2pixels(start), cpu2y(cpu)+width, width, type); |
| 370 | |||
| 371 | fprintf(svgfile, "</g>\n"); | ||
| 309 | } | 372 | } |
| 310 | 373 | ||
| 311 | static char *HzToHuman(unsigned long hz) | 374 | static char *HzToHuman(unsigned long hz) |
| @@ -339,6 +402,8 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq) | |||
| 339 | if (!svgfile) | 402 | if (!svgfile) |
| 340 | return; | 403 | return; |
| 341 | 404 | ||
| 405 | fprintf(svgfile, "<g>\n"); | ||
| 406 | |||
| 342 | if (max_freq) | 407 | if (max_freq) |
| 343 | height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); | 408 | height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); |
| 344 | height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; | 409 | height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; |
| @@ -347,10 +412,11 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq) | |||
| 347 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", | 412 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", |
| 348 | time2pixels(start), height+0.9, HzToHuman(freq)); | 413 | time2pixels(start), height+0.9, HzToHuman(freq)); |
| 349 | 414 | ||
| 415 | fprintf(svgfile, "</g>\n"); | ||
| 350 | } | 416 | } |
| 351 | 417 | ||
| 352 | 418 | ||
| 353 | void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2) | 419 | void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace) |
| 354 | { | 420 | { |
| 355 | double height; | 421 | double height; |
| 356 | 422 | ||
| @@ -358,6 +424,15 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc | |||
| 358 | return; | 424 | return; |
| 359 | 425 | ||
| 360 | 426 | ||
| 427 | fprintf(svgfile, "<g>\n"); | ||
| 428 | |||
| 429 | fprintf(svgfile, "<title>%s wakes up %s</title>\n", | ||
| 430 | desc1 ? desc1 : "?", | ||
| 431 | desc2 ? desc2 : "?"); | ||
| 432 | |||
| 433 | if (backtrace) | ||
| 434 | fprintf(svgfile, "<desc>%s</desc>\n", backtrace); | ||
| 435 | |||
| 361 | if (row1 < row2) { | 436 | if (row1 < row2) { |
| 362 | if (row1) { | 437 | if (row1) { |
| 363 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", | 438 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", |
| @@ -395,9 +470,11 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc | |||
| 395 | if (row1) | 470 | if (row1) |
| 396 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", | 471 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", |
| 397 | time2pixels(start), height); | 472 | time2pixels(start), height); |
| 473 | |||
| 474 | fprintf(svgfile, "</g>\n"); | ||
| 398 | } | 475 | } |
| 399 | 476 | ||
| 400 | void svg_wakeline(u64 start, int row1, int row2) | 477 | void svg_wakeline(u64 start, int row1, int row2, const char *backtrace) |
| 401 | { | 478 | { |
| 402 | double height; | 479 | double height; |
| 403 | 480 | ||
| @@ -405,6 +482,11 @@ void svg_wakeline(u64 start, int row1, int row2) | |||
| 405 | return; | 482 | return; |
| 406 | 483 | ||
| 407 | 484 | ||
| 485 | fprintf(svgfile, "<g>\n"); | ||
| 486 | |||
| 487 | if (backtrace) | ||
| 488 | fprintf(svgfile, "<desc>%s</desc>\n", backtrace); | ||
| 489 | |||
| 408 | if (row1 < row2) | 490 | if (row1 < row2) |
| 409 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", | 491 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", |
| 410 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); | 492 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); |
| @@ -417,17 +499,28 @@ void svg_wakeline(u64 start, int row1, int row2) | |||
| 417 | height += SLOT_HEIGHT; | 499 | height += SLOT_HEIGHT; |
| 418 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", | 500 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", |
| 419 | time2pixels(start), height); | 501 | time2pixels(start), height); |
| 502 | |||
| 503 | fprintf(svgfile, "</g>\n"); | ||
| 420 | } | 504 | } |
| 421 | 505 | ||
| 422 | void svg_interrupt(u64 start, int row) | 506 | void svg_interrupt(u64 start, int row, const char *backtrace) |
| 423 | { | 507 | { |
| 424 | if (!svgfile) | 508 | if (!svgfile) |
| 425 | return; | 509 | return; |
| 426 | 510 | ||
| 511 | fprintf(svgfile, "<g>\n"); | ||
| 512 | |||
| 513 | fprintf(svgfile, "<title>Wakeup from interrupt</title>\n"); | ||
| 514 | |||
| 515 | if (backtrace) | ||
| 516 | fprintf(svgfile, "<desc>%s</desc>\n", backtrace); | ||
| 517 | |||
| 427 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", | 518 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", |
| 428 | time2pixels(start), row * SLOT_MULT); | 519 | time2pixels(start), row * SLOT_MULT); |
| 429 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", | 520 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", |
| 430 | time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); | 521 | time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); |
| 522 | |||
| 523 | fprintf(svgfile, "</g>\n"); | ||
| 431 | } | 524 | } |
| 432 | 525 | ||
| 433 | void svg_text(int Yslot, u64 start, const char *text) | 526 | void svg_text(int Yslot, u64 start, const char *text) |
| @@ -455,6 +548,7 @@ void svg_legenda(void) | |||
| 455 | if (!svgfile) | 548 | if (!svgfile) |
| 456 | return; | 549 | return; |
| 457 | 550 | ||
| 551 | fprintf(svgfile, "<g>\n"); | ||
| 458 | svg_legenda_box(0, "Running", "sample"); | 552 | svg_legenda_box(0, "Running", "sample"); |
| 459 | svg_legenda_box(100, "Idle","c1"); | 553 | svg_legenda_box(100, "Idle","c1"); |
| 460 | svg_legenda_box(200, "Deeper Idle", "c3"); | 554 | svg_legenda_box(200, "Deeper Idle", "c3"); |
| @@ -462,6 +556,7 @@ void svg_legenda(void) | |||
| 462 | svg_legenda_box(550, "Sleeping", "process2"); | 556 | svg_legenda_box(550, "Sleeping", "process2"); |
| 463 | svg_legenda_box(650, "Waiting for cpu", "waiting"); | 557 | svg_legenda_box(650, "Waiting for cpu", "waiting"); |
| 464 | svg_legenda_box(800, "Blocked on IO", "blocked"); | 558 | svg_legenda_box(800, "Blocked on IO", "blocked"); |
| 559 | fprintf(svgfile, "</g>\n"); | ||
| 465 | } | 560 | } |
| 466 | 561 | ||
| 467 | void svg_time_grid(void) | 562 | void svg_time_grid(void) |
| @@ -499,3 +594,123 @@ void svg_close(void) | |||
| 499 | svgfile = NULL; | 594 | svgfile = NULL; |
| 500 | } | 595 | } |
| 501 | } | 596 | } |
| 597 | |||
| 598 | #define cpumask_bits(maskp) ((maskp)->bits) | ||
| 599 | typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t; | ||
| 600 | |||
| 601 | struct topology { | ||
| 602 | cpumask_t *sib_core; | ||
| 603 | int sib_core_nr; | ||
| 604 | cpumask_t *sib_thr; | ||
| 605 | int sib_thr_nr; | ||
| 606 | }; | ||
| 607 | |||
| 608 | static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos) | ||
| 609 | { | ||
| 610 | int i; | ||
| 611 | int thr; | ||
| 612 | |||
| 613 | for (i = 0; i < t->sib_thr_nr; i++) { | ||
| 614 | if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i]))) | ||
| 615 | continue; | ||
| 616 | |||
| 617 | for_each_set_bit(thr, | ||
| 618 | cpumask_bits(&t->sib_thr[i]), | ||
| 619 | MAX_NR_CPUS) | ||
| 620 | if (map[thr] == -1) | ||
| 621 | map[thr] = (*pos)++; | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 625 | static void scan_core_topology(int *map, struct topology *t) | ||
| 626 | { | ||
| 627 | int pos = 0; | ||
| 628 | int i; | ||
| 629 | int cpu; | ||
| 630 | |||
| 631 | for (i = 0; i < t->sib_core_nr; i++) | ||
| 632 | for_each_set_bit(cpu, | ||
| 633 | cpumask_bits(&t->sib_core[i]), | ||
| 634 | MAX_NR_CPUS) | ||
| 635 | scan_thread_topology(map, t, cpu, &pos); | ||
| 636 | } | ||
| 637 | |||
| 638 | static int str_to_bitmap(char *s, cpumask_t *b) | ||
| 639 | { | ||
| 640 | int i; | ||
| 641 | int ret = 0; | ||
| 642 | struct cpu_map *m; | ||
| 643 | int c; | ||
| 644 | |||
| 645 | m = cpu_map__new(s); | ||
| 646 | if (!m) | ||
| 647 | return -1; | ||
| 648 | |||
| 649 | for (i = 0; i < m->nr; i++) { | ||
| 650 | c = m->map[i]; | ||
| 651 | if (c >= MAX_NR_CPUS) { | ||
| 652 | ret = -1; | ||
| 653 | break; | ||
| 654 | } | ||
| 655 | |||
| 656 | set_bit(c, cpumask_bits(b)); | ||
| 657 | } | ||
| 658 | |||
| 659 | cpu_map__delete(m); | ||
| 660 | |||
| 661 | return ret; | ||
| 662 | } | ||
| 663 | |||
| 664 | int svg_build_topology_map(char *sib_core, int sib_core_nr, | ||
| 665 | char *sib_thr, int sib_thr_nr) | ||
| 666 | { | ||
| 667 | int i; | ||
| 668 | struct topology t; | ||
| 669 | |||
| 670 | t.sib_core_nr = sib_core_nr; | ||
| 671 | t.sib_thr_nr = sib_thr_nr; | ||
| 672 | t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t)); | ||
| 673 | t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t)); | ||
| 674 | |||
| 675 | if (!t.sib_core || !t.sib_thr) { | ||
| 676 | fprintf(stderr, "topology: no memory\n"); | ||
| 677 | goto exit; | ||
| 678 | } | ||
| 679 | |||
| 680 | for (i = 0; i < sib_core_nr; i++) { | ||
| 681 | if (str_to_bitmap(sib_core, &t.sib_core[i])) { | ||
| 682 | fprintf(stderr, "topology: can't parse siblings map\n"); | ||
| 683 | goto exit; | ||
| 684 | } | ||
| 685 | |||
| 686 | sib_core += strlen(sib_core) + 1; | ||
| 687 | } | ||
| 688 | |||
| 689 | for (i = 0; i < sib_thr_nr; i++) { | ||
| 690 | if (str_to_bitmap(sib_thr, &t.sib_thr[i])) { | ||
| 691 | fprintf(stderr, "topology: can't parse siblings map\n"); | ||
| 692 | goto exit; | ||
| 693 | } | ||
| 694 | |||
| 695 | sib_thr += strlen(sib_thr) + 1; | ||
| 696 | } | ||
| 697 | |||
| 698 | topology_map = malloc(sizeof(int) * MAX_NR_CPUS); | ||
| 699 | if (!topology_map) { | ||
| 700 | fprintf(stderr, "topology: no memory\n"); | ||
| 701 | goto exit; | ||
| 702 | } | ||
| 703 | |||
| 704 | for (i = 0; i < MAX_NR_CPUS; i++) | ||
| 705 | topology_map[i] = -1; | ||
| 706 | |||
| 707 | scan_core_topology(topology_map, &t); | ||
| 708 | |||
| 709 | return 0; | ||
| 710 | |||
| 711 | exit: | ||
| 712 | zfree(&t.sib_core); | ||
| 713 | zfree(&t.sib_thr); | ||
| 714 | |||
| 715 | return -1; | ||
| 716 | } | ||
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h index e0781989cc31..f7b4d6e699ea 100644 --- a/tools/perf/util/svghelper.h +++ b/tools/perf/util/svghelper.h | |||
| @@ -5,24 +5,29 @@ | |||
| 5 | 5 | ||
| 6 | extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); | 6 | extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); |
| 7 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); | 7 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); |
| 8 | extern void svg_sample(int Yslot, int cpu, u64 start, u64 end); | 8 | extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
| 9 | extern void svg_waiting(int Yslot, u64 start, u64 end); | 9 | extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
| 10 | extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); | ||
| 10 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); | 11 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); |
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name); | 14 | extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace); |
| 14 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); | 15 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); |
| 15 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); | 16 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); |
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | extern void svg_time_grid(void); | 19 | extern void svg_time_grid(void); |
| 19 | extern void svg_legenda(void); | 20 | extern void svg_legenda(void); |
| 20 | extern void svg_wakeline(u64 start, int row1, int row2); | 21 | extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace); |
| 21 | extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2); | 22 | extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace); |
| 22 | extern void svg_interrupt(u64 start, int row); | 23 | extern void svg_interrupt(u64 start, int row, const char *backtrace); |
| 23 | extern void svg_text(int Yslot, u64 start, const char *text); | 24 | extern void svg_text(int Yslot, u64 start, const char *text); |
| 24 | extern void svg_close(void); | 25 | extern void svg_close(void); |
| 26 | extern int svg_build_topology_map(char *sib_core, int sib_core_nr, | ||
| 27 | char *sib_thr, int sib_thr_nr); | ||
| 25 | 28 | ||
| 26 | extern int svg_page_width; | 29 | extern int svg_page_width; |
| 30 | extern u64 svg_highlight; | ||
| 31 | extern const char *svg_highlight_name; | ||
| 27 | 32 | ||
| 28 | #endif /* __PERF_SVGHELPER_H */ | 33 | #endif /* __PERF_SVGHELPER_H */ |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index eed0b96302af..759456728703 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <inttypes.h> | 6 | #include <inttypes.h> |
| 7 | 7 | ||
| 8 | #include "symbol.h" | 8 | #include "symbol.h" |
| 9 | #include <symbol/kallsyms.h> | ||
| 9 | #include "debug.h" | 10 | #include "debug.h" |
| 10 | 11 | ||
| 11 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT | 12 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT |
| @@ -135,9 +136,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) | |||
| 135 | return -1; | 136 | return -1; |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 138 | static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | 139 | Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, |
| 139 | GElf_Shdr *shp, const char *name, | 140 | GElf_Shdr *shp, const char *name, size_t *idx) |
| 140 | size_t *idx) | ||
| 141 | { | 141 | { |
| 142 | Elf_Scn *sec = NULL; | 142 | Elf_Scn *sec = NULL; |
| 143 | size_t cnt = 1; | 143 | size_t cnt = 1; |
| @@ -553,7 +553,7 @@ bool symsrc__has_symtab(struct symsrc *ss) | |||
| 553 | 553 | ||
| 554 | void symsrc__destroy(struct symsrc *ss) | 554 | void symsrc__destroy(struct symsrc *ss) |
| 555 | { | 555 | { |
| 556 | free(ss->name); | 556 | zfree(&ss->name); |
| 557 | elf_end(ss->elf); | 557 | elf_end(ss->elf); |
| 558 | close(ss->fd); | 558 | close(ss->fd); |
| 559 | } | 559 | } |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 2d2dd0532b5a..bd15f490d04f 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include "symbol.h" | 1 | #include "symbol.h" |
| 2 | #include "util.h" | ||
| 2 | 3 | ||
| 3 | #include <stdio.h> | 4 | #include <stdio.h> |
| 4 | #include <fcntl.h> | 5 | #include <fcntl.h> |
| @@ -253,6 +254,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, | |||
| 253 | if (!ss->name) | 254 | if (!ss->name) |
| 254 | goto out_close; | 255 | goto out_close; |
| 255 | 256 | ||
| 257 | ss->fd = fd; | ||
| 256 | ss->type = type; | 258 | ss->type = type; |
| 257 | 259 | ||
| 258 | return 0; | 260 | return 0; |
| @@ -274,7 +276,7 @@ bool symsrc__has_symtab(struct symsrc *ss __maybe_unused) | |||
| 274 | 276 | ||
| 275 | void symsrc__destroy(struct symsrc *ss) | 277 | void symsrc__destroy(struct symsrc *ss) |
| 276 | { | 278 | { |
| 277 | free(ss->name); | 279 | zfree(&ss->name); |
| 278 | close(ss->fd); | 280 | close(ss->fd); |
| 279 | } | 281 | } |
| 280 | 282 | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c0c36965fff0..39ce9adbaaf0 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -18,12 +18,9 @@ | |||
| 18 | 18 | ||
| 19 | #include <elf.h> | 19 | #include <elf.h> |
| 20 | #include <limits.h> | 20 | #include <limits.h> |
| 21 | #include <symbol/kallsyms.h> | ||
| 21 | #include <sys/utsname.h> | 22 | #include <sys/utsname.h> |
| 22 | 23 | ||
| 23 | #ifndef KSYM_NAME_LEN | ||
| 24 | #define KSYM_NAME_LEN 256 | ||
| 25 | #endif | ||
| 26 | |||
| 27 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, | 24 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, |
| 28 | symbol_filter_t filter); | 25 | symbol_filter_t filter); |
| 29 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | 26 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, |
| @@ -446,62 +443,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso, | |||
| 446 | return ret; | 443 | return ret; |
| 447 | } | 444 | } |
| 448 | 445 | ||
| 449 | int kallsyms__parse(const char *filename, void *arg, | ||
| 450 | int (*process_symbol)(void *arg, const char *name, | ||
| 451 | char type, u64 start)) | ||
| 452 | { | ||
| 453 | char *line = NULL; | ||
| 454 | size_t n; | ||
| 455 | int err = -1; | ||
| 456 | FILE *file = fopen(filename, "r"); | ||
| 457 | |||
| 458 | if (file == NULL) | ||
| 459 | goto out_failure; | ||
| 460 | |||
| 461 | err = 0; | ||
| 462 | |||
| 463 | while (!feof(file)) { | ||
| 464 | u64 start; | ||
| 465 | int line_len, len; | ||
| 466 | char symbol_type; | ||
| 467 | char *symbol_name; | ||
| 468 | |||
| 469 | line_len = getline(&line, &n, file); | ||
| 470 | if (line_len < 0 || !line) | ||
| 471 | break; | ||
| 472 | |||
| 473 | line[--line_len] = '\0'; /* \n */ | ||
| 474 | |||
| 475 | len = hex2u64(line, &start); | ||
| 476 | |||
| 477 | len++; | ||
| 478 | if (len + 2 >= line_len) | ||
| 479 | continue; | ||
| 480 | |||
| 481 | symbol_type = line[len]; | ||
| 482 | len += 2; | ||
| 483 | symbol_name = line + len; | ||
| 484 | len = line_len - len; | ||
| 485 | |||
| 486 | if (len >= KSYM_NAME_LEN) { | ||
| 487 | err = -1; | ||
| 488 | break; | ||
| 489 | } | ||
| 490 | |||
| 491 | err = process_symbol(arg, symbol_name, | ||
| 492 | symbol_type, start); | ||
| 493 | if (err) | ||
| 494 | break; | ||
| 495 | } | ||
| 496 | |||
| 497 | free(line); | ||
| 498 | fclose(file); | ||
| 499 | return err; | ||
| 500 | |||
| 501 | out_failure: | ||
| 502 | return -1; | ||
| 503 | } | ||
| 504 | |||
| 505 | int modules__parse(const char *filename, void *arg, | 446 | int modules__parse(const char *filename, void *arg, |
| 506 | int (*process_module)(void *arg, const char *name, | 447 | int (*process_module)(void *arg, const char *name, |
| 507 | u64 start)) | 448 | u64 start)) |
| @@ -565,12 +506,34 @@ struct process_kallsyms_args { | |||
| 565 | struct dso *dso; | 506 | struct dso *dso; |
| 566 | }; | 507 | }; |
| 567 | 508 | ||
| 568 | static u8 kallsyms2elf_type(char type) | 509 | bool symbol__is_idle(struct symbol *sym) |
| 569 | { | 510 | { |
| 570 | if (type == 'W') | 511 | const char * const idle_symbols[] = { |
| 571 | return STB_WEAK; | 512 | "cpu_idle", |
| 513 | "intel_idle", | ||
| 514 | "default_idle", | ||
| 515 | "native_safe_halt", | ||
| 516 | "enter_idle", | ||
| 517 | "exit_idle", | ||
| 518 | "mwait_idle", | ||
| 519 | "mwait_idle_with_hints", | ||
| 520 | "poll_idle", | ||
| 521 | "ppc64_runlatch_off", | ||
| 522 | "pseries_dedicated_idle_sleep", | ||
| 523 | NULL | ||
| 524 | }; | ||
| 525 | |||
| 526 | int i; | ||
| 527 | |||
| 528 | if (!sym) | ||
| 529 | return false; | ||
| 530 | |||
| 531 | for (i = 0; idle_symbols[i]; i++) { | ||
| 532 | if (!strcmp(idle_symbols[i], sym->name)) | ||
| 533 | return true; | ||
| 534 | } | ||
| 572 | 535 | ||
| 573 | return isupper(type) ? STB_GLOBAL : STB_LOCAL; | 536 | return false; |
| 574 | } | 537 | } |
| 575 | 538 | ||
| 576 | static int map__process_kallsym_symbol(void *arg, const char *name, | 539 | static int map__process_kallsym_symbol(void *arg, const char *name, |
| @@ -833,7 +796,7 @@ static void delete_modules(struct rb_root *modules) | |||
| 833 | mi = rb_entry(next, struct module_info, rb_node); | 796 | mi = rb_entry(next, struct module_info, rb_node); |
| 834 | next = rb_next(&mi->rb_node); | 797 | next = rb_next(&mi->rb_node); |
| 835 | rb_erase(&mi->rb_node, modules); | 798 | rb_erase(&mi->rb_node, modules); |
| 836 | free(mi->name); | 799 | zfree(&mi->name); |
| 837 | free(mi); | 800 | free(mi); |
| 838 | } | 801 | } |
| 839 | } | 802 | } |
| @@ -1126,10 +1089,10 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1126 | * dso__data_read_addr(). | 1089 | * dso__data_read_addr(). |
| 1127 | */ | 1090 | */ |
| 1128 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | 1091 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
| 1129 | dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; | 1092 | dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE; |
| 1130 | else | 1093 | else |
| 1131 | dso->data_type = DSO_BINARY_TYPE__KCORE; | 1094 | dso->binary_type = DSO_BINARY_TYPE__KCORE; |
| 1132 | dso__set_long_name(dso, strdup(kcore_filename)); | 1095 | dso__set_long_name(dso, strdup(kcore_filename), true); |
| 1133 | 1096 | ||
| 1134 | close(fd); | 1097 | close(fd); |
| 1135 | 1098 | ||
| @@ -1295,8 +1258,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
| 1295 | 1258 | ||
| 1296 | enum dso_binary_type symtab_type = binary_type_symtab[i]; | 1259 | enum dso_binary_type symtab_type = binary_type_symtab[i]; |
| 1297 | 1260 | ||
| 1298 | if (dso__binary_type_file(dso, symtab_type, | 1261 | if (dso__read_binary_type_filename(dso, symtab_type, |
| 1299 | root_dir, name, PATH_MAX)) | 1262 | root_dir, name, PATH_MAX)) |
| 1300 | continue; | 1263 | continue; |
| 1301 | 1264 | ||
| 1302 | /* Name is now the name of the next image to try */ | 1265 | /* Name is now the name of the next image to try */ |
| @@ -1306,6 +1269,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
| 1306 | if (!syms_ss && symsrc__has_symtab(ss)) { | 1269 | if (!syms_ss && symsrc__has_symtab(ss)) { |
| 1307 | syms_ss = ss; | 1270 | syms_ss = ss; |
| 1308 | next_slot = true; | 1271 | next_slot = true; |
| 1272 | if (!dso->symsrc_filename) | ||
| 1273 | dso->symsrc_filename = strdup(name); | ||
| 1309 | } | 1274 | } |
| 1310 | 1275 | ||
| 1311 | if (!runtime_ss && symsrc__possibly_runtime(ss)) { | 1276 | if (!runtime_ss && symsrc__possibly_runtime(ss)) { |
| @@ -1376,7 +1341,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg, | |||
| 1376 | } | 1341 | } |
| 1377 | 1342 | ||
| 1378 | int dso__load_vmlinux(struct dso *dso, struct map *map, | 1343 | int dso__load_vmlinux(struct dso *dso, struct map *map, |
| 1379 | const char *vmlinux, symbol_filter_t filter) | 1344 | const char *vmlinux, bool vmlinux_allocated, |
| 1345 | symbol_filter_t filter) | ||
| 1380 | { | 1346 | { |
| 1381 | int err = -1; | 1347 | int err = -1; |
| 1382 | struct symsrc ss; | 1348 | struct symsrc ss; |
| @@ -1402,10 +1368,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, | |||
| 1402 | 1368 | ||
| 1403 | if (err > 0) { | 1369 | if (err > 0) { |
| 1404 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | 1370 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
| 1405 | dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX; | 1371 | dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX; |
| 1406 | else | 1372 | else |
| 1407 | dso->data_type = DSO_BINARY_TYPE__VMLINUX; | 1373 | dso->binary_type = DSO_BINARY_TYPE__VMLINUX; |
| 1408 | dso__set_long_name(dso, (char *)vmlinux); | 1374 | dso__set_long_name(dso, vmlinux, vmlinux_allocated); |
| 1409 | dso__set_loaded(dso, map->type); | 1375 | dso__set_loaded(dso, map->type); |
| 1410 | pr_debug("Using %s for symbols\n", symfs_vmlinux); | 1376 | pr_debug("Using %s for symbols\n", symfs_vmlinux); |
| 1411 | } | 1377 | } |
| @@ -1424,21 +1390,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
| 1424 | 1390 | ||
| 1425 | filename = dso__build_id_filename(dso, NULL, 0); | 1391 | filename = dso__build_id_filename(dso, NULL, 0); |
| 1426 | if (filename != NULL) { | 1392 | if (filename != NULL) { |
| 1427 | err = dso__load_vmlinux(dso, map, filename, filter); | 1393 | err = dso__load_vmlinux(dso, map, filename, true, filter); |
| 1428 | if (err > 0) { | 1394 | if (err > 0) |
| 1429 | dso->lname_alloc = 1; | ||
| 1430 | goto out; | 1395 | goto out; |
| 1431 | } | ||
| 1432 | free(filename); | 1396 | free(filename); |
| 1433 | } | 1397 | } |
| 1434 | 1398 | ||
| 1435 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | 1399 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { |
| 1436 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); | 1400 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); |
| 1437 | if (err > 0) { | 1401 | if (err > 0) |
| 1438 | dso__set_long_name(dso, strdup(vmlinux_path[i])); | ||
| 1439 | dso->lname_alloc = 1; | ||
| 1440 | break; | 1402 | break; |
| 1441 | } | ||
| 1442 | } | 1403 | } |
| 1443 | out: | 1404 | out: |
| 1444 | return err; | 1405 | return err; |
| @@ -1496,14 +1457,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
| 1496 | 1457 | ||
| 1497 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | 1458 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
| 1498 | 1459 | ||
| 1460 | scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir, | ||
| 1461 | sbuild_id); | ||
| 1462 | |||
| 1499 | /* Use /proc/kallsyms if possible */ | 1463 | /* Use /proc/kallsyms if possible */ |
| 1500 | if (is_host) { | 1464 | if (is_host) { |
| 1501 | DIR *d; | 1465 | DIR *d; |
| 1502 | int fd; | 1466 | int fd; |
| 1503 | 1467 | ||
| 1504 | /* If no cached kcore go with /proc/kallsyms */ | 1468 | /* If no cached kcore go with /proc/kallsyms */ |
| 1505 | scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", | ||
| 1506 | buildid_dir, sbuild_id); | ||
| 1507 | d = opendir(path); | 1469 | d = opendir(path); |
| 1508 | if (!d) | 1470 | if (!d) |
| 1509 | goto proc_kallsyms; | 1471 | goto proc_kallsyms; |
| @@ -1528,6 +1490,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
| 1528 | goto proc_kallsyms; | 1490 | goto proc_kallsyms; |
| 1529 | } | 1491 | } |
| 1530 | 1492 | ||
| 1493 | /* Find kallsyms in build-id cache with kcore */ | ||
| 1494 | if (!find_matching_kcore(map, path, sizeof(path))) | ||
| 1495 | return strdup(path); | ||
| 1496 | |||
| 1531 | scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", | 1497 | scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", |
| 1532 | buildid_dir, sbuild_id); | 1498 | buildid_dir, sbuild_id); |
| 1533 | 1499 | ||
| @@ -1570,15 +1536,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, | |||
| 1570 | } | 1536 | } |
| 1571 | 1537 | ||
| 1572 | if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { | 1538 | if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { |
| 1573 | err = dso__load_vmlinux(dso, map, | 1539 | return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, |
| 1574 | symbol_conf.vmlinux_name, filter); | 1540 | false, filter); |
| 1575 | if (err > 0) { | ||
| 1576 | dso__set_long_name(dso, | ||
| 1577 | strdup(symbol_conf.vmlinux_name)); | ||
| 1578 | dso->lname_alloc = 1; | ||
| 1579 | return err; | ||
| 1580 | } | ||
| 1581 | return err; | ||
| 1582 | } | 1541 | } |
| 1583 | 1542 | ||
| 1584 | if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { | 1543 | if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { |
| @@ -1604,7 +1563,7 @@ do_kallsyms: | |||
| 1604 | free(kallsyms_allocated_filename); | 1563 | free(kallsyms_allocated_filename); |
| 1605 | 1564 | ||
| 1606 | if (err > 0 && !dso__is_kcore(dso)) { | 1565 | if (err > 0 && !dso__is_kcore(dso)) { |
| 1607 | dso__set_long_name(dso, strdup("[kernel.kallsyms]")); | 1566 | dso__set_long_name(dso, "[kernel.kallsyms]", false); |
| 1608 | map__fixup_start(map); | 1567 | map__fixup_start(map); |
| 1609 | map__fixup_end(map); | 1568 | map__fixup_end(map); |
| 1610 | } | 1569 | } |
| @@ -1634,7 +1593,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
| 1634 | */ | 1593 | */ |
| 1635 | if (symbol_conf.default_guest_vmlinux_name != NULL) { | 1594 | if (symbol_conf.default_guest_vmlinux_name != NULL) { |
| 1636 | err = dso__load_vmlinux(dso, map, | 1595 | err = dso__load_vmlinux(dso, map, |
| 1637 | symbol_conf.default_guest_vmlinux_name, filter); | 1596 | symbol_conf.default_guest_vmlinux_name, |
| 1597 | false, filter); | ||
| 1638 | return err; | 1598 | return err; |
| 1639 | } | 1599 | } |
| 1640 | 1600 | ||
| @@ -1651,7 +1611,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
| 1651 | pr_debug("Using %s for symbols\n", kallsyms_filename); | 1611 | pr_debug("Using %s for symbols\n", kallsyms_filename); |
| 1652 | if (err > 0 && !dso__is_kcore(dso)) { | 1612 | if (err > 0 && !dso__is_kcore(dso)) { |
| 1653 | machine__mmap_name(machine, path, sizeof(path)); | 1613 | machine__mmap_name(machine, path, sizeof(path)); |
| 1654 | dso__set_long_name(dso, strdup(path)); | 1614 | dso__set_long_name(dso, strdup(path), true); |
| 1655 | map__fixup_start(map); | 1615 | map__fixup_start(map); |
| 1656 | map__fixup_end(map); | 1616 | map__fixup_end(map); |
| 1657 | } | 1617 | } |
| @@ -1661,13 +1621,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
| 1661 | 1621 | ||
| 1662 | static void vmlinux_path__exit(void) | 1622 | static void vmlinux_path__exit(void) |
| 1663 | { | 1623 | { |
| 1664 | while (--vmlinux_path__nr_entries >= 0) { | 1624 | while (--vmlinux_path__nr_entries >= 0) |
| 1665 | free(vmlinux_path[vmlinux_path__nr_entries]); | 1625 | zfree(&vmlinux_path[vmlinux_path__nr_entries]); |
| 1666 | vmlinux_path[vmlinux_path__nr_entries] = NULL; | ||
| 1667 | } | ||
| 1668 | 1626 | ||
| 1669 | free(vmlinux_path); | 1627 | zfree(&vmlinux_path); |
| 1670 | vmlinux_path = NULL; | ||
| 1671 | } | 1628 | } |
| 1672 | 1629 | ||
| 1673 | static int vmlinux_path__init(void) | 1630 | static int vmlinux_path__init(void) |
| @@ -1719,7 +1676,7 @@ out_fail: | |||
| 1719 | return -1; | 1676 | return -1; |
| 1720 | } | 1677 | } |
| 1721 | 1678 | ||
| 1722 | static int setup_list(struct strlist **list, const char *list_str, | 1679 | int setup_list(struct strlist **list, const char *list_str, |
| 1723 | const char *list_name) | 1680 | const char *list_name) |
| 1724 | { | 1681 | { |
| 1725 | if (list_str == NULL) | 1682 | if (list_str == NULL) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 07de8fea2f48..fffe2888a1c7 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -52,6 +52,11 @@ static inline char *bfd_demangle(void __maybe_unused *v, | |||
| 52 | # define PERF_ELF_C_READ_MMAP ELF_C_READ | 52 | # define PERF_ELF_C_READ_MMAP ELF_C_READ |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | #ifdef HAVE_LIBELF_SUPPORT | ||
| 56 | extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | ||
| 57 | GElf_Shdr *shp, const char *name, size_t *idx); | ||
| 58 | #endif | ||
| 59 | |||
| 55 | #ifndef DMGL_PARAMS | 60 | #ifndef DMGL_PARAMS |
| 56 | #define DMGL_PARAMS (1 << 0) /* Include function args */ | 61 | #define DMGL_PARAMS (1 << 0) /* Include function args */ |
| 57 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | 62 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
| @@ -164,6 +169,7 @@ struct mem_info { | |||
| 164 | }; | 169 | }; |
| 165 | 170 | ||
| 166 | struct addr_location { | 171 | struct addr_location { |
| 172 | struct machine *machine; | ||
| 167 | struct thread *thread; | 173 | struct thread *thread; |
| 168 | struct map *map; | 174 | struct map *map; |
| 169 | struct symbol *sym; | 175 | struct symbol *sym; |
| @@ -206,7 +212,8 @@ bool symsrc__possibly_runtime(struct symsrc *ss); | |||
| 206 | 212 | ||
| 207 | int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); | 213 | int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); |
| 208 | int dso__load_vmlinux(struct dso *dso, struct map *map, | 214 | int dso__load_vmlinux(struct dso *dso, struct map *map, |
| 209 | const char *vmlinux, symbol_filter_t filter); | 215 | const char *vmlinux, bool vmlinux_allocated, |
| 216 | symbol_filter_t filter); | ||
| 210 | int dso__load_vmlinux_path(struct dso *dso, struct map *map, | 217 | int dso__load_vmlinux_path(struct dso *dso, struct map *map, |
| 211 | symbol_filter_t filter); | 218 | symbol_filter_t filter); |
| 212 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, | 219 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, |
| @@ -220,9 +227,6 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); | |||
| 220 | 227 | ||
| 221 | int filename__read_build_id(const char *filename, void *bf, size_t size); | 228 | int filename__read_build_id(const char *filename, void *bf, size_t size); |
| 222 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); | 229 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); |
| 223 | int kallsyms__parse(const char *filename, void *arg, | ||
| 224 | int (*process_symbol)(void *arg, const char *name, | ||
| 225 | char type, u64 start)); | ||
| 226 | int modules__parse(const char *filename, void *arg, | 230 | int modules__parse(const char *filename, void *arg, |
| 227 | int (*process_module)(void *arg, const char *name, | 231 | int (*process_module)(void *arg, const char *name, |
| 228 | u64 start)); | 232 | u64 start)); |
| @@ -240,6 +244,7 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp); | |||
| 240 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | 244 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); |
| 241 | bool symbol__restricted_filename(const char *filename, | 245 | bool symbol__restricted_filename(const char *filename, |
| 242 | const char *restricted_filename); | 246 | const char *restricted_filename); |
| 247 | bool symbol__is_idle(struct symbol *sym); | ||
| 243 | 248 | ||
| 244 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | 249 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, |
| 245 | struct symsrc *runtime_ss, symbol_filter_t filter, | 250 | struct symsrc *runtime_ss, symbol_filter_t filter, |
| @@ -273,4 +278,7 @@ void kcore_extract__delete(struct kcore_extract *kce); | |||
| 273 | int kcore_copy(const char *from_dir, const char *to_dir); | 278 | int kcore_copy(const char *from_dir, const char *to_dir); |
| 274 | int compare_proc_modules(const char *from, const char *to); | 279 | int compare_proc_modules(const char *from, const char *to); |
| 275 | 280 | ||
| 281 | int setup_list(struct strlist **list, const char *list_str, | ||
| 282 | const char *list_name); | ||
| 283 | |||
| 276 | #endif /* __PERF_SYMBOL */ | 284 | #endif /* __PERF_SYMBOL */ |
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 3c778a07b7cc..e74c5963dc7a 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c | |||
| @@ -55,6 +55,13 @@ enum target_errno target__validate(struct target *target) | |||
| 55 | ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; | 55 | ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | /* THREAD and SYSTEM/CPU are mutually exclusive */ | ||
| 59 | if (target->per_thread && (target->system_wide || target->cpu_list)) { | ||
| 60 | target->per_thread = false; | ||
| 61 | if (ret == TARGET_ERRNO__SUCCESS) | ||
| 62 | ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD; | ||
| 63 | } | ||
| 64 | |||
| 58 | return ret; | 65 | return ret; |
| 59 | } | 66 | } |
| 60 | 67 | ||
| @@ -100,6 +107,7 @@ static const char *target__error_str[] = { | |||
| 100 | "UID switch overriding CPU", | 107 | "UID switch overriding CPU", |
| 101 | "PID/TID switch overriding SYSTEM", | 108 | "PID/TID switch overriding SYSTEM", |
| 102 | "UID switch overriding SYSTEM", | 109 | "UID switch overriding SYSTEM", |
| 110 | "SYSTEM/CPU switch overriding PER-THREAD", | ||
| 103 | "Invalid User: %s", | 111 | "Invalid User: %s", |
| 104 | "Problems obtaining information for user %s", | 112 | "Problems obtaining information for user %s", |
| 105 | }; | 113 | }; |
| @@ -131,7 +139,8 @@ int target__strerror(struct target *target, int errnum, | |||
| 131 | msg = target__error_str[idx]; | 139 | msg = target__error_str[idx]; |
| 132 | 140 | ||
| 133 | switch (errnum) { | 141 | switch (errnum) { |
| 134 | case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM: | 142 | case TARGET_ERRNO__PID_OVERRIDE_CPU ... |
| 143 | TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD: | ||
| 135 | snprintf(buf, buflen, "%s", msg); | 144 | snprintf(buf, buflen, "%s", msg); |
| 136 | break; | 145 | break; |
| 137 | 146 | ||
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h index 2d0c50690892..7381b1ca4041 100644 --- a/tools/perf/util/target.h +++ b/tools/perf/util/target.h | |||
| @@ -12,7 +12,8 @@ struct target { | |||
| 12 | uid_t uid; | 12 | uid_t uid; |
| 13 | bool system_wide; | 13 | bool system_wide; |
| 14 | bool uses_mmap; | 14 | bool uses_mmap; |
| 15 | bool force_per_cpu; | 15 | bool default_per_cpu; |
| 16 | bool per_thread; | ||
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| 18 | enum target_errno { | 19 | enum target_errno { |
| @@ -33,6 +34,7 @@ enum target_errno { | |||
| 33 | TARGET_ERRNO__UID_OVERRIDE_CPU, | 34 | TARGET_ERRNO__UID_OVERRIDE_CPU, |
| 34 | TARGET_ERRNO__PID_OVERRIDE_SYSTEM, | 35 | TARGET_ERRNO__PID_OVERRIDE_SYSTEM, |
| 35 | TARGET_ERRNO__UID_OVERRIDE_SYSTEM, | 36 | TARGET_ERRNO__UID_OVERRIDE_SYSTEM, |
| 37 | TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD, | ||
| 36 | 38 | ||
| 37 | /* for target__parse_uid() */ | 39 | /* for target__parse_uid() */ |
| 38 | TARGET_ERRNO__INVALID_UID, | 40 | TARGET_ERRNO__INVALID_UID, |
| @@ -61,4 +63,17 @@ static inline bool target__none(struct target *target) | |||
| 61 | return !target__has_task(target) && !target__has_cpu(target); | 63 | return !target__has_task(target) && !target__has_cpu(target); |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 66 | static inline bool target__uses_dummy_map(struct target *target) | ||
| 67 | { | ||
| 68 | bool use_dummy = false; | ||
| 69 | |||
| 70 | if (target->default_per_cpu) | ||
| 71 | use_dummy = target->per_thread ? true : false; | ||
| 72 | else if (target__has_task(target) || | ||
| 73 | (!target__has_cpu(target) && !target->uses_mmap)) | ||
| 74 | use_dummy = true; | ||
| 75 | |||
| 76 | return use_dummy; | ||
| 77 | } | ||
| 78 | |||
| 64 | #endif /* _PERF_TARGET_H */ | 79 | #endif /* _PERF_TARGET_H */ |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 49eaf1d7d89d..0358882c8910 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
| @@ -66,10 +66,13 @@ struct comm *thread__comm(const struct thread *thread) | |||
| 66 | int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) | 66 | int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) |
| 67 | { | 67 | { |
| 68 | struct comm *new, *curr = thread__comm(thread); | 68 | struct comm *new, *curr = thread__comm(thread); |
| 69 | int err; | ||
| 69 | 70 | ||
| 70 | /* Override latest entry if it had no specific time coverage */ | 71 | /* Override latest entry if it had no specific time coverage */ |
| 71 | if (!curr->start) { | 72 | if (!curr->start) { |
| 72 | comm__override(curr, str, timestamp); | 73 | err = comm__override(curr, str, timestamp); |
| 74 | if (err) | ||
| 75 | return err; | ||
| 73 | } else { | 76 | } else { |
| 74 | new = comm__new(str, timestamp); | 77 | new = comm__new(str, timestamp); |
| 75 | if (!new) | 78 | if (!new) |
| @@ -126,7 +129,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) | |||
| 126 | if (!comm) | 129 | if (!comm) |
| 127 | return -ENOMEM; | 130 | return -ENOMEM; |
| 128 | err = thread__set_comm(thread, comm, timestamp); | 131 | err = thread__set_comm(thread, comm, timestamp); |
| 129 | if (!err) | 132 | if (err) |
| 130 | return err; | 133 | return err; |
| 131 | thread->comm_set = true; | 134 | thread->comm_set = true; |
| 132 | } | 135 | } |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 897c1b2a750a..5b856bf942e1 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <unistd.h> | 6 | #include <unistd.h> |
| 7 | #include <sys/types.h> | 7 | #include <sys/types.h> |
| 8 | #include "symbol.h" | 8 | #include "symbol.h" |
| 9 | #include <strlist.h> | ||
| 9 | 10 | ||
| 10 | struct thread { | 11 | struct thread { |
| 11 | union { | 12 | union { |
| @@ -66,4 +67,15 @@ static inline void thread__set_priv(struct thread *thread, void *p) | |||
| 66 | { | 67 | { |
| 67 | thread->priv = p; | 68 | thread->priv = p; |
| 68 | } | 69 | } |
| 70 | |||
| 71 | static inline bool thread__is_filtered(struct thread *thread) | ||
| 72 | { | ||
| 73 | if (symbol_conf.comm_list && | ||
| 74 | !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) { | ||
| 75 | return true; | ||
| 76 | } | ||
| 77 | |||
| 78 | return false; | ||
| 79 | } | ||
| 80 | |||
| 69 | #endif /* __PERF_THREAD_H */ | 81 | #endif /* __PERF_THREAD_H */ |
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 9b5f856cc280..5d3215912105 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "strlist.h" | 9 | #include "strlist.h" |
| 10 | #include <string.h> | 10 | #include <string.h> |
| 11 | #include "thread_map.h" | 11 | #include "thread_map.h" |
| 12 | #include "util.h" | ||
| 12 | 13 | ||
| 13 | /* Skip "." and ".." directories */ | 14 | /* Skip "." and ".." directories */ |
| 14 | static int filter(const struct dirent *dir) | 15 | static int filter(const struct dirent *dir) |
| @@ -40,7 +41,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) | |||
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | for (i=0; i<items; i++) | 43 | for (i=0; i<items; i++) |
| 43 | free(namelist[i]); | 44 | zfree(&namelist[i]); |
| 44 | free(namelist); | 45 | free(namelist); |
| 45 | 46 | ||
| 46 | return threads; | 47 | return threads; |
| @@ -117,7 +118,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) | |||
| 117 | threads->map[threads->nr + i] = atoi(namelist[i]->d_name); | 118 | threads->map[threads->nr + i] = atoi(namelist[i]->d_name); |
| 118 | 119 | ||
| 119 | for (i = 0; i < items; i++) | 120 | for (i = 0; i < items; i++) |
| 120 | free(namelist[i]); | 121 | zfree(&namelist[i]); |
| 121 | free(namelist); | 122 | free(namelist); |
| 122 | 123 | ||
| 123 | threads->nr += items; | 124 | threads->nr += items; |
| @@ -134,12 +135,11 @@ out_free_threads: | |||
| 134 | 135 | ||
| 135 | out_free_namelist: | 136 | out_free_namelist: |
| 136 | for (i = 0; i < items; i++) | 137 | for (i = 0; i < items; i++) |
| 137 | free(namelist[i]); | 138 | zfree(&namelist[i]); |
| 138 | free(namelist); | 139 | free(namelist); |
| 139 | 140 | ||
| 140 | out_free_closedir: | 141 | out_free_closedir: |
| 141 | free(threads); | 142 | zfree(&threads); |
| 142 | threads = NULL; | ||
| 143 | goto out_closedir; | 143 | goto out_closedir; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -194,7 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) | |||
| 194 | 194 | ||
| 195 | for (i = 0; i < items; i++) { | 195 | for (i = 0; i < items; i++) { |
| 196 | threads->map[j++] = atoi(namelist[i]->d_name); | 196 | threads->map[j++] = atoi(namelist[i]->d_name); |
| 197 | free(namelist[i]); | 197 | zfree(&namelist[i]); |
| 198 | } | 198 | } |
| 199 | threads->nr = total_tasks; | 199 | threads->nr = total_tasks; |
| 200 | free(namelist); | 200 | free(namelist); |
| @@ -206,12 +206,11 @@ out: | |||
| 206 | 206 | ||
| 207 | out_free_namelist: | 207 | out_free_namelist: |
| 208 | for (i = 0; i < items; i++) | 208 | for (i = 0; i < items; i++) |
| 209 | free(namelist[i]); | 209 | zfree(&namelist[i]); |
| 210 | free(namelist); | 210 | free(namelist); |
| 211 | 211 | ||
| 212 | out_free_threads: | 212 | out_free_threads: |
| 213 | free(threads); | 213 | zfree(&threads); |
| 214 | threads = NULL; | ||
| 215 | goto out; | 214 | goto out; |
| 216 | } | 215 | } |
| 217 | 216 | ||
| @@ -262,8 +261,7 @@ out: | |||
| 262 | return threads; | 261 | return threads; |
| 263 | 262 | ||
| 264 | out_free_threads: | 263 | out_free_threads: |
| 265 | free(threads); | 264 | zfree(&threads); |
| 266 | threads = NULL; | ||
| 267 | goto out; | 265 | goto out; |
| 268 | } | 266 | } |
| 269 | 267 | ||
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index ce793c7dd23c..8e517def925b 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c | |||
| @@ -26,7 +26,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) | |||
| 26 | float samples_per_sec; | 26 | float samples_per_sec; |
| 27 | float ksamples_per_sec; | 27 | float ksamples_per_sec; |
| 28 | float esamples_percent; | 28 | float esamples_percent; |
| 29 | struct perf_record_opts *opts = &top->record_opts; | 29 | struct record_opts *opts = &top->record_opts; |
| 30 | struct target *target = &opts->target; | 30 | struct target *target = &opts->target; |
| 31 | size_t ret = 0; | 31 | size_t ret = 0; |
| 32 | 32 | ||
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 88cfeaff600b..dab14d0ad3d0 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h | |||
| @@ -14,7 +14,7 @@ struct perf_session; | |||
| 14 | struct perf_top { | 14 | struct perf_top { |
| 15 | struct perf_tool tool; | 15 | struct perf_tool tool; |
| 16 | struct perf_evlist *evlist; | 16 | struct perf_evlist *evlist; |
| 17 | struct perf_record_opts record_opts; | 17 | struct record_opts record_opts; |
| 18 | /* | 18 | /* |
| 19 | * Symbols will be added here in perf_event__process_sample and will | 19 | * Symbols will be added here in perf_event__process_sample and will |
| 20 | * get out after decayed. | 20 | * get out after decayed. |
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index f3c9e551bd35..7e6fcfe8b438 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #include "../perf.h" | 39 | #include "../perf.h" |
| 40 | #include "trace-event.h" | 40 | #include "trace-event.h" |
| 41 | #include <lk/debugfs.h> | 41 | #include <api/fs/debugfs.h> |
| 42 | #include "evsel.h" | 42 | #include "evsel.h" |
| 43 | 43 | ||
| 44 | #define VERSION "0.5" | 44 | #define VERSION "0.5" |
| @@ -397,8 +397,8 @@ put_tracepoints_path(struct tracepoint_path *tps) | |||
| 397 | struct tracepoint_path *t = tps; | 397 | struct tracepoint_path *t = tps; |
| 398 | 398 | ||
| 399 | tps = tps->next; | 399 | tps = tps->next; |
| 400 | free(t->name); | 400 | zfree(&t->name); |
| 401 | free(t->system); | 401 | zfree(&t->system); |
| 402 | free(t); | 402 | free(t); |
| 403 | } | 403 | } |
| 404 | } | 404 | } |
| @@ -562,10 +562,8 @@ out: | |||
| 562 | output_fd = fd; | 562 | output_fd = fd; |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | if (err) { | 565 | if (err) |
| 566 | free(tdata); | 566 | zfree(&tdata); |
| 567 | tdata = NULL; | ||
| 568 | } | ||
| 569 | 567 | ||
| 570 | put_tracepoints_path(tps); | 568 | put_tracepoints_path(tps); |
| 571 | return tdata; | 569 | return tdata; |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 6681f71f2f95..e0d6d07f6848 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
| @@ -28,19 +28,6 @@ | |||
| 28 | #include "util.h" | 28 | #include "util.h" |
| 29 | #include "trace-event.h" | 29 | #include "trace-event.h" |
| 30 | 30 | ||
| 31 | struct pevent *read_trace_init(int file_bigendian, int host_bigendian) | ||
| 32 | { | ||
| 33 | struct pevent *pevent = pevent_alloc(); | ||
| 34 | |||
| 35 | if (pevent != NULL) { | ||
| 36 | pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); | ||
| 37 | pevent_set_file_bigendian(pevent, file_bigendian); | ||
| 38 | pevent_set_host_bigendian(pevent, host_bigendian); | ||
| 39 | } | ||
| 40 | |||
| 41 | return pevent; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int get_common_field(struct scripting_context *context, | 31 | static int get_common_field(struct scripting_context *context, |
| 45 | int *offset, int *size, const char *type) | 32 | int *offset, int *size, const char *type) |
| 46 | { | 33 | { |
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index f2112270c663..e113e180c48f 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c | |||
| @@ -343,7 +343,7 @@ static int read_event_files(struct pevent *pevent) | |||
| 343 | return 0; | 343 | return 0; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | 346 | ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe) |
| 347 | { | 347 | { |
| 348 | char buf[BUFSIZ]; | 348 | char buf[BUFSIZ]; |
| 349 | char test[] = { 23, 8, 68 }; | 349 | char test[] = { 23, 8, 68 }; |
| @@ -356,11 +356,9 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | |||
| 356 | int host_bigendian; | 356 | int host_bigendian; |
| 357 | int file_long_size; | 357 | int file_long_size; |
| 358 | int file_page_size; | 358 | int file_page_size; |
| 359 | struct pevent *pevent; | 359 | struct pevent *pevent = NULL; |
| 360 | int err; | 360 | int err; |
| 361 | 361 | ||
| 362 | *ppevent = NULL; | ||
| 363 | |||
| 364 | repipe = __repipe; | 362 | repipe = __repipe; |
| 365 | input_fd = fd; | 363 | input_fd = fd; |
| 366 | 364 | ||
| @@ -390,12 +388,17 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | |||
| 390 | file_bigendian = buf[0]; | 388 | file_bigendian = buf[0]; |
| 391 | host_bigendian = bigendian(); | 389 | host_bigendian = bigendian(); |
| 392 | 390 | ||
| 393 | pevent = read_trace_init(file_bigendian, host_bigendian); | 391 | if (trace_event__init(tevent)) { |
| 394 | if (pevent == NULL) { | 392 | pr_debug("trace_event__init failed"); |
| 395 | pr_debug("read_trace_init failed"); | ||
| 396 | goto out; | 393 | goto out; |
| 397 | } | 394 | } |
| 398 | 395 | ||
| 396 | pevent = tevent->pevent; | ||
| 397 | |||
| 398 | pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); | ||
| 399 | pevent_set_file_bigendian(pevent, file_bigendian); | ||
| 400 | pevent_set_host_bigendian(pevent, host_bigendian); | ||
| 401 | |||
| 399 | if (do_read(buf, 1) < 0) | 402 | if (do_read(buf, 1) < 0) |
| 400 | goto out; | 403 | goto out; |
| 401 | file_long_size = buf[0]; | 404 | file_long_size = buf[0]; |
| @@ -432,11 +435,10 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | |||
| 432 | pevent_print_printk(pevent); | 435 | pevent_print_printk(pevent); |
| 433 | } | 436 | } |
| 434 | 437 | ||
| 435 | *ppevent = pevent; | ||
| 436 | pevent = NULL; | 438 | pevent = NULL; |
| 437 | 439 | ||
| 438 | out: | 440 | out: |
| 439 | if (pevent) | 441 | if (pevent) |
| 440 | pevent_free(pevent); | 442 | trace_event__cleanup(tevent); |
| 441 | return size; | 443 | return size; |
| 442 | } | 444 | } |
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 95199e4eea97..57aaccc1692e 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c | |||
| @@ -38,9 +38,8 @@ static int stop_script_unsupported(void) | |||
| 38 | static void process_event_unsupported(union perf_event *event __maybe_unused, | 38 | static void process_event_unsupported(union perf_event *event __maybe_unused, |
| 39 | struct perf_sample *sample __maybe_unused, | 39 | struct perf_sample *sample __maybe_unused, |
| 40 | struct perf_evsel *evsel __maybe_unused, | 40 | struct perf_evsel *evsel __maybe_unused, |
| 41 | struct machine *machine __maybe_unused, | ||
| 42 | struct thread *thread __maybe_unused, | 41 | struct thread *thread __maybe_unused, |
| 43 | struct addr_location *al __maybe_unused) | 42 | struct addr_location *al __maybe_unused) |
| 44 | { | 43 | { |
| 45 | } | 44 | } |
| 46 | 45 | ||
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c new file mode 100644 index 000000000000..6322d37164c5 --- /dev/null +++ b/tools/perf/util/trace-event.c | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | |||
| 2 | #include <stdio.h> | ||
| 3 | #include <unistd.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <errno.h> | ||
| 6 | #include <sys/types.h> | ||
| 7 | #include <sys/stat.h> | ||
| 8 | #include <fcntl.h> | ||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <traceevent/event-parse.h> | ||
| 11 | #include "trace-event.h" | ||
| 12 | #include "util.h" | ||
| 13 | |||
| 14 | /* | ||
| 15 | * global trace_event object used by trace_event__tp_format | ||
| 16 | * | ||
| 17 | * TODO There's no cleanup call for this. Add some sort of | ||
| 18 | * __exit function support and call trace_event__cleanup | ||
| 19 | * there. | ||
| 20 | */ | ||
| 21 | static struct trace_event tevent; | ||
| 22 | |||
| 23 | int trace_event__init(struct trace_event *t) | ||
| 24 | { | ||
| 25 | struct pevent *pevent = pevent_alloc(); | ||
| 26 | |||
| 27 | if (pevent) { | ||
| 28 | t->plugin_list = traceevent_load_plugins(pevent); | ||
| 29 | t->pevent = pevent; | ||
| 30 | } | ||
| 31 | |||
| 32 | return pevent ? 0 : -1; | ||
| 33 | } | ||
| 34 | |||
| 35 | void trace_event__cleanup(struct trace_event *t) | ||
| 36 | { | ||
| 37 | traceevent_unload_plugins(t->plugin_list, t->pevent); | ||
| 38 | pevent_free(t->pevent); | ||
| 39 | } | ||
| 40 | |||
| 41 | static struct event_format* | ||
| 42 | tp_format(const char *sys, const char *name) | ||
| 43 | { | ||
| 44 | struct pevent *pevent = tevent.pevent; | ||
| 45 | struct event_format *event = NULL; | ||
| 46 | char path[PATH_MAX]; | ||
| 47 | size_t size; | ||
| 48 | char *data; | ||
| 49 | |||
| 50 | scnprintf(path, PATH_MAX, "%s/%s/%s/format", | ||
| 51 | tracing_events_path, sys, name); | ||
| 52 | |||
| 53 | if (filename__read_str(path, &data, &size)) | ||
| 54 | return NULL; | ||
| 55 | |||
| 56 | pevent_parse_format(pevent, &event, data, size, sys); | ||
| 57 | |||
| 58 | free(data); | ||
| 59 | return event; | ||
| 60 | } | ||
| 61 | |||
| 62 | struct event_format* | ||
| 63 | trace_event__tp_format(const char *sys, const char *name) | ||
| 64 | { | ||
| 65 | static bool initialized; | ||
| 66 | |||
| 67 | if (!initialized) { | ||
| 68 | int be = traceevent_host_bigendian(); | ||
| 69 | struct pevent *pevent; | ||
| 70 | |||
| 71 | if (trace_event__init(&tevent)) | ||
| 72 | return NULL; | ||
| 73 | |||
| 74 | pevent = tevent.pevent; | ||
| 75 | pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); | ||
| 76 | pevent_set_file_bigendian(pevent, be); | ||
| 77 | pevent_set_host_bigendian(pevent, be); | ||
| 78 | initialized = true; | ||
| 79 | } | ||
| 80 | |||
| 81 | return tp_format(sys, name); | ||
| 82 | } | ||
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 04df63114109..7b6d68688327 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
| @@ -3,17 +3,26 @@ | |||
| 3 | 3 | ||
| 4 | #include <traceevent/event-parse.h> | 4 | #include <traceevent/event-parse.h> |
| 5 | #include "parse-events.h" | 5 | #include "parse-events.h" |
| 6 | #include "session.h" | ||
| 7 | 6 | ||
| 8 | struct machine; | 7 | struct machine; |
| 9 | struct perf_sample; | 8 | struct perf_sample; |
| 10 | union perf_event; | 9 | union perf_event; |
| 11 | struct perf_tool; | 10 | struct perf_tool; |
| 12 | struct thread; | 11 | struct thread; |
| 12 | struct plugin_list; | ||
| 13 | |||
| 14 | struct trace_event { | ||
| 15 | struct pevent *pevent; | ||
| 16 | struct plugin_list *plugin_list; | ||
| 17 | }; | ||
| 18 | |||
| 19 | int trace_event__init(struct trace_event *t); | ||
| 20 | void trace_event__cleanup(struct trace_event *t); | ||
| 21 | struct event_format* | ||
| 22 | trace_event__tp_format(const char *sys, const char *name); | ||
| 13 | 23 | ||
| 14 | int bigendian(void); | 24 | int bigendian(void); |
| 15 | 25 | ||
| 16 | struct pevent *read_trace_init(int file_bigendian, int host_bigendian); | ||
| 17 | void event_format__print(struct event_format *event, | 26 | void event_format__print(struct event_format *event, |
| 18 | int cpu, void *data, int size); | 27 | int cpu, void *data, int size); |
| 19 | 28 | ||
| @@ -27,7 +36,7 @@ raw_field_value(struct event_format *event, const char *name, void *data); | |||
| 27 | void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); | 36 | void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); |
| 28 | void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); | 37 | void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); |
| 29 | 38 | ||
| 30 | ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); | 39 | ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); |
| 31 | 40 | ||
| 32 | struct event_format *trace_find_next_event(struct pevent *pevent, | 41 | struct event_format *trace_find_next_event(struct pevent *pevent, |
| 33 | struct event_format *event); | 42 | struct event_format *event); |
| @@ -59,7 +68,6 @@ struct scripting_ops { | |||
| 59 | void (*process_event) (union perf_event *event, | 68 | void (*process_event) (union perf_event *event, |
| 60 | struct perf_sample *sample, | 69 | struct perf_sample *sample, |
| 61 | struct perf_evsel *evsel, | 70 | struct perf_evsel *evsel, |
| 62 | struct machine *machine, | ||
| 63 | struct thread *thread, | 71 | struct thread *thread, |
| 64 | struct addr_location *al); | 72 | struct addr_location *al); |
| 65 | int (*generate_script) (struct pevent *pevent, const char *outfile); | 73 | int (*generate_script) (struct pevent *pevent, const char *outfile); |
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index 0efd5393de85..742f23bf35ff 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "session.h" | 28 | #include "session.h" |
| 29 | #include "perf_regs.h" | 29 | #include "perf_regs.h" |
| 30 | #include "unwind.h" | 30 | #include "unwind.h" |
| 31 | #include "symbol.h" | ||
| 31 | #include "util.h" | 32 | #include "util.h" |
| 32 | 33 | ||
| 33 | extern int | 34 | extern int |
| @@ -158,23 +159,6 @@ static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, | |||
| 158 | __v; \ | 159 | __v; \ |
| 159 | }) | 160 | }) |
| 160 | 161 | ||
| 161 | static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | ||
| 162 | GElf_Shdr *shp, const char *name) | ||
| 163 | { | ||
| 164 | Elf_Scn *sec = NULL; | ||
| 165 | |||
| 166 | while ((sec = elf_nextscn(elf, sec)) != NULL) { | ||
| 167 | char *str; | ||
| 168 | |||
| 169 | gelf_getshdr(sec, shp); | ||
| 170 | str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); | ||
| 171 | if (!strcmp(name, str)) | ||
| 172 | break; | ||
| 173 | } | ||
| 174 | |||
| 175 | return sec; | ||
| 176 | } | ||
| 177 | |||
| 178 | static u64 elf_section_offset(int fd, const char *name) | 162 | static u64 elf_section_offset(int fd, const char *name) |
| 179 | { | 163 | { |
| 180 | Elf *elf; | 164 | Elf *elf; |
| @@ -190,7 +174,7 @@ static u64 elf_section_offset(int fd, const char *name) | |||
| 190 | if (gelf_getehdr(elf, &ehdr) == NULL) | 174 | if (gelf_getehdr(elf, &ehdr) == NULL) |
| 191 | break; | 175 | break; |
| 192 | 176 | ||
| 193 | if (!elf_section_by_name(elf, &ehdr, &shdr, name)) | 177 | if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL)) |
| 194 | break; | 178 | break; |
| 195 | 179 | ||
| 196 | offset = shdr.sh_offset; | 180 | offset = shdr.sh_offset; |
| @@ -340,10 +324,10 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
| 340 | /* Check the .debug_frame section for unwinding info */ | 324 | /* Check the .debug_frame section for unwinding info */ |
| 341 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | 325 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { |
| 342 | memset(&di, 0, sizeof(di)); | 326 | memset(&di, 0, sizeof(di)); |
| 343 | dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, | 327 | if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, |
| 344 | map->start, map->end); | 328 | map->start, map->end)) |
| 345 | return dwarf_search_unwind_table(as, ip, &di, pi, | 329 | return dwarf_search_unwind_table(as, ip, &di, pi, |
| 346 | need_unwind_info, arg); | 330 | need_unwind_info, arg); |
| 347 | } | 331 | } |
| 348 | #endif | 332 | #endif |
| 349 | 333 | ||
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 28a0a89c1f73..42ad667bb317 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
| @@ -1,11 +1,17 @@ | |||
| 1 | #include "../perf.h" | 1 | #include "../perf.h" |
| 2 | #include "util.h" | 2 | #include "util.h" |
| 3 | #include "fs.h" | ||
| 3 | #include <sys/mman.h> | 4 | #include <sys/mman.h> |
| 4 | #ifdef HAVE_BACKTRACE_SUPPORT | 5 | #ifdef HAVE_BACKTRACE_SUPPORT |
| 5 | #include <execinfo.h> | 6 | #include <execinfo.h> |
| 6 | #endif | 7 | #endif |
| 7 | #include <stdio.h> | 8 | #include <stdio.h> |
| 8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 10 | #include <string.h> | ||
| 11 | #include <errno.h> | ||
| 12 | #include <limits.h> | ||
| 13 | #include <byteswap.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 9 | 15 | ||
| 10 | /* | 16 | /* |
| 11 | * XXX We need to find a better place for these things... | 17 | * XXX We need to find a better place for these things... |
| @@ -151,21 +157,40 @@ unsigned long convert_unit(unsigned long value, char *unit) | |||
| 151 | return value; | 157 | return value; |
| 152 | } | 158 | } |
| 153 | 159 | ||
| 154 | int readn(int fd, void *buf, size_t n) | 160 | static ssize_t ion(bool is_read, int fd, void *buf, size_t n) |
| 155 | { | 161 | { |
| 156 | void *buf_start = buf; | 162 | void *buf_start = buf; |
| 163 | size_t left = n; | ||
| 157 | 164 | ||
| 158 | while (n) { | 165 | while (left) { |
| 159 | int ret = read(fd, buf, n); | 166 | ssize_t ret = is_read ? read(fd, buf, left) : |
| 167 | write(fd, buf, left); | ||
| 160 | 168 | ||
| 161 | if (ret <= 0) | 169 | if (ret <= 0) |
| 162 | return ret; | 170 | return ret; |
| 163 | 171 | ||
| 164 | n -= ret; | 172 | left -= ret; |
| 165 | buf += ret; | 173 | buf += ret; |
| 166 | } | 174 | } |
| 167 | 175 | ||
| 168 | return buf - buf_start; | 176 | BUG_ON((size_t)(buf - buf_start) != n); |
| 177 | return n; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* | ||
| 181 | * Read exactly 'n' bytes or return an error. | ||
| 182 | */ | ||
| 183 | ssize_t readn(int fd, void *buf, size_t n) | ||
| 184 | { | ||
| 185 | return ion(true, fd, buf, n); | ||
| 186 | } | ||
| 187 | |||
| 188 | /* | ||
| 189 | * Write exactly 'n' bytes or return an error. | ||
| 190 | */ | ||
| 191 | ssize_t writen(int fd, void *buf, size_t n) | ||
| 192 | { | ||
| 193 | return ion(false, fd, buf, n); | ||
| 169 | } | 194 | } |
| 170 | 195 | ||
| 171 | size_t hex_width(u64 v) | 196 | size_t hex_width(u64 v) |
| @@ -413,3 +438,102 @@ int filename__read_int(const char *filename, int *value) | |||
| 413 | close(fd); | 438 | close(fd); |
| 414 | return err; | 439 | return err; |
| 415 | } | 440 | } |
| 441 | |||
| 442 | int filename__read_str(const char *filename, char **buf, size_t *sizep) | ||
| 443 | { | ||
| 444 | size_t size = 0, alloc_size = 0; | ||
| 445 | void *bf = NULL, *nbf; | ||
| 446 | int fd, n, err = 0; | ||
| 447 | |||
| 448 | fd = open(filename, O_RDONLY); | ||
| 449 | if (fd < 0) | ||
| 450 | return -errno; | ||
| 451 | |||
| 452 | do { | ||
| 453 | if (size == alloc_size) { | ||
| 454 | alloc_size += BUFSIZ; | ||
| 455 | nbf = realloc(bf, alloc_size); | ||
| 456 | if (!nbf) { | ||
| 457 | err = -ENOMEM; | ||
| 458 | break; | ||
| 459 | } | ||
| 460 | |||
| 461 | bf = nbf; | ||
| 462 | } | ||
| 463 | |||
| 464 | n = read(fd, bf + size, alloc_size - size); | ||
| 465 | if (n < 0) { | ||
| 466 | if (size) { | ||
| 467 | pr_warning("read failed %d: %s\n", | ||
| 468 | errno, strerror(errno)); | ||
| 469 | err = 0; | ||
| 470 | } else | ||
| 471 | err = -errno; | ||
| 472 | |||
| 473 | break; | ||
| 474 | } | ||
| 475 | |||
| 476 | size += n; | ||
| 477 | } while (n > 0); | ||
| 478 | |||
| 479 | if (!err) { | ||
| 480 | *sizep = size; | ||
| 481 | *buf = bf; | ||
| 482 | } else | ||
| 483 | free(bf); | ||
| 484 | |||
| 485 | close(fd); | ||
| 486 | return err; | ||
| 487 | } | ||
| 488 | |||
| 489 | const char *get_filename_for_perf_kvm(void) | ||
| 490 | { | ||
| 491 | const char *filename; | ||
| 492 | |||
| 493 | if (perf_host && !perf_guest) | ||
| 494 | filename = strdup("perf.data.host"); | ||
| 495 | else if (!perf_host && perf_guest) | ||
| 496 | filename = strdup("perf.data.guest"); | ||
| 497 | else | ||
| 498 | filename = strdup("perf.data.kvm"); | ||
| 499 | |||
| 500 | return filename; | ||
| 501 | } | ||
| 502 | |||
| 503 | int perf_event_paranoid(void) | ||
| 504 | { | ||
| 505 | char path[PATH_MAX]; | ||
| 506 | const char *procfs = procfs__mountpoint(); | ||
| 507 | int value; | ||
| 508 | |||
| 509 | if (!procfs) | ||
| 510 | return INT_MAX; | ||
| 511 | |||
| 512 | scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); | ||
| 513 | |||
| 514 | if (filename__read_int(path, &value)) | ||
| 515 | return INT_MAX; | ||
| 516 | |||
| 517 | return value; | ||
| 518 | } | ||
| 519 | |||
| 520 | void mem_bswap_32(void *src, int byte_size) | ||
| 521 | { | ||
| 522 | u32 *m = src; | ||
| 523 | while (byte_size > 0) { | ||
| 524 | *m = bswap_32(*m); | ||
| 525 | byte_size -= sizeof(u32); | ||
| 526 | ++m; | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | void mem_bswap_64(void *src, int byte_size) | ||
| 531 | { | ||
| 532 | u64 *m = src; | ||
| 533 | |||
| 534 | while (byte_size > 0) { | ||
| 535 | *m = bswap_64(*m); | ||
| 536 | byte_size -= sizeof(u64); | ||
| 537 | ++m; | ||
| 538 | } | ||
| 539 | } | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index c8f362daba87..6995d66f225c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
| @@ -71,8 +71,9 @@ | |||
| 71 | #include <linux/magic.h> | 71 | #include <linux/magic.h> |
| 72 | #include "types.h" | 72 | #include "types.h" |
| 73 | #include <sys/ttydefaults.h> | 73 | #include <sys/ttydefaults.h> |
| 74 | #include <lk/debugfs.h> | 74 | #include <api/fs/debugfs.h> |
| 75 | #include <termios.h> | 75 | #include <termios.h> |
| 76 | #include <linux/bitops.h> | ||
| 76 | 77 | ||
| 77 | extern const char *graph_line; | 78 | extern const char *graph_line; |
| 78 | extern const char *graph_dotted_line; | 79 | extern const char *graph_dotted_line; |
| @@ -185,6 +186,8 @@ static inline void *zalloc(size_t size) | |||
| 185 | return calloc(1, size); | 186 | return calloc(1, size); |
| 186 | } | 187 | } |
| 187 | 188 | ||
| 189 | #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) | ||
| 190 | |||
| 188 | static inline int has_extension(const char *filename, const char *ext) | 191 | static inline int has_extension(const char *filename, const char *ext) |
| 189 | { | 192 | { |
| 190 | size_t len = strlen(filename); | 193 | size_t len = strlen(filename); |
| @@ -253,7 +256,8 @@ bool strlazymatch(const char *str, const char *pat); | |||
| 253 | int strtailcmp(const char *s1, const char *s2); | 256 | int strtailcmp(const char *s1, const char *s2); |
| 254 | char *strxfrchar(char *s, char from, char to); | 257 | char *strxfrchar(char *s, char from, char to); |
| 255 | unsigned long convert_unit(unsigned long value, char *unit); | 258 | unsigned long convert_unit(unsigned long value, char *unit); |
| 256 | int readn(int fd, void *buf, size_t size); | 259 | ssize_t readn(int fd, void *buf, size_t n); |
| 260 | ssize_t writen(int fd, void *buf, size_t n); | ||
| 257 | 261 | ||
| 258 | struct perf_event_attr; | 262 | struct perf_event_attr; |
| 259 | 263 | ||
| @@ -280,6 +284,17 @@ static inline unsigned next_pow2(unsigned x) | |||
| 280 | return 1ULL << (32 - __builtin_clz(x - 1)); | 284 | return 1ULL << (32 - __builtin_clz(x - 1)); |
| 281 | } | 285 | } |
| 282 | 286 | ||
| 287 | static inline unsigned long next_pow2_l(unsigned long x) | ||
| 288 | { | ||
| 289 | #if BITS_PER_LONG == 64 | ||
| 290 | if (x <= (1UL << 31)) | ||
| 291 | return next_pow2(x); | ||
| 292 | return (unsigned long)next_pow2(x >> 32) << 32; | ||
| 293 | #else | ||
| 294 | return next_pow2(x); | ||
| 295 | #endif | ||
| 296 | } | ||
| 297 | |||
| 283 | size_t hex_width(u64 v); | 298 | size_t hex_width(u64 v); |
| 284 | int hex2u64(const char *ptr, u64 *val); | 299 | int hex2u64(const char *ptr, u64 *val); |
| 285 | 300 | ||
| @@ -307,4 +322,11 @@ char *get_srcline(struct dso *dso, unsigned long addr); | |||
| 307 | void free_srcline(char *srcline); | 322 | void free_srcline(char *srcline); |
| 308 | 323 | ||
| 309 | int filename__read_int(const char *filename, int *value); | 324 | int filename__read_int(const char *filename, int *value); |
| 325 | int filename__read_str(const char *filename, char **buf, size_t *sizep); | ||
| 326 | int perf_event_paranoid(void); | ||
| 327 | |||
| 328 | void mem_bswap_64(void *src, int byte_size); | ||
| 329 | void mem_bswap_32(void *src, int byte_size); | ||
| 330 | |||
| 331 | const char *get_filename_for_perf_kvm(void); | ||
| 310 | #endif /* GIT_COMPAT_UTIL_H */ | 332 | #endif /* GIT_COMPAT_UTIL_H */ |
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c index 697c8b4e59cc..0fb3c1fcd3e6 100644 --- a/tools/perf/util/values.c +++ b/tools/perf/util/values.c | |||
| @@ -31,14 +31,14 @@ void perf_read_values_destroy(struct perf_read_values *values) | |||
| 31 | return; | 31 | return; |
| 32 | 32 | ||
| 33 | for (i = 0; i < values->threads; i++) | 33 | for (i = 0; i < values->threads; i++) |
| 34 | free(values->value[i]); | 34 | zfree(&values->value[i]); |
| 35 | free(values->value); | 35 | zfree(&values->value); |
| 36 | free(values->pid); | 36 | zfree(&values->pid); |
| 37 | free(values->tid); | 37 | zfree(&values->tid); |
| 38 | free(values->counterrawid); | 38 | zfree(&values->counterrawid); |
| 39 | for (i = 0; i < values->counters; i++) | 39 | for (i = 0; i < values->counters; i++) |
| 40 | free(values->countername[i]); | 40 | zfree(&values->countername[i]); |
| 41 | free(values->countername); | 41 | zfree(&values->countername); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static void perf_read_values__enlarge_threads(struct perf_read_values *values) | 44 | static void perf_read_values__enlarge_threads(struct perf_read_values *values) |
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 39159822d58f..0ddb3b8a89ec 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c | |||
| @@ -103,7 +103,7 @@ struct dso *vdso__dso_findnew(struct list_head *head) | |||
| 103 | dso = dso__new(VDSO__MAP_NAME); | 103 | dso = dso__new(VDSO__MAP_NAME); |
| 104 | if (dso != NULL) { | 104 | if (dso != NULL) { |
| 105 | dsos__add(head, dso); | 105 | dsos__add(head, dso); |
| 106 | dso__set_long_name(dso, file); | 106 | dso__set_long_name(dso, file, false); |
| 107 | } | 107 | } |
| 108 | } | 108 | } |
| 109 | 109 | ||
