aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/alias.c6
-rw-r--r--tools/perf/util/annotate.c82
-rw-r--r--tools/perf/util/annotate.h11
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/callchain.c46
-rw-r--r--tools/perf/util/callchain.h8
-rw-r--r--tools/perf/util/cgroup.c6
-rw-r--r--tools/perf/util/color.c15
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c21
-rw-r--r--tools/perf/util/comm.h2
-rw-r--r--tools/perf/util/data.c6
-rw-r--r--tools/perf/util/data.h14
-rw-r--r--tools/perf/util/debug.c31
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/dso.c134
-rw-r--r--tools/perf/util/dso.h31
-rw-r--r--tools/perf/util/event.c97
-rw-r--r--tools/perf/util/event.h13
-rw-r--r--tools/perf/util/evlist.c128
-rw-r--r--tools/perf/util/evlist.h81
-rw-r--r--tools/perf/util/evsel.c76
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/header.c71
-rw-r--r--tools/perf/util/header.h10
-rw-r--r--tools/perf/util/help.c7
-rw-r--r--tools/perf/util/hist.c49
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/include/asm/bug.h22
-rw-r--r--tools/perf/util/include/asm/hash.h6
-rw-r--r--tools/perf/util/include/linux/bitops.h4
-rw-r--r--tools/perf/util/include/linux/compiler.h30
-rw-r--r--tools/perf/util/machine.c70
-rw-r--r--tools/perf/util/machine.h2
-rw-r--r--tools/perf/util/map.c29
-rw-r--r--tools/perf/util/map.h3
-rw-r--r--tools/perf/util/parse-events.c60
-rw-r--r--tools/perf/util/parse-options.c21
-rw-r--r--tools/perf/util/parse-options.h8
-rw-r--r--tools/perf/util/pmu.c158
-rw-r--r--tools/perf/util/pmu.h3
-rw-r--r--tools/perf/util/probe-event.c258
-rw-r--r--tools/perf/util/probe-event.h7
-rw-r--r--tools/perf/util/probe-finder.c33
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/python.c3
-rw-r--r--tools/perf/util/record.c52
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c22
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c28
-rw-r--r--tools/perf/util/session.c126
-rw-r--r--tools/perf/util/session.h10
-rw-r--r--tools/perf/util/setup.py4
-rw-r--r--tools/perf/util/sort.c22
-rw-r--r--tools/perf/util/srcline.c72
-rw-r--r--tools/perf/util/strbuf.c2
-rw-r--r--tools/perf/util/strfilter.c2
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/strlist.c3
-rw-r--r--tools/perf/util/svghelper.c235
-rw-r--r--tools/perf/util/svghelper.h17
-rw-r--r--tools/perf/util/symbol-elf.c18
-rw-r--r--tools/perf/util/symbol-minimal.c4
-rw-r--r--tools/perf/util/symbol.c232
-rw-r--r--tools/perf/util/symbol.h16
-rw-r--r--tools/perf/util/target.c11
-rw-r--r--tools/perf/util/target.h17
-rw-r--r--tools/perf/util/thread.c7
-rw-r--r--tools/perf/util/thread.h12
-rw-r--r--tools/perf/util/thread_map.c20
-rw-r--r--tools/perf/util/top.c2
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/trace-event-info.c12
-rw-r--r--tools/perf/util/trace-event-parse.c13
-rw-r--r--tools/perf/util/trace-event-read.c20
-rw-r--r--tools/perf/util/trace-event-scripting.c3
-rw-r--r--tools/perf/util/trace-event.c82
-rw-r--r--tools/perf/util/trace-event.h16
-rw-r--r--tools/perf/util/unwind.c28
-rw-r--r--tools/perf/util/util.c136
-rw-r--r--tools/perf/util/util.h26
-rw-r--r--tools/perf/util/values.c14
-rw-r--r--tools/perf/util/vdso.c2
83 files changed, 2022 insertions, 948 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..3aa555ff9d89 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -8,6 +8,8 @@
8 */ 8 */
9 9
10#include "util.h" 10#include "util.h"
11#include "ui/ui.h"
12#include "sort.h"
11#include "build-id.h" 13#include "build-id.h"
12#include "color.h" 14#include "color.h"
13#include "cache.h" 15#include "cache.h"
@@ -26,10 +28,10 @@ static int disasm_line__parse(char *line, char **namep, char **rawp);
26 28
27static void ins__delete(struct ins_operands *ops) 29static void ins__delete(struct ins_operands *ops)
28{ 30{
29 free(ops->source.raw); 31 zfree(&ops->source.raw);
30 free(ops->source.name); 32 zfree(&ops->source.name);
31 free(ops->target.raw); 33 zfree(&ops->target.raw);
32 free(ops->target.name); 34 zfree(&ops->target.name);
33} 35}
34 36
35static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, 37static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
@@ -185,8 +187,7 @@ static int lock__parse(struct ins_operands *ops)
185 return 0; 187 return 0;
186 188
187out_free_ops: 189out_free_ops:
188 free(ops->locked.ops); 190 zfree(&ops->locked.ops);
189 ops->locked.ops = NULL;
190 return 0; 191 return 0;
191} 192}
192 193
@@ -205,9 +206,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
205 206
206static void lock__delete(struct ins_operands *ops) 207static void lock__delete(struct ins_operands *ops)
207{ 208{
208 free(ops->locked.ops); 209 zfree(&ops->locked.ops);
209 free(ops->target.raw); 210 zfree(&ops->target.raw);
210 free(ops->target.name); 211 zfree(&ops->target.name);
211} 212}
212 213
213static struct ins_ops lock_ops = { 214static struct ins_ops lock_ops = {
@@ -256,8 +257,7 @@ static int mov__parse(struct ins_operands *ops)
256 return 0; 257 return 0;
257 258
258out_free_source: 259out_free_source:
259 free(ops->source.raw); 260 zfree(&ops->source.raw);
260 ops->source.raw = NULL;
261 return -1; 261 return -1;
262} 262}
263 263
@@ -464,17 +464,12 @@ void symbol__annotate_zero_histograms(struct symbol *sym)
464 pthread_mutex_unlock(&notes->lock); 464 pthread_mutex_unlock(&notes->lock);
465} 465}
466 466
467int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 467static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
468 int evidx, u64 addr) 468 struct annotation *notes, int evidx, u64 addr)
469{ 469{
470 unsigned offset; 470 unsigned offset;
471 struct annotation *notes;
472 struct sym_hist *h; 471 struct sym_hist *h;
473 472
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)); 473 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
479 474
480 if (addr < sym->start || addr > sym->end) 475 if (addr < sym->start || addr > sym->end)
@@ -491,6 +486,33 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
491 return 0; 486 return 0;
492} 487}
493 488
489static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
490 int evidx, u64 addr)
491{
492 struct annotation *notes;
493
494 if (sym == NULL)
495 return 0;
496
497 notes = symbol__annotation(sym);
498 if (notes->src == NULL) {
499 if (symbol__alloc_hist(sym) < 0)
500 return -ENOMEM;
501 }
502
503 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
504}
505
506int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
507{
508 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
509}
510
511int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
512{
513 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
514}
515
494static void disasm_line__init_ins(struct disasm_line *dl) 516static void disasm_line__init_ins(struct disasm_line *dl)
495{ 517{
496 dl->ins = ins__find(dl->name); 518 dl->ins = ins__find(dl->name);
@@ -538,8 +560,7 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)
538 return 0; 560 return 0;
539 561
540out_free_name: 562out_free_name:
541 free(*namep); 563 zfree(namep);
542 *namep = NULL;
543 return -1; 564 return -1;
544} 565}
545 566
@@ -564,7 +585,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs
564 return dl; 585 return dl;
565 586
566out_free_line: 587out_free_line:
567 free(dl->line); 588 zfree(&dl->line);
568out_delete: 589out_delete:
569 free(dl); 590 free(dl);
570 return NULL; 591 return NULL;
@@ -572,8 +593,8 @@ out_delete:
572 593
573void disasm_line__free(struct disasm_line *dl) 594void disasm_line__free(struct disasm_line *dl)
574{ 595{
575 free(dl->line); 596 zfree(&dl->line);
576 free(dl->name); 597 zfree(&dl->name);
577 if (dl->ins && dl->ins->ops->free) 598 if (dl->ins && dl->ins->ops->free)
578 dl->ins->ops->free(&dl->ops); 599 dl->ins->ops->free(&dl->ops);
579 else 600 else
@@ -900,7 +921,7 @@ fallback:
900 * cache, or is just a kallsyms file, well, lets hope that this 921 * cache, or is just a kallsyms file, well, lets hope that this
901 * DSO is the same as when 'perf record' ran. 922 * DSO is the same as when 'perf record' ran.
902 */ 923 */
903 filename = dso->long_name; 924 filename = (char *)dso->long_name;
904 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 925 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
905 symbol_conf.symfs, filename); 926 symbol_conf.symfs, filename);
906 free_filename = false; 927 free_filename = false;
@@ -1091,8 +1112,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1091 src_line = (void *)src_line + sizeof_src_line; 1112 src_line = (void *)src_line + sizeof_src_line;
1092 } 1113 }
1093 1114
1094 free(notes->src->lines); 1115 zfree(&notes->src->lines);
1095 notes->src->lines = NULL;
1096} 1116}
1097 1117
1098/* Get the filename:line for the colored entries */ 1118/* Get the filename:line for the colored entries */
@@ -1376,3 +1396,13 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1376 1396
1377 return 0; 1397 return 0;
1378} 1398}
1399
1400int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1401{
1402 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1403}
1404
1405bool ui__has_annotation(void)
1406{
1407 return use_browser == 1 && sort__has_sym;
1408}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 834b7b57b788..56ad4f5287de 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
135int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 135int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx);
136 int evidx, u64 addr); 136
137int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
138
137int symbol__alloc_hist(struct symbol *sym); 139int symbol__alloc_hist(struct symbol *sym);
138void symbol__annotate_zero_histograms(struct symbol *sym); 140void symbol__annotate_zero_histograms(struct symbol *sym);
139 141
140int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 142int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
143
144int hist_entry__annotate(struct hist_entry *he, size_t privsize);
145
141int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); 146int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym);
142int symbol__annotate_printf(struct symbol *sym, struct map *map, 147int 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,
@@ -146,6 +151,8 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
146void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 151void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
147void disasm__purge(struct list_head *head); 152void disasm__purge(struct list_head *head);
148 153
154bool ui__has_annotation(void);
155
149int symbol__tty_annotate(struct symbol *sym, struct map *map, 156int symbol__tty_annotate(struct symbol *sym, struct map *map,
150 struct perf_evsel *evsel, bool print_lines, 157 struct perf_evsel *evsel, bool print_lines,
151 bool full_paths, int min_pcnt, int max_lines); 158 bool full_paths, int min_pcnt, int max_lines);
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
92char *dso__build_id_filename(struct dso *dso, char *bf, size_t size) 92char *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;
10struct dso; 10struct dso;
11 11
12int build_id__sprintf(const u8 *build_id, int len, char *bf); 12int build_id__sprintf(const u8 *build_id, int len, char *bf);
13char *dso__build_id_filename(struct dso *dso, char *bf, size_t size); 13char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
14 14
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int 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
534int 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
548int 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
147struct option; 147struct option;
148struct hist_entry;
148 149
149int record_parse_callchain(const char *arg, struct perf_record_opts *opts); 150int record_parse_callchain(const char *arg, struct record_opts *opts);
150int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 151int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
151int record_callchain_opt(const struct option *opt, const char *arg, int unset); 152int record_callchain_opt(const struct option *opt, const char *arg, int unset);
152 153
154int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
155 struct perf_evsel *evsel, struct addr_location *al,
156 int max_stack);
157int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
158
153extern const char record_callchain_help[]; 159extern 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
5int perf_use_color_default = -1; 6int 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
322int 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
321int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 328int 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, ...);
39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); 39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
42int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
43int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 44int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
44const char *get_percent_color(double percent); 45const 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
97void comm__override(struct comm *comm, const char *str, u64 timestamp) 97int 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
112void comm__free(struct comm *comm) 113void 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 {
16void comm__free(struct comm *comm); 16void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 17struct comm *comm__new(const char *str, u64 timestamp);
18const char *comm__str(const struct comm *comm); 18const char *comm__str(const struct comm *comm);
19void comm__override(struct comm *comm, const char *str, u64 timestamp); 19int 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
122ssize_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
11struct perf_data_file { 11struct 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
20static inline bool perf_data_file__is_read(struct perf_data_file *file) 20static 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
45int perf_data_file__open(struct perf_data_file *file); 45int perf_data_file__open(struct perf_data_file *file);
46void perf_data_file__close(struct perf_data_file *file); 46void perf_data_file__close(struct perf_data_file *file);
47ssize_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 @@
16int verbose; 16int verbose;
17bool dump_trace = false, quiet = false; 17bool dump_trace = false, quiet = false;
18 18
19int eprintf(int level, const char *fmt, ...) 19static 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
33int 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 */
49void 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
36int dump_printf(const char *fmt, ...) 59int 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);
17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
19 19
20void 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
31int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, 31int 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
138static int open_dso(struct dso *dso, struct machine *machine) 139static 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
162int dso__data_fd(struct dso *dso, struct machine *machine) 162int 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
203static struct dso_cache* 203static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
204dso_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
389void dso__set_long_name(struct dso *dso, char *name) 388void 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
397void dso__set_short_name(struct dso *dso, const char *name) 401void 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
405static void dso__set_basename(struct dso *dso) 414static 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
410int dso__name_len(const struct dso *dso) 440int 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
546struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short) 586struct 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)
107struct dso *dso__new(const char *name); 110struct dso *dso__new(const char *name);
108void dso__delete(struct dso *dso); 111void dso__delete(struct dso *dso);
109 112
110void dso__set_short_name(struct dso *dso, const char *name); 113void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated);
111void dso__set_long_name(struct dso *dso, char *name); 114void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated);
112 115
113int dso__name_len(const struct dso *dso); 116int dso__name_len(const struct dso *dso);
114 117
@@ -125,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso,
125int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); 128int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
126 129
127char dso__symtab_origin(const struct dso *dso); 130char dso__symtab_origin(const struct dso *dso);
128int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, 131int 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
131int dso__data_fd(struct dso *dso, struct machine *machine); 134int dso__data_fd(struct dso *dso, struct machine *machine);
132ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 135ssize_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
142void dsos__add(struct list_head *head, struct dso *dso); 145void dsos__add(struct list_head *head, struct dso *dso);
143struct dso *dsos__find(struct list_head *head, const char *name, 146struct dso *dsos__find(const struct list_head *head, const char *name,
144 bool cmp_short); 147 bool cmp_short);
145struct dso *__dsos__findnew(struct list_head *head, const char *name); 148struct dso *__dsos__findnew(struct list_head *head, const char *name);
146bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 149bool __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
157static inline bool dso__is_vmlinux(struct dso *dso) 160static 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
163static inline bool dso__is_kcore(struct dso *dso) 166static 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
172void 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..b0f3ca850e9e 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
11static const char *perf_event__names[] = { 12static 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
169static int perf_event__synthesize_mmap_events(struct perf_tool *tool, 178int 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
@@ -448,23 +470,32 @@ static int find_symbol_cb(void *arg, const char *name, char type,
448 return 1; 470 return 1;
449} 471}
450 472
473u64 kallsyms__get_function_start(const char *kallsyms_filename,
474 const char *symbol_name)
475{
476 struct process_symbol_args args = { .name = symbol_name, };
477
478 if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
479 return 0;
480
481 return args.start;
482}
483
451int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 484int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
452 perf_event__handler_t process, 485 perf_event__handler_t process,
453 struct machine *machine, 486 struct machine *machine)
454 const char *symbol_name)
455{ 487{
456 size_t size; 488 size_t size;
457 const char *filename, *mmap_name; 489 const char *mmap_name;
458 char path[PATH_MAX];
459 char name_buff[PATH_MAX]; 490 char name_buff[PATH_MAX];
460 struct map *map; 491 struct map *map;
492 struct kmap *kmap;
461 int err; 493 int err;
462 /* 494 /*
463 * We should get this from /sys/kernel/sections/.text, but till that is 495 * We should get this from /sys/kernel/sections/.text, but till that is
464 * available use this, and after it is use this as a fallback for older 496 * available use this, and after it is use this as a fallback for older
465 * kernels. 497 * kernels.
466 */ 498 */
467 struct process_symbol_args args = { .name = symbol_name, };
468 union perf_event *event = zalloc((sizeof(event->mmap) + 499 union perf_event *event = zalloc((sizeof(event->mmap) +
469 machine->id_hdr_size)); 500 machine->id_hdr_size));
470 if (event == NULL) { 501 if (event == NULL) {
@@ -480,30 +511,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
480 * see kernel/perf_event.c __perf_event_mmap 511 * see kernel/perf_event.c __perf_event_mmap
481 */ 512 */
482 event->header.misc = PERF_RECORD_MISC_KERNEL; 513 event->header.misc = PERF_RECORD_MISC_KERNEL;
483 filename = "/proc/kallsyms";
484 } else { 514 } else {
485 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 515 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
486 if (machine__is_default_guest(machine))
487 filename = (char *) symbol_conf.default_guest_kallsyms;
488 else {
489 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
490 filename = path;
491 }
492 }
493
494 if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) {
495 free(event);
496 return -ENOENT;
497 } 516 }
498 517
499 map = machine->vmlinux_maps[MAP__FUNCTION]; 518 map = machine->vmlinux_maps[MAP__FUNCTION];
519 kmap = map__kmap(map);
500 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 520 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
501 "%s%s", mmap_name, symbol_name) + 1; 521 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
502 size = PERF_ALIGN(size, sizeof(u64)); 522 size = PERF_ALIGN(size, sizeof(u64));
503 event->mmap.header.type = PERF_RECORD_MMAP; 523 event->mmap.header.type = PERF_RECORD_MMAP;
504 event->mmap.header.size = (sizeof(event->mmap) - 524 event->mmap.header.size = (sizeof(event->mmap) -
505 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); 525 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
506 event->mmap.pgoff = args.start; 526 event->mmap.pgoff = kmap->ref_reloc_sym->addr;
507 event->mmap.start = map->start; 527 event->mmap.start = map->start;
508 event->mmap.len = map->end - event->mmap.start; 528 event->mmap.len = map->end - event->mmap.start;
509 event->mmap.pid = machine->pid; 529 event->mmap.pid = machine->pid;
@@ -637,6 +657,7 @@ void thread__find_addr_map(struct thread *thread,
637 struct map_groups *mg = &thread->mg; 657 struct map_groups *mg = &thread->mg;
638 bool load_map = false; 658 bool load_map = false;
639 659
660 al->machine = machine;
640 al->thread = thread; 661 al->thread = thread;
641 al->addr = addr; 662 al->addr = addr;
642 al->cpumode = cpumode; 663 al->cpumode = cpumode;
@@ -657,15 +678,10 @@ void thread__find_addr_map(struct thread *thread,
657 al->level = 'g'; 678 al->level = 'g';
658 mg = &machine->kmaps; 679 mg = &machine->kmaps;
659 load_map = true; 680 load_map = true;
681 } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
682 al->level = 'u';
660 } else { 683 } else {
661 /* 684 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; 685 al->map = NULL;
670 686
671 if ((cpumode == PERF_RECORD_MISC_GUEST_USER || 687 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
@@ -732,8 +748,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
732 if (thread == NULL) 748 if (thread == NULL)
733 return -1; 749 return -1;
734 750
735 if (symbol_conf.comm_list && 751 if (thread__is_filtered(thread))
736 !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
737 goto out_filtered; 752 goto out_filtered;
738 753
739 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 754 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..851fa06f4a42 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -214,8 +214,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
214 struct machine *machine, bool mmap_data); 214 struct machine *machine, bool mmap_data);
215int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 215int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
216 perf_event__handler_t process, 216 perf_event__handler_t process,
217 struct machine *machine, 217 struct machine *machine);
218 const char *symbol_name);
219 218
220int perf_event__synthesize_modules(struct perf_tool *tool, 219int perf_event__synthesize_modules(struct perf_tool *tool,
221 perf_event__handler_t process, 220 perf_event__handler_t process,
@@ -266,10 +265,20 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
266 const struct perf_sample *sample, 265 const struct perf_sample *sample,
267 bool swapped); 266 bool swapped);
268 267
268int perf_event__synthesize_mmap_events(struct perf_tool *tool,
269 union perf_event *event,
270 pid_t pid, pid_t tgid,
271 perf_event__handler_t process,
272 struct machine *machine,
273 bool mmap_data);
274
269size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); 275size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
270size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); 276size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
271size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); 277size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
272size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); 278size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
273size_t perf_event__fprintf(union perf_event *event, FILE *fp); 279size_t perf_event__fprintf(union perf_event *event, FILE *fp);
274 280
281u64 kallsyms__get_function_start(const char *kallsyms_filename,
282 const char *symbol_name);
283
275#endif /* __PERF_RECORD_H */ 284#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index bbc746aa5716..59ef2802fcf6 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
102void perf_evlist__exit(struct perf_evlist *evlist) 102void 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
110void perf_evlist__delete(struct perf_evlist *evlist) 108void 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
205out_delete_partial_list: 209out_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
594static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 600static 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
841void 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
849int perf_evlist__apply_filters(struct perf_evlist *evlist) 845int 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 }
@@ -1007,9 +1003,12 @@ void perf_evlist__close(struct perf_evlist *evlist)
1007 struct perf_evsel *evsel; 1003 struct perf_evsel *evsel;
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);
1006 int n;
1010 1007
1011 list_for_each_entry_reverse(evsel, &evlist->entries, node) 1008 evlist__for_each_reverse(evlist, evsel) {
1012 perf_evsel__close(evsel, ncpus, nthreads); 1009 n = evsel->cpus ? evsel->cpus->nr : ncpus;
1010 perf_evsel__close(evsel, n, nthreads);
1011 }
1013} 1012}
1014 1013
1015int perf_evlist__open(struct perf_evlist *evlist) 1014int perf_evlist__open(struct perf_evlist *evlist)
@@ -1019,7 +1018,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
1019 1018
1020 perf_evlist__update_id_pos(evlist); 1019 perf_evlist__update_id_pos(evlist);
1021 1020
1022 list_for_each_entry(evsel, &evlist->entries, node) { 1021 evlist__for_each(evlist, evsel) {
1023 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 1022 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
1024 if (err < 0) 1023 if (err < 0)
1025 goto out_err; 1024 goto out_err;
@@ -1034,7 +1033,7 @@ out_err:
1034 1033
1035int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, 1034int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
1036 const char *argv[], bool pipe_output, 1035 const char *argv[], bool pipe_output,
1037 bool want_signal) 1036 void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
1038{ 1037{
1039 int child_ready_pipe[2], go_pipe[2]; 1038 int child_ready_pipe[2], go_pipe[2];
1040 char bf; 1039 char bf;
@@ -1078,12 +1077,25 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 1077
1079 execvp(argv[0], (char **)argv); 1078 execvp(argv[0], (char **)argv);
1080 1079
1081 perror(argv[0]); 1080 if (exec_error) {
1082 if (want_signal) 1081 union sigval val;
1083 kill(getppid(), SIGUSR1); 1082
1083 val.sival_int = errno;
1084 if (sigqueue(getppid(), SIGUSR1, val))
1085 perror(argv[0]);
1086 } else
1087 perror(argv[0]);
1084 exit(-1); 1088 exit(-1);
1085 } 1089 }
1086 1090
1091 if (exec_error) {
1092 struct sigaction act = {
1093 .sa_flags = SA_SIGINFO,
1094 .sa_sigaction = exec_error,
1095 };
1096 sigaction(SIGUSR1, &act, NULL);
1097 }
1098
1087 if (target__none(target)) 1099 if (target__none(target))
1088 evlist->threads->map[0] = evlist->workload.pid; 1100 evlist->threads->map[0] = evlist->workload.pid;
1089 1101
@@ -1145,7 +1157,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1145 struct perf_evsel *evsel; 1157 struct perf_evsel *evsel;
1146 size_t printed = 0; 1158 size_t printed = 0;
1147 1159
1148 list_for_each_entry(evsel, &evlist->entries, node) { 1160 evlist__for_each(evlist, evsel) {
1149 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 1161 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
1150 perf_evsel__name(evsel)); 1162 perf_evsel__name(evsel));
1151 } 1163 }
@@ -1193,8 +1205,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1193 "Error:\t%s.\n" 1205 "Error:\t%s.\n"
1194 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); 1206 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1195 1207
1196 if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) 1208 value = perf_event_paranoid();
1197 break;
1198 1209
1199 printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); 1210 printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1200 1211
@@ -1215,3 +1226,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1215 1226
1216 return 0; 1227 return 0;
1217} 1228}
1229
1230void perf_evlist__to_front(struct perf_evlist *evlist,
1231 struct perf_evsel *move_evsel)
1232{
1233 struct perf_evsel *evsel, *n;
1234 LIST_HEAD(move);
1235
1236 if (move_evsel == perf_evlist__first(evlist))
1237 return;
1238
1239 evlist__for_each_safe(evlist, n, evsel) {
1240 if (evsel->leader == move_evsel->leader)
1241 list_move_tail(&evsel->node, &move);
1242 }
1243
1244 list_splice(&move, &evlist->entries);
1245}
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 @@
12struct pollfd; 12struct pollfd;
13struct thread_map; 13struct thread_map;
14struct cpu_map; 14struct cpu_map;
15struct perf_record_opts; 15struct 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
98void perf_evlist__set_id_pos(struct perf_evlist *evlist); 98void perf_evlist__set_id_pos(struct perf_evlist *evlist);
99bool perf_can_sample_identifier(void); 99bool perf_can_sample_identifier(void);
100void perf_evlist__config(struct perf_evlist *evlist, 100void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts);
101 struct perf_record_opts *opts); 101int record_opts__config(struct record_opts *opts);
102int perf_record_opts__config(struct perf_record_opts *opts);
103 102
104int perf_evlist__prepare_workload(struct perf_evlist *evlist, 103int 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));
108int perf_evlist__start_workload(struct perf_evlist *evlist); 108int perf_evlist__start_workload(struct perf_evlist *evlist);
109 109
110int perf_evlist__parse_mmap_pages(const struct option *opt, 110int 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
137int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); 137int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
138void perf_evlist__delete_maps(struct perf_evlist *evlist);
139int perf_evlist__apply_filters(struct perf_evlist *evlist); 138int perf_evlist__apply_filters(struct perf_evlist *evlist);
140 139
141void __perf_evlist__set_leader(struct list_head *list); 140void __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
195bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
196void 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..55407c594b87 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
27static struct { 28static 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
181struct 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
213out_free_bf:
214 free(bf);
215 close(fd);
216out_free_filename:
217 free(filename);
218out:
219 return format;
220}
221
222struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 184struct 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
248out_free: 210out_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 */
569void perf_evsel__config(struct perf_evsel *evsel, 531void 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
795void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 757void 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
806void perf_evsel__free_counts(struct perf_evsel *evsel) 768void perf_evsel__free_counts(struct perf_evsel *evsel)
807{ 769{
808 free(evsel->counts); 770 zfree(&evsel->counts);
809} 771}
810 772
811void perf_evsel__exit(struct perf_evsel *evsel) 773void 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
@@ -1119,7 +1081,6 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
1119 1081
1120 perf_evsel__close_fd(evsel, ncpus, nthreads); 1082 perf_evsel__close_fd(evsel, ncpus, nthreads);
1121 perf_evsel__free_fd(evsel); 1083 perf_evsel__free_fd(evsel);
1122 evsel->fd = NULL;
1123} 1084}
1124 1085
1125static struct { 1086static struct {
@@ -1998,8 +1959,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
1998 evsel->attr.type = PERF_TYPE_SOFTWARE; 1959 evsel->attr.type = PERF_TYPE_SOFTWARE;
1999 evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; 1960 evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK;
2000 1961
2001 free(evsel->name); 1962 zfree(&evsel->name);
2002 evsel->name = NULL;
2003 return true; 1963 return true;
2004 } 1964 }
2005 1965
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 {
94struct cpu_map; 96struct cpu_map;
95struct thread_map; 97struct thread_map;
96struct perf_evlist; 98struct perf_evlist;
97struct perf_record_opts; 99struct record_opts;
98 100
99struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); 101struct 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);
118void perf_evsel__delete(struct perf_evsel *evsel); 120void perf_evsel__delete(struct perf_evsel *evsel);
119 121
120void perf_evsel__config(struct perf_evsel *evsel, 122void perf_evsel__config(struct perf_evsel *evsel,
121 struct perf_record_opts *opts); 123 struct record_opts *opts);
122 124
123int __perf_evsel__sample_size(u64 sample_type); 125int __perf_evsel__sample_size(u64 sample_type);
124void perf_evsel__calc_id_pos(struct perf_evsel *evsel); 126void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -138,6 +140,7 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
138int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, 140int __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);
140const char *perf_evsel__name(struct perf_evsel *evsel); 142const char *perf_evsel__name(struct perf_evsel *evsel);
143
141const char *perf_evsel__group_name(struct perf_evsel *evsel); 144const char *perf_evsel__group_name(struct perf_evsel *evsel);
142int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 145int 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..893f8e2df928 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
180static int write_buildid(char *name, size_t name_len, u8 *build_id, 180static 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}
@@ -931,7 +930,7 @@ static int write_topo_node(int fd, int node)
931 /* skip over invalid lines */ 930 /* skip over invalid lines */
932 if (!strchr(buf, ':')) 931 if (!strchr(buf, ':'))
933 continue; 932 continue;
934 if (sscanf(buf, "%*s %*d %s %"PRIu64, field, &mem) != 2) 933 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
935 goto done; 934 goto done;
936 if (!strcmp(field, "MemTotal:")) 935 if (!strcmp(field, "MemTotal:"))
937 mem_total = mem; 936 mem_total = mem;
@@ -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 }
1328out: 1325out:
1329 if (buf) 1326 free(buf);
1330 free(buf);
1331 return events; 1327 return events;
1332error: 1328error:
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;
2109out_free: 2105out_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,
2534int perf_file_header__read(struct perf_file_header *header, 2531int 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
92struct perf_header { 92struct 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
271const char *help_unknown_cmd(const char *cmd) 270const 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
185static void hist_entry__add_cpumode_period(struct hist_entry *he, 184static 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
226static void hist_entry__decay(struct hist_entry *he) 225static 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
344static struct hist_entry *add_hist_entry(struct hists *hists, 343static 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);
405out: 404out:
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
443int64_t 442int64_t
@@ -476,8 +475,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
476 475
477void hist_entry__free(struct hist_entry *he) 476void 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
810int 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
815int hist_entry__annotate(struct hist_entry *he, size_t privsize)
816{
817 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
818}
819
820void events_stats__inc(struct events_stats *stats, u32 type) 809void 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);
111size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 111size_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
114int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
115int hist_entry__annotate(struct hist_entry *he, size_t privsize);
116
117void hists__filter_by_dso(struct hists *hists); 114void hists__filter_by_dso(struct hists *hists);
118void hists__filter_by_thread(struct hists *hists); 115void hists__filter_by_thread(struct hists *hists);
119void hists__filter_by_symbol(struct hists *hists); 116void 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/asm/hash.h b/tools/perf/util/include/asm/hash.h
new file mode 100644
index 000000000000..d82b170bb216
--- /dev/null
+++ b/tools/perf/util/include/asm/hash.h
@@ -0,0 +1,6 @@
1#ifndef __ASM_GENERIC_HASH_H
2#define __ASM_GENERIC_HASH_H
3
4/* Stub */
5
6#endif /* __ASM_GENERIC_HASH_H */
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 45cf10a562bd..dadfa7e54287 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -87,13 +87,15 @@ static __always_inline unsigned long __ffs(unsigned long word)
87 return num; 87 return num;
88} 88}
89 89
90typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
91
90/* 92/*
91 * Find the first set bit in a memory region. 93 * Find the first set bit in a memory region.
92 */ 94 */
93static inline unsigned long 95static inline unsigned long
94find_first_bit(const unsigned long *addr, unsigned long size) 96find_first_bit(const unsigned long *addr, unsigned long size)
95{ 97{
96 const unsigned long *p = addr; 98 long_alias_t *p = (long_alias_t *) addr;
97 unsigned long result = 0; 99 unsigned long result = 0;
98 unsigned long tmp; 100 unsigned long tmp;
99 101
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..620a1983b76b 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
14int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 15int 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
108void machine__delete(struct machine *machine) 109void machine__delete(struct machine *machine)
@@ -495,23 +496,22 @@ static int symbol__in_kernel(void *arg, const char *name,
495 return 1; 496 return 1;
496} 497}
497 498
499static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
500 size_t bufsz)
501{
502 if (machine__is_default_guest(machine))
503 scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
504 else
505 scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
506}
507
498/* Figure out the start address of kernel map from /proc/kallsyms */ 508/* Figure out the start address of kernel map from /proc/kallsyms */
499static u64 machine__get_kernel_start_addr(struct machine *machine) 509static u64 machine__get_kernel_start_addr(struct machine *machine)
500{ 510{
501 const char *filename; 511 char filename[PATH_MAX];
502 char path[PATH_MAX];
503 struct process_args args; 512 struct process_args args;
504 513
505 if (machine__is_host(machine)) { 514 machine__get_kallsyms_filename(machine, filename, PATH_MAX);
506 filename = "/proc/kallsyms";
507 } else {
508 if (machine__is_default_guest(machine))
509 filename = (char *)symbol_conf.default_guest_kallsyms;
510 else {
511 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
512 filename = path;
513 }
514 }
515 515
516 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 516 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
517 return 0; 517 return 0;
@@ -565,11 +565,10 @@ void machine__destroy_kernel_maps(struct machine *machine)
565 * on one of them. 565 * on one of them.
566 */ 566 */
567 if (type == MAP__FUNCTION) { 567 if (type == MAP__FUNCTION) {
568 free((char *)kmap->ref_reloc_sym->name); 568 zfree((char **)&kmap->ref_reloc_sym->name);
569 kmap->ref_reloc_sym->name = NULL; 569 zfree(&kmap->ref_reloc_sym);
570 free(kmap->ref_reloc_sym); 570 } else
571 } 571 kmap->ref_reloc_sym = NULL;
572 kmap->ref_reloc_sym = NULL;
573 } 572 }
574 573
575 map__delete(machine->vmlinux_maps[type]); 574 map__delete(machine->vmlinux_maps[type]);
@@ -767,8 +766,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
767 ret = -1; 766 ret = -1;
768 goto out; 767 goto out;
769 } 768 }
770 dso__set_long_name(map->dso, long_name); 769 dso__set_long_name(map->dso, long_name, true);
771 map->dso->lname_alloc = 1;
772 dso__kernel_module_get_build_id(map->dso, ""); 770 dso__kernel_module_get_build_id(map->dso, "");
773 } 771 }
774 } 772 }
@@ -834,9 +832,25 @@ static int machine__create_modules(struct machine *machine)
834 return 0; 832 return 0;
835} 833}
836 834
835const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
836
837int machine__create_kernel_maps(struct machine *machine) 837int machine__create_kernel_maps(struct machine *machine)
838{ 838{
839 struct dso *kernel = machine__get_kernel(machine); 839 struct dso *kernel = machine__get_kernel(machine);
840 char filename[PATH_MAX];
841 const char *name;
842 u64 addr = 0;
843 int i;
844
845 machine__get_kallsyms_filename(machine, filename, PATH_MAX);
846
847 for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
848 addr = kallsyms__get_function_start(filename, name);
849 if (addr)
850 break;
851 }
852 if (!addr)
853 return -1;
840 854
841 if (kernel == NULL || 855 if (kernel == NULL ||
842 __machine__create_kernel_maps(machine, kernel) < 0) 856 __machine__create_kernel_maps(machine, kernel) < 0)
@@ -855,6 +869,13 @@ int machine__create_kernel_maps(struct machine *machine)
855 * Now that we have all the maps created, just set the ->end of them: 869 * Now that we have all the maps created, just set the ->end of them:
856 */ 870 */
857 map_groups__fixup_end(&machine->kmaps); 871 map_groups__fixup_end(&machine->kmaps);
872
873 if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name,
874 addr)) {
875 machine__destroy_kernel_maps(machine);
876 return -1;
877 }
878
858 return 0; 879 return 0;
859} 880}
860 881
@@ -939,8 +960,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
939 if (name == NULL) 960 if (name == NULL)
940 goto out_problem; 961 goto out_problem;
941 962
942 map->dso->short_name = name; 963 dso__set_short_name(map->dso, name, true);
943 map->dso->sname_alloc = 1;
944 map->end = map->start + event->mmap.len; 964 map->end = map->start + event->mmap.len;
945 } else if (is_kernel_mmap) { 965 } else if (is_kernel_mmap) {
946 const char *symbol_name = (event->mmap.filename + 966 const char *symbol_name = (event->mmap.filename +
@@ -1193,7 +1213,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1193 */ 1213 */
1194 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, 1214 thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
1195 ip, &al); 1215 ip, &al);
1196 if (al.sym) 1216 if (al.map)
1197 goto found; 1217 goto found;
1198 } 1218 }
1199found: 1219found:
@@ -1320,8 +1340,6 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1320 *root_al = al; 1340 *root_al = al;
1321 callchain_cursor_reset(&callchain_cursor); 1341 callchain_cursor_reset(&callchain_cursor);
1322 } 1342 }
1323 if (!symbol_conf.use_callchain)
1324 break;
1325 } 1343 }
1326 1344
1327 err = callchain_cursor_append(&callchain_cursor, 1345 err = callchain_cursor_append(&callchain_cursor,
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 477133015440..f77e91e483dc 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -18,6 +18,8 @@ union perf_event;
18#define HOST_KERNEL_ID (-1) 18#define HOST_KERNEL_ID (-1)
19#define DEFAULT_GUEST_KERNEL_ID (0) 19#define DEFAULT_GUEST_KERNEL_ID (0)
20 20
21extern const char *ref_reloc_sym_names[];
22
21struct machine { 23struct machine {
22 struct rb_node rb_node; 24 struct rb_node rb_node;
23 pid_t pid; 25 pid_t pid;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index ef5bc913ca7a..39cd2d0faff6 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
16const char *map_type__name[MAP__NR_TYPES] = { 17const char *map_type__name[MAP__NR_TYPES] = {
@@ -38,6 +39,7 @@ void map__init(struct map *map, enum map_type type,
38 map->start = start; 39 map->start = start;
39 map->end = end; 40 map->end = end;
40 map->pgoff = pgoff; 41 map->pgoff = pgoff;
42 map->reloc = 0;
41 map->dso = dso; 43 map->dso = dso;
42 map->map_ip = map__map_ip; 44 map->map_ip = map__map_ip;
43 map->unmap_ip = map__unmap_ip; 45 map->unmap_ip = map__unmap_ip;
@@ -68,7 +70,7 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
68 map->ino = ino; 70 map->ino = ino;
69 map->ino_generation = ino_gen; 71 map->ino_generation = ino_gen;
70 72
71 if (anon) { 73 if ((anon || no_dso) && type == MAP__FUNCTION) {
72 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 74 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
73 filename = newfilename; 75 filename = newfilename;
74 } 76 }
@@ -92,7 +94,7 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
92 * functions still return NULL, and we avoid the 94 * functions still return NULL, and we avoid the
93 * unnecessary map__load warning. 95 * unnecessary map__load warning.
94 */ 96 */
95 if (no_dso) 97 if (type != MAP__FUNCTION)
96 dso__set_loaded(dso, map->type); 98 dso__set_loaded(dso, map->type);
97 } 99 }
98 } 100 }
@@ -252,6 +254,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
252 return fprintf(fp, "%s", dsoname); 254 return fprintf(fp, "%s", dsoname);
253} 255}
254 256
257int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
258 FILE *fp)
259{
260 char *srcline;
261 int ret = 0;
262
263 if (map && map->dso) {
264 srcline = get_srcline(map->dso,
265 map__rip_2objdump(map, addr));
266 if (srcline != SRCLINE_UNKNOWN)
267 ret = fprintf(fp, "%s%s", prefix, srcline);
268 free_srcline(srcline);
269 }
270 return ret;
271}
272
255/** 273/**
256 * map__rip_2objdump - convert symbol start address to objdump address. 274 * map__rip_2objdump - convert symbol start address to objdump address.
257 * @map: memory map 275 * @map: memory map
@@ -271,7 +289,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
271 if (map->dso->rel) 289 if (map->dso->rel)
272 return rip - map->pgoff; 290 return rip - map->pgoff;
273 291
274 return map->unmap_ip(map, rip); 292 return map->unmap_ip(map, rip) - map->reloc;
275} 293}
276 294
277/** 295/**
@@ -294,7 +312,7 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
294 if (map->dso->rel) 312 if (map->dso->rel)
295 return map->unmap_ip(map, ip + map->pgoff); 313 return map->unmap_ip(map, ip + map->pgoff);
296 314
297 return ip; 315 return ip + map->reloc;
298} 316}
299 317
300void map_groups__init(struct map_groups *mg) 318void map_groups__init(struct map_groups *mg)
@@ -369,7 +387,8 @@ struct symbol *map_groups__find_symbol(struct map_groups *mg,
369{ 387{
370 struct map *map = map_groups__find(mg, type, addr); 388 struct map *map = map_groups__find(mg, type, addr);
371 389
372 if (map != NULL) { 390 /* Ensure map is loaded before using map->map_ip */
391 if (map != NULL && map__load(map, filter) >= 0) {
373 if (mapp != NULL) 392 if (mapp != NULL)
374 *mapp = map; 393 *mapp = map;
375 return map__find_symbol(map, map->map_ip(map, addr), filter); 394 return map__find_symbol(map, map->map_ip(map, addr), filter);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index e4e259c3ba16..257e513205ce 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -36,6 +36,7 @@ struct map {
36 bool erange_warned; 36 bool erange_warned;
37 u32 priv; 37 u32 priv;
38 u64 pgoff; 38 u64 pgoff;
39 u64 reloc;
39 u32 maj, min; /* only valid for MMAP2 record */ 40 u32 maj, min; /* only valid for MMAP2 record */
40 u64 ino; /* only valid for MMAP2 record */ 41 u64 ino; /* only valid for MMAP2 record */
41 u64 ino_generation;/* only valid for MMAP2 record */ 42 u64 ino_generation;/* only valid for MMAP2 record */
@@ -103,6 +104,8 @@ struct map *map__clone(struct map *map);
103int map__overlap(struct map *l, struct map *r); 104int map__overlap(struct map *l, struct map *r);
104size_t map__fprintf(struct map *map, FILE *fp); 105size_t map__fprintf(struct map *map, FILE *fp);
105size_t map__fprintf_dsoname(struct map *map, FILE *fp); 106size_t map__fprintf_dsoname(struct map *map, FILE *fp);
107int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
108 FILE *fp);
106 109
107int map__load(struct map *map, symbol_filter_t filter); 110int map__load(struct map *map, symbol_filter_t filter);
108struct symbol *map__find_symbol(struct map *map, 111struct 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..1e15df10a88c 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
272static int __add_event(struct list_head *list, int *idx, 272static 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
291static int add_event(struct list_head *list, int *idx, 292static 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
297static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 298static 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 const 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
659int parse_events__modifier_group(struct list_head *list, 669int 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
@@ -1082,12 +1091,12 @@ int is_valid_tracepoint(const char *event_string)
1082static bool is_event_supported(u8 type, unsigned config) 1091static bool is_event_supported(u8 type, unsigned config)
1083{ 1092{
1084 bool ret = true; 1093 bool ret = true;
1094 int open_return;
1085 struct perf_evsel *evsel; 1095 struct perf_evsel *evsel;
1086 struct perf_event_attr attr = { 1096 struct perf_event_attr attr = {
1087 .type = type, 1097 .type = type,
1088 .config = config, 1098 .config = config,
1089 .disabled = 1, 1099 .disabled = 1,
1090 .exclude_kernel = 1,
1091 }; 1100 };
1092 struct { 1101 struct {
1093 struct thread_map map; 1102 struct thread_map map;
@@ -1099,7 +1108,20 @@ static bool is_event_supported(u8 type, unsigned config)
1099 1108
1100 evsel = perf_evsel__new(&attr); 1109 evsel = perf_evsel__new(&attr);
1101 if (evsel) { 1110 if (evsel) {
1102 ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; 1111 open_return = perf_evsel__open(evsel, NULL, &tmap.map);
1112 ret = open_return >= 0;
1113
1114 if (open_return == -EACCES) {
1115 /*
1116 * This happens if the paranoid value
1117 * /proc/sys/kernel/perf_event_paranoid is set to 2
1118 * Re-run with exclude_kernel set; we don't do that
1119 * by default as some ARM machines do not support it.
1120 *
1121 */
1122 evsel->attr.exclude_kernel = 1;
1123 ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
1124 }
1103 perf_evsel__delete(evsel); 1125 perf_evsel__delete(evsel);
1104 } 1126 }
1105 1127
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)) {
229is_abbreviated: 249is_abbreviated:
@@ -259,6 +279,7 @@ is_abbreviated:
259 if (!rest) 279 if (!rest)
260 continue; 280 continue;
261 } 281 }
282match:
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 */
86struct option { 89struct 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..b752ecb40d86 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
13struct perf_pmu_alias { 15struct 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
19struct perf_pmu_format { 23struct 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
97static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) 101static 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 const 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;
142error:
143 close(fd);
144 return ret;
145}
146
147static 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;
168error:
169 close(fd);
170 alias->unit[0] = '\0';
171 return -1;
172}
173
174static 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 */
411static int pmu_config_term(struct list_head *formats, 510static int pmu_config_term(struct list_head *formats,
412 struct perf_event_attr *attr, 511 struct perf_event_attr *attr,
@@ -508,16 +607,46 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
508 return NULL; 607 return NULL;
509} 608}
510 609
610
611static int check_unit_scale(struct perf_pmu_alias *alias,
612 const 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 */
515int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) 636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const 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 /*
644 * Mark unit and scale as not set
645 * (different from default values, see below)
646 */
647 *unit = NULL;
648 *scale = 0.0;
649
521 list_for_each_entry_safe(term, h, head_terms, list) { 650 list_for_each_entry_safe(term, h, head_terms, list) {
522 alias = pmu_find_alias(pmu, term); 651 alias = pmu_find_alias(pmu, term);
523 if (!alias) 652 if (!alias)
@@ -525,9 +654,26 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
525 ret = pmu_alias_terms(alias, &term->list); 654 ret = pmu_alias_terms(alias, &term->list);
526 if (ret) 655 if (ret)
527 return ret; 656 return ret;
657
658 ret = check_unit_scale(alias, unit, scale);
659 if (ret)
660 return ret;
661
528 list_del(&term->list); 662 list_del(&term->list);
529 free(term); 663 free(term);
530 } 664 }
665
666 /*
667 * if no unit or scale foundin aliases, then
668 * set defaults as for evsel
669 * unit cannot left to NULL
670 */
671 if (*unit == NULL)
672 *unit = "";
673
674 if (*scale == 0.0)
675 *scale = 1.0;
676
531 return 0; 677 return 0;
532} 678}
533 679
@@ -625,7 +771,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
625 continue; 771 continue;
626 } 772 }
627 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 773 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
628 free(aliases[j]); 774 zfree(&aliases[j]);
629 printed++; 775 printed++;
630 } 776 }
631 if (printed) 777 if (printed)
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 1179b26f244a..8b64125a9281 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,
28int perf_pmu__config_terms(struct list_head *formats, 28int 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);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms); 31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale);
32struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 33struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
33 struct list_head *head_terms); 34 struct list_head *head_terms);
34int perf_pmu_wrap(void); 35int perf_pmu_wrap(void);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9c6989ca2bea..d8b048c20cde 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, ...)
72static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 72static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
73static int convert_name_to_addr(struct perf_probe_event *pev, 73static int convert_name_to_addr(struct perf_probe_event *pev,
74 const char *exec); 74 const char *exec);
75static void clear_probe_trace_event(struct probe_trace_event *tev);
75static struct machine machine; 76static 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
190static 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
216out:
217 free(exec_copy);
218 return ret;
219}
220
189static int convert_to_perf_probe_point(struct probe_trace_point *tp, 221static 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
296static 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;
319out:
320 elf_end(elf);
321 return ret;
322}
323
324static 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 /* point.address is the addres of point.symbol + point.offset */
340 offset = tevs[i].point.address - stext;
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
264static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 358static 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
391static 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 */
300static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 400static 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
648static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 746static 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
777void 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
793void line_range__init(struct line_range *lr)
794{
795 memset(lr, 0, sizeof(*lr));
796 INIT_LIST_HEAD(&lr->line_list);
797}
798
681static int parse_line_num(char **ptr, int *val, const char *what) 799static 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)
1278error: 1396error:
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 */
120extern int parse_line_range_desc(const char *cmd, struct line_range *lr); 121extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
121 122
123/* Release line range members */
124extern void line_range__clear(struct line_range *lr);
125
126/* Initialize line range */
127extern void line_range__init(struct line_range *lr);
128
122/* Internal use: Return kernel/module path */ 129/* Internal use: Return kernel/module path */
123extern const char *kernel_get_module_path(const char *module); 130extern 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
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20util/fs.c 20util/fs.c
21util/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
77void perf_evlist__config(struct perf_evlist *evlist, 77void 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
126static int perf_record_opts__config_freq(struct perf_record_opts *opts) 125static 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
176int perf_record_opts__config(struct perf_record_opts *opts) 175int 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
180bool 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
212out_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
260static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, 259static 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
350static void perl_process_event_generic(union perf_event *event, 346static 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,
377static void perl_process_event(union perf_event *event, 370static 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
388static void run_start_sub(void) 380static 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
234static void python_process_tracepoint(union perf_event *perf_event 233static 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
354static void python_process_general_event(union perf_event *perf_event 350static 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
414static void python_process_event(union perf_event *perf_event, 407static 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..5da6ce74c676 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
133static void perf_session_env__delete(struct perf_session_env *env) 133static 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
149void perf_session__delete(struct perf_session *session) 149void 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
250void 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
260void 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
271static void swap_sample_id_all(union perf_event *event, void *data) 250static 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;
@@ -1024,6 +1008,12 @@ static int perf_session__process_user_event(struct perf_session *session, union
1024 if (err == 0) 1008 if (err == 0)
1025 perf_session__set_id_hdr_size(session); 1009 perf_session__set_id_hdr_size(session);
1026 return err; 1010 return err;
1011 case PERF_RECORD_HEADER_EVENT_TYPE:
1012 /*
1013 * Depreceated, but we need to handle it for sake
1014 * of old data files create in pipe mode.
1015 */
1016 return 0;
1027 case PERF_RECORD_HEADER_TRACING_DATA: 1017 case PERF_RECORD_HEADER_TRACING_DATA:
1028 /* setup for reading amidst mmap */ 1018 /* setup for reading amidst mmap */
1029 lseek(fd, file_offset, SEEK_SET); 1019 lseek(fd, file_offset, SEEK_SET);
@@ -1158,7 +1148,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session,
1158 void *buf = NULL; 1148 void *buf = NULL;
1159 int skip = 0; 1149 int skip = 0;
1160 u64 head; 1150 u64 head;
1161 int err; 1151 ssize_t err;
1162 void *p; 1152 void *p;
1163 1153
1164 perf_tool__fill_defaults(tool); 1154 perf_tool__fill_defaults(tool);
@@ -1400,7 +1390,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
1400{ 1390{
1401 struct perf_evsel *evsel; 1391 struct perf_evsel *evsel;
1402 1392
1403 list_for_each_entry(evsel, &session->evlist->entries, node) { 1393 evlist__for_each(session->evlist, evsel) {
1404 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) 1394 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1405 return true; 1395 return true;
1406 } 1396 }
@@ -1458,7 +1448,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1458 1448
1459 ret += events_stats__fprintf(&session->stats, fp); 1449 ret += events_stats__fprintf(&session->stats, fp);
1460 1450
1461 list_for_each_entry(pos, &session->evlist->entries, node) { 1451 evlist__for_each(session->evlist, pos) {
1462 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); 1452 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1463 ret += events_stats__fprintf(&pos->hists.stats, fp); 1453 ret += events_stats__fprintf(&pos->hists.stats, fp);
1464 } 1454 }
@@ -1480,35 +1470,30 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1480{ 1470{
1481 struct perf_evsel *pos; 1471 struct perf_evsel *pos;
1482 1472
1483 list_for_each_entry(pos, &session->evlist->entries, node) { 1473 evlist__for_each(session->evlist, pos) {
1484 if (pos->attr.type == type) 1474 if (pos->attr.type == type)
1485 return pos; 1475 return pos;
1486 } 1476 }
1487 return NULL; 1477 return NULL;
1488} 1478}
1489 1479
1490void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 1480void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1491 struct perf_sample *sample, struct machine *machine, 1481 struct addr_location *al,
1492 unsigned int print_opts, unsigned int stack_depth) 1482 unsigned int print_opts, unsigned int stack_depth)
1493{ 1483{
1494 struct addr_location al;
1495 struct callchain_cursor_node *node; 1484 struct callchain_cursor_node *node;
1496 int print_ip = print_opts & PRINT_IP_OPT_IP; 1485 int print_ip = print_opts & PRINT_IP_OPT_IP;
1497 int print_sym = print_opts & PRINT_IP_OPT_SYM; 1486 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1498 int print_dso = print_opts & PRINT_IP_OPT_DSO; 1487 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1499 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; 1488 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1500 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; 1489 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1490 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
1501 char s = print_oneline ? ' ' : '\t'; 1491 char s = print_oneline ? ' ' : '\t';
1502 1492
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) { 1493 if (symbol_conf.use_callchain && sample->callchain) {
1494 struct addr_location node_al;
1510 1495
1511 if (machine__resolve_callchain(machine, evsel, al.thread, 1496 if (machine__resolve_callchain(al->machine, evsel, al->thread,
1512 sample, NULL, NULL, 1497 sample, NULL, NULL,
1513 PERF_MAX_STACK_DEPTH) != 0) { 1498 PERF_MAX_STACK_DEPTH) != 0) {
1514 if (verbose) 1499 if (verbose)
@@ -1517,20 +1502,31 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1517 } 1502 }
1518 callchain_cursor_commit(&callchain_cursor); 1503 callchain_cursor_commit(&callchain_cursor);
1519 1504
1505 if (print_symoffset)
1506 node_al = *al;
1507
1520 while (stack_depth) { 1508 while (stack_depth) {
1509 u64 addr = 0;
1510
1521 node = callchain_cursor_current(&callchain_cursor); 1511 node = callchain_cursor_current(&callchain_cursor);
1522 if (!node) 1512 if (!node)
1523 break; 1513 break;
1524 1514
1515 if (node->sym && node->sym->ignore)
1516 goto next;
1517
1525 if (print_ip) 1518 if (print_ip)
1526 printf("%c%16" PRIx64, s, node->ip); 1519 printf("%c%16" PRIx64, s, node->ip);
1527 1520
1521 if (node->map)
1522 addr = node->map->map_ip(node->map, node->ip);
1523
1528 if (print_sym) { 1524 if (print_sym) {
1529 printf(" "); 1525 printf(" ");
1530 if (print_symoffset) { 1526 if (print_symoffset) {
1531 al.addr = node->ip; 1527 node_al.addr = addr;
1532 al.map = node->map; 1528 node_al.map = node->map;
1533 symbol__fprintf_symname_offs(node->sym, &al, stdout); 1529 symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
1534 } else 1530 } else
1535 symbol__fprintf_symname(node->sym, stdout); 1531 symbol__fprintf_symname(node->sym, stdout);
1536 } 1532 }
@@ -1541,39 +1537,49 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1541 printf(")"); 1537 printf(")");
1542 } 1538 }
1543 1539
1540 if (print_srcline)
1541 map__fprintf_srcline(node->map, addr, "\n ",
1542 stdout);
1543
1544 if (!print_oneline) 1544 if (!print_oneline)
1545 printf("\n"); 1545 printf("\n");
1546 1546
1547 callchain_cursor_advance(&callchain_cursor);
1548
1549 stack_depth--; 1547 stack_depth--;
1548next:
1549 callchain_cursor_advance(&callchain_cursor);
1550 } 1550 }
1551 1551
1552 } else { 1552 } else {
1553 if (al->sym && al->sym->ignore)
1554 return;
1555
1553 if (print_ip) 1556 if (print_ip)
1554 printf("%16" PRIx64, sample->ip); 1557 printf("%16" PRIx64, sample->ip);
1555 1558
1556 if (print_sym) { 1559 if (print_sym) {
1557 printf(" "); 1560 printf(" ");
1558 if (print_symoffset) 1561 if (print_symoffset)
1559 symbol__fprintf_symname_offs(al.sym, &al, 1562 symbol__fprintf_symname_offs(al->sym, al,
1560 stdout); 1563 stdout);
1561 else 1564 else
1562 symbol__fprintf_symname(al.sym, stdout); 1565 symbol__fprintf_symname(al->sym, stdout);
1563 } 1566 }
1564 1567
1565 if (print_dso) { 1568 if (print_dso) {
1566 printf(" ("); 1569 printf(" (");
1567 map__fprintf_dsoname(al.map, stdout); 1570 map__fprintf_dsoname(al->map, stdout);
1568 printf(")"); 1571 printf(")");
1569 } 1572 }
1573
1574 if (print_srcline)
1575 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
1570 } 1576 }
1571} 1577}
1572 1578
1573int perf_session__cpu_bitmap(struct perf_session *session, 1579int perf_session__cpu_bitmap(struct perf_session *session,
1574 const char *cpu_list, unsigned long *cpu_bitmap) 1580 const char *cpu_list, unsigned long *cpu_bitmap)
1575{ 1581{
1576 int i; 1582 int i, err = -1;
1577 struct cpu_map *map; 1583 struct cpu_map *map;
1578 1584
1579 for (i = 0; i < PERF_TYPE_MAX; ++i) { 1585 for (i = 0; i < PERF_TYPE_MAX; ++i) {
@@ -1602,13 +1608,17 @@ int perf_session__cpu_bitmap(struct perf_session *session,
1602 if (cpu >= MAX_NR_CPUS) { 1608 if (cpu >= MAX_NR_CPUS) {
1603 pr_err("Requested CPU %d too large. " 1609 pr_err("Requested CPU %d too large. "
1604 "Consider raising MAX_NR_CPUS\n", cpu); 1610 "Consider raising MAX_NR_CPUS\n", cpu);
1605 return -1; 1611 goto out_delete_map;
1606 } 1612 }
1607 1613
1608 set_bit(cpu, cpu_bitmap); 1614 set_bit(cpu, cpu_bitmap);
1609 } 1615 }
1610 1616
1611 return 0; 1617 err = 0;
1618
1619out_delete_map:
1620 cpu_map__delete(map);
1621 return err;
1612} 1622}
1613 1623
1614void perf_session__fprintf_info(struct perf_session *session, FILE *fp, 1624void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
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
48struct perf_tool; 50struct perf_tool;
49 51
@@ -72,8 +74,6 @@ int perf_session__resolve_callchain(struct perf_session *session,
72 74
73bool perf_session__has_traces(struct perf_session *session, const char *msg); 75bool perf_session__has_traces(struct perf_session *session, const char *msg);
74 76
75void mem_bswap_64(void *src, int byte_size);
76void mem_bswap_32(void *src, int byte_size);
77void perf_event__attr_swap(struct perf_event_attr *attr); 77void perf_event__attr_swap(struct perf_event_attr *attr);
78 78
79int perf_session__create_kernel_maps(struct perf_session *session); 79int 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);
105struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 105struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
106 unsigned int type); 106 unsigned int type);
107 107
108void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 108void 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
112int perf_session__cpu_bitmap(struct perf_session *session, 112int 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'
25build_lib = getenv('PYTHON_EXTBUILD_LIB') 25build_lib = getenv('PYTHON_EXTBUILD_LIB')
26build_tmp = getenv('PYTHON_EXTBUILD_TMP') 26build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27libtraceevent = getenv('LIBTRACEEVENT') 27libtraceevent = getenv('LIBTRACEEVENT')
28liblk = getenv('LIBLK') 28libapikfs = getenv('LIBAPIKFS')
29 29
30ext_sources = [f.strip() for f in file('util/python-ext-sources') 30ext_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
40setup(name='perf', 40setup(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;
13int sort__need_collapse = 0; 13int sort__need_collapse = 0;
14int sort__has_parent = 0; 14int sort__has_parent = 0;
15int sort__has_sym = 0; 15int sort__has_sym = 0;
16int sort__has_dso = 0;
16enum sort_mode sort__mode = SORT_MODE__NORMAL; 17enum sort_mode sort__mode = SORT_MODE__NORMAL;
17 18
18enum sort_type sort__first_dimension; 19enum sort_type sort__first_dimension;
@@ -161,6 +162,11 @@ struct sort_entry sort_dso = {
161 162
162/* --sort symbol */ 163/* --sort symbol */
163 164
165static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
166{
167 return (int64_t)(right_ip - left_ip);
168}
169
164static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) 170static 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
130out: 130out:
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
148static int addr2line(const char *dso_name, unsigned long addr, 148static 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
180void 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
177static int addr2line(const char *dso_name, unsigned long addr, 194static 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
241void 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
224char *get_srcline(struct dso *dso, unsigned long addr) 253char *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
256out: 287out:
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)
28void strbuf_release(struct strbuf *sb) 28void 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:
38static void str_node__delete(struct str_node *snode, bool dupstr) 39static 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
23static u64 first_time, last_time; 27static u64 first_time, last_time;
24static u64 turbo_frequency, max_freq; 28static 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
30int svg_page_width = 1000; 34int svg_page_width = 1000;
35u64 svg_highlight;
36const 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
48static int *topology_map;
49
42static double cpu2y(int cpu) 50static 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
47static double time2pixels(u64 __time) 58static 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
131void svg_sample(int Yslot, int cpu, u64 start, u64 end) 144static char *time_to_string(u64 duration);
145void 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
159void 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
153static char *time_to_string(u64 duration) 195static 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
171void svg_waiting(int Yslot, u64 start, u64 end) 213void 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
258void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name) 307void 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
311static char *HzToHuman(unsigned long hz) 374static 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
353void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2) 419void 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
400void svg_wakeline(u64 start, int row1, int row2) 477void 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
422void svg_interrupt(u64 start, int row) 506void 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
433void svg_text(int Yslot, u64 start, const char *text) 526void 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
467void svg_time_grid(void) 562void 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)
599typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
600
601struct topology {
602 cpumask_t *sib_core;
603 int sib_core_nr;
604 cpumask_t *sib_thr;
605 int sib_thr_nr;
606};
607
608static 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
625static 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
638static 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
664int 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
711exit:
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
6extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); 6extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
7extern void svg_box(int Yslot, u64 start, u64 end, const char *type); 7extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
8extern void svg_sample(int Yslot, int cpu, u64 start, u64 end); 8extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
9extern void svg_waiting(int Yslot, u64 start, u64 end); 9extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
10extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
10extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); 11extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
11 12
12 13
13extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name); 14extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace);
14extern void svg_cstate(int cpu, u64 start, u64 end, int type); 15extern void svg_cstate(int cpu, u64 start, u64 end, int type);
15extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); 16extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
16 17
17 18
18extern void svg_time_grid(void); 19extern void svg_time_grid(void);
19extern void svg_legenda(void); 20extern void svg_legenda(void);
20extern void svg_wakeline(u64 start, int row1, int row2); 21extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace);
21extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2); 22extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace);
22extern void svg_interrupt(u64 start, int row); 23extern void svg_interrupt(u64 start, int row, const char *backtrace);
23extern void svg_text(int Yslot, u64 start, const char *text); 24extern void svg_text(int Yslot, u64 start, const char *text);
24extern void svg_close(void); 25extern void svg_close(void);
26extern int svg_build_topology_map(char *sib_core, int sib_core_nr,
27 char *sib_thr, int sib_thr_nr);
25 28
26extern int svg_page_width; 29extern int svg_page_width;
30extern u64 svg_highlight;
31extern 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..516d19fb999b 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
138static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 139Elf_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;
@@ -151,15 +151,15 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
151 151
152 gelf_getshdr(sec, shp); 152 gelf_getshdr(sec, shp);
153 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 153 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
154 if (!strcmp(name, str)) { 154 if (str && !strcmp(name, str)) {
155 if (idx) 155 if (idx)
156 *idx = cnt; 156 *idx = cnt;
157 break; 157 return sec;
158 } 158 }
159 ++cnt; 159 ++cnt;
160 } 160 }
161 161
162 return sec; 162 return NULL;
163} 163}
164 164
165#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 165#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
@@ -553,7 +553,7 @@ bool symsrc__has_symtab(struct symsrc *ss)
553 553
554void symsrc__destroy(struct symsrc *ss) 554void 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}
@@ -751,6 +751,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
751 if (strcmp(elf_name, kmap->ref_reloc_sym->name)) 751 if (strcmp(elf_name, kmap->ref_reloc_sym->name))
752 continue; 752 continue;
753 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value; 753 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
754 map->reloc = kmap->ref_reloc_sym->addr -
755 kmap->ref_reloc_sym->unrelocated_addr;
754 break; 756 break;
755 } 757 }
756 } 758 }
@@ -922,6 +924,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
922 (u64)shdr.sh_offset); 924 (u64)shdr.sh_offset);
923 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 925 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
924 } 926 }
927new_symbol:
925 /* 928 /*
926 * We need to figure out if the object was created from C++ sources 929 * We need to figure out if the object was created from C++ sources
927 * DWARF DW_compile_unit has this, but we don't always have access 930 * DWARF DW_compile_unit has this, but we don't always have access
@@ -933,7 +936,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
933 if (demangled != NULL) 936 if (demangled != NULL)
934 elf_name = demangled; 937 elf_name = demangled;
935 } 938 }
936new_symbol:
937 f = symbol__new(sym.st_value, sym.st_size, 939 f = symbol__new(sym.st_value, sym.st_size,
938 GELF_ST_BIND(sym.st_info), elf_name); 940 GELF_ST_BIND(sym.st_info), elf_name);
939 free(demangled); 941 free(demangled);
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
275void symsrc__destroy(struct symsrc *ss) 277void 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..e89afc097d8a 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
27static int dso__load_kernel_sym(struct dso *dso, struct map *map, 24static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 25 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 26static 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
449int 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
501out_failure:
502 return -1;
503}
504
505int modules__parse(const char *filename, void *arg, 446int 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
568static u8 kallsyms2elf_type(char type) 509bool 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;
572 530
573 return isupper(type) ? STB_GLOBAL : STB_LOCAL; 531 for (i = 0; idle_symbols[i]; i++) {
532 if (!strcmp(idle_symbols[i], sym->name))
533 return true;
534 }
535
536 return false;
574} 537}
575 538
576static int map__process_kallsym_symbol(void *arg, const char *name, 539static int map__process_kallsym_symbol(void *arg, const char *name,
@@ -664,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
664 * kernel range is broken in several maps, named [kernel].N, as we don't have 627 * kernel range is broken in several maps, named [kernel].N, as we don't have
665 * the original ELF section names vmlinux have. 628 * the original ELF section names vmlinux have.
666 */ 629 */
667static int dso__split_kallsyms(struct dso *dso, struct map *map, 630static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
668 symbol_filter_t filter) 631 symbol_filter_t filter)
669{ 632{
670 struct map_groups *kmaps = map__kmap(map)->kmaps; 633 struct map_groups *kmaps = map__kmap(map)->kmaps;
@@ -729,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
729 char dso_name[PATH_MAX]; 692 char dso_name[PATH_MAX];
730 struct dso *ndso; 693 struct dso *ndso;
731 694
695 if (delta) {
696 /* Kernel was relocated at boot time */
697 pos->start -= delta;
698 pos->end -= delta;
699 }
700
732 if (count == 0) { 701 if (count == 0) {
733 curr_map = map; 702 curr_map = map;
734 goto filter_symbol; 703 goto filter_symbol;
@@ -758,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
758 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 727 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
759 map_groups__insert(kmaps, curr_map); 728 map_groups__insert(kmaps, curr_map);
760 ++kernel_range; 729 ++kernel_range;
730 } else if (delta) {
731 /* Kernel was relocated at boot time */
732 pos->start -= delta;
733 pos->end -= delta;
761 } 734 }
762filter_symbol: 735filter_symbol:
763 if (filter && filter(curr_map, pos)) { 736 if (filter && filter(curr_map, pos)) {
@@ -833,7 +806,7 @@ static void delete_modules(struct rb_root *modules)
833 mi = rb_entry(next, struct module_info, rb_node); 806 mi = rb_entry(next, struct module_info, rb_node);
834 next = rb_next(&mi->rb_node); 807 next = rb_next(&mi->rb_node);
835 rb_erase(&mi->rb_node, modules); 808 rb_erase(&mi->rb_node, modules);
836 free(mi->name); 809 zfree(&mi->name);
837 free(mi); 810 free(mi);
838 } 811 }
839} 812}
@@ -1013,6 +986,23 @@ static int validate_kcore_modules(const char *kallsyms_filename,
1013 return 0; 986 return 0;
1014} 987}
1015 988
989static int validate_kcore_addresses(const char *kallsyms_filename,
990 struct map *map)
991{
992 struct kmap *kmap = map__kmap(map);
993
994 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
995 u64 start;
996
997 start = kallsyms__get_function_start(kallsyms_filename,
998 kmap->ref_reloc_sym->name);
999 if (start != kmap->ref_reloc_sym->addr)
1000 return -EINVAL;
1001 }
1002
1003 return validate_kcore_modules(kallsyms_filename, map);
1004}
1005
1016struct kcore_mapfn_data { 1006struct kcore_mapfn_data {
1017 struct dso *dso; 1007 struct dso *dso;
1018 enum map_type type; 1008 enum map_type type;
@@ -1056,8 +1046,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1056 kallsyms_filename)) 1046 kallsyms_filename))
1057 return -EINVAL; 1047 return -EINVAL;
1058 1048
1059 /* All modules must be present at their original addresses */ 1049 /* Modules and kernel must be present at their original addresses */
1060 if (validate_kcore_modules(kallsyms_filename, map)) 1050 if (validate_kcore_addresses(kallsyms_filename, map))
1061 return -EINVAL; 1051 return -EINVAL;
1062 1052
1063 md.dso = dso; 1053 md.dso = dso;
@@ -1126,10 +1116,10 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1126 * dso__data_read_addr(). 1116 * dso__data_read_addr().
1127 */ 1117 */
1128 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1118 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1129 dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; 1119 dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE;
1130 else 1120 else
1131 dso->data_type = DSO_BINARY_TYPE__KCORE; 1121 dso->binary_type = DSO_BINARY_TYPE__KCORE;
1132 dso__set_long_name(dso, strdup(kcore_filename)); 1122 dso__set_long_name(dso, strdup(kcore_filename), true);
1133 1123
1134 close(fd); 1124 close(fd);
1135 1125
@@ -1150,15 +1140,41 @@ out_err:
1150 return -EINVAL; 1140 return -EINVAL;
1151} 1141}
1152 1142
1143/*
1144 * If the kernel is relocated at boot time, kallsyms won't match. Compute the
1145 * delta based on the relocation reference symbol.
1146 */
1147static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1148{
1149 struct kmap *kmap = map__kmap(map);
1150 u64 addr;
1151
1152 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1153 return 0;
1154
1155 addr = kallsyms__get_function_start(filename,
1156 kmap->ref_reloc_sym->name);
1157 if (!addr)
1158 return -1;
1159
1160 *delta = addr - kmap->ref_reloc_sym->addr;
1161 return 0;
1162}
1163
1153int dso__load_kallsyms(struct dso *dso, const char *filename, 1164int dso__load_kallsyms(struct dso *dso, const char *filename,
1154 struct map *map, symbol_filter_t filter) 1165 struct map *map, symbol_filter_t filter)
1155{ 1166{
1167 u64 delta = 0;
1168
1156 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 1169 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
1157 return -1; 1170 return -1;
1158 1171
1159 if (dso__load_all_kallsyms(dso, filename, map) < 0) 1172 if (dso__load_all_kallsyms(dso, filename, map) < 0)
1160 return -1; 1173 return -1;
1161 1174
1175 if (kallsyms__delta(map, filename, &delta))
1176 return -1;
1177
1162 symbols__fixup_duplicate(&dso->symbols[map->type]); 1178 symbols__fixup_duplicate(&dso->symbols[map->type]);
1163 symbols__fixup_end(&dso->symbols[map->type]); 1179 symbols__fixup_end(&dso->symbols[map->type]);
1164 1180
@@ -1170,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1170 if (!dso__load_kcore(dso, map, filename)) 1186 if (!dso__load_kcore(dso, map, filename))
1171 return dso__split_kallsyms_for_kcore(dso, map, filter); 1187 return dso__split_kallsyms_for_kcore(dso, map, filter);
1172 else 1188 else
1173 return dso__split_kallsyms(dso, map, filter); 1189 return dso__split_kallsyms(dso, map, delta, filter);
1174} 1190}
1175 1191
1176static int dso__load_perf_map(struct dso *dso, struct map *map, 1192static int dso__load_perf_map(struct dso *dso, struct map *map,
@@ -1295,8 +1311,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1295 1311
1296 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1312 enum dso_binary_type symtab_type = binary_type_symtab[i];
1297 1313
1298 if (dso__binary_type_file(dso, symtab_type, 1314 if (dso__read_binary_type_filename(dso, symtab_type,
1299 root_dir, name, PATH_MAX)) 1315 root_dir, name, PATH_MAX))
1300 continue; 1316 continue;
1301 1317
1302 /* Name is now the name of the next image to try */ 1318 /* Name is now the name of the next image to try */
@@ -1306,6 +1322,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1306 if (!syms_ss && symsrc__has_symtab(ss)) { 1322 if (!syms_ss && symsrc__has_symtab(ss)) {
1307 syms_ss = ss; 1323 syms_ss = ss;
1308 next_slot = true; 1324 next_slot = true;
1325 if (!dso->symsrc_filename)
1326 dso->symsrc_filename = strdup(name);
1309 } 1327 }
1310 1328
1311 if (!runtime_ss && symsrc__possibly_runtime(ss)) { 1329 if (!runtime_ss && symsrc__possibly_runtime(ss)) {
@@ -1318,6 +1336,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1318 1336
1319 if (syms_ss && runtime_ss) 1337 if (syms_ss && runtime_ss)
1320 break; 1338 break;
1339 } else {
1340 symsrc__destroy(ss);
1321 } 1341 }
1322 1342
1323 } 1343 }
@@ -1376,7 +1396,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1376} 1396}
1377 1397
1378int dso__load_vmlinux(struct dso *dso, struct map *map, 1398int dso__load_vmlinux(struct dso *dso, struct map *map,
1379 const char *vmlinux, symbol_filter_t filter) 1399 const char *vmlinux, bool vmlinux_allocated,
1400 symbol_filter_t filter)
1380{ 1401{
1381 int err = -1; 1402 int err = -1;
1382 struct symsrc ss; 1403 struct symsrc ss;
@@ -1402,10 +1423,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1402 1423
1403 if (err > 0) { 1424 if (err > 0) {
1404 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1425 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1405 dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1426 dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1406 else 1427 else
1407 dso->data_type = DSO_BINARY_TYPE__VMLINUX; 1428 dso->binary_type = DSO_BINARY_TYPE__VMLINUX;
1408 dso__set_long_name(dso, (char *)vmlinux); 1429 dso__set_long_name(dso, vmlinux, vmlinux_allocated);
1409 dso__set_loaded(dso, map->type); 1430 dso__set_loaded(dso, map->type);
1410 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1431 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1411 } 1432 }
@@ -1424,21 +1445,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1424 1445
1425 filename = dso__build_id_filename(dso, NULL, 0); 1446 filename = dso__build_id_filename(dso, NULL, 0);
1426 if (filename != NULL) { 1447 if (filename != NULL) {
1427 err = dso__load_vmlinux(dso, map, filename, filter); 1448 err = dso__load_vmlinux(dso, map, filename, true, filter);
1428 if (err > 0) { 1449 if (err > 0)
1429 dso->lname_alloc = 1;
1430 goto out; 1450 goto out;
1431 }
1432 free(filename); 1451 free(filename);
1433 } 1452 }
1434 1453
1435 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1454 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1436 err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); 1455 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1437 if (err > 0) { 1456 if (err > 0)
1438 dso__set_long_name(dso, strdup(vmlinux_path[i]));
1439 dso->lname_alloc = 1;
1440 break; 1457 break;
1441 }
1442 } 1458 }
1443out: 1459out:
1444 return err; 1460 return err;
@@ -1463,7 +1479,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1463 continue; 1479 continue;
1464 scnprintf(kallsyms_filename, sizeof(kallsyms_filename), 1480 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1465 "%s/%s/kallsyms", dir, dent->d_name); 1481 "%s/%s/kallsyms", dir, dent->d_name);
1466 if (!validate_kcore_modules(kallsyms_filename, map)) { 1482 if (!validate_kcore_addresses(kallsyms_filename, map)) {
1467 strlcpy(dir, kallsyms_filename, dir_sz); 1483 strlcpy(dir, kallsyms_filename, dir_sz);
1468 ret = 0; 1484 ret = 0;
1469 break; 1485 break;
@@ -1496,14 +1512,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1496 1512
1497 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1513 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1498 1514
1515 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
1516 sbuild_id);
1517
1499 /* Use /proc/kallsyms if possible */ 1518 /* Use /proc/kallsyms if possible */
1500 if (is_host) { 1519 if (is_host) {
1501 DIR *d; 1520 DIR *d;
1502 int fd; 1521 int fd;
1503 1522
1504 /* If no cached kcore go with /proc/kallsyms */ 1523 /* 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); 1524 d = opendir(path);
1508 if (!d) 1525 if (!d)
1509 goto proc_kallsyms; 1526 goto proc_kallsyms;
@@ -1517,7 +1534,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1517 if (fd != -1) { 1534 if (fd != -1) {
1518 close(fd); 1535 close(fd);
1519 /* If module maps match go with /proc/kallsyms */ 1536 /* If module maps match go with /proc/kallsyms */
1520 if (!validate_kcore_modules("/proc/kallsyms", map)) 1537 if (!validate_kcore_addresses("/proc/kallsyms", map))
1521 goto proc_kallsyms; 1538 goto proc_kallsyms;
1522 } 1539 }
1523 1540
@@ -1528,6 +1545,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1528 goto proc_kallsyms; 1545 goto proc_kallsyms;
1529 } 1546 }
1530 1547
1548 /* Find kallsyms in build-id cache with kcore */
1549 if (!find_matching_kcore(map, path, sizeof(path)))
1550 return strdup(path);
1551
1531 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", 1552 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1532 buildid_dir, sbuild_id); 1553 buildid_dir, sbuild_id);
1533 1554
@@ -1570,15 +1591,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1570 } 1591 }
1571 1592
1572 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { 1593 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1573 err = dso__load_vmlinux(dso, map, 1594 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name,
1574 symbol_conf.vmlinux_name, filter); 1595 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 } 1596 }
1583 1597
1584 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { 1598 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
@@ -1604,7 +1618,7 @@ do_kallsyms:
1604 free(kallsyms_allocated_filename); 1618 free(kallsyms_allocated_filename);
1605 1619
1606 if (err > 0 && !dso__is_kcore(dso)) { 1620 if (err > 0 && !dso__is_kcore(dso)) {
1607 dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 1621 dso__set_long_name(dso, "[kernel.kallsyms]", false);
1608 map__fixup_start(map); 1622 map__fixup_start(map);
1609 map__fixup_end(map); 1623 map__fixup_end(map);
1610 } 1624 }
@@ -1634,7 +1648,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1634 */ 1648 */
1635 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1649 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1636 err = dso__load_vmlinux(dso, map, 1650 err = dso__load_vmlinux(dso, map,
1637 symbol_conf.default_guest_vmlinux_name, filter); 1651 symbol_conf.default_guest_vmlinux_name,
1652 false, filter);
1638 return err; 1653 return err;
1639 } 1654 }
1640 1655
@@ -1651,7 +1666,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1651 pr_debug("Using %s for symbols\n", kallsyms_filename); 1666 pr_debug("Using %s for symbols\n", kallsyms_filename);
1652 if (err > 0 && !dso__is_kcore(dso)) { 1667 if (err > 0 && !dso__is_kcore(dso)) {
1653 machine__mmap_name(machine, path, sizeof(path)); 1668 machine__mmap_name(machine, path, sizeof(path));
1654 dso__set_long_name(dso, strdup(path)); 1669 dso__set_long_name(dso, strdup(path), true);
1655 map__fixup_start(map); 1670 map__fixup_start(map);
1656 map__fixup_end(map); 1671 map__fixup_end(map);
1657 } 1672 }
@@ -1661,13 +1676,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1661 1676
1662static void vmlinux_path__exit(void) 1677static void vmlinux_path__exit(void)
1663{ 1678{
1664 while (--vmlinux_path__nr_entries >= 0) { 1679 while (--vmlinux_path__nr_entries >= 0)
1665 free(vmlinux_path[vmlinux_path__nr_entries]); 1680 zfree(&vmlinux_path[vmlinux_path__nr_entries]);
1666 vmlinux_path[vmlinux_path__nr_entries] = NULL;
1667 }
1668 1681
1669 free(vmlinux_path); 1682 zfree(&vmlinux_path);
1670 vmlinux_path = NULL;
1671} 1683}
1672 1684
1673static int vmlinux_path__init(void) 1685static int vmlinux_path__init(void)
@@ -1719,7 +1731,7 @@ out_fail:
1719 return -1; 1731 return -1;
1720} 1732}
1721 1733
1722static int setup_list(struct strlist **list, const char *list_str, 1734int setup_list(struct strlist **list, const char *list_str,
1723 const char *list_name) 1735 const char *list_name)
1724{ 1736{
1725 if (list_str == NULL) 1737 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
56extern 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
166struct addr_location { 171struct 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
207int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 213int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
208int dso__load_vmlinux(struct dso *dso, struct map *map, 214int 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);
210int dso__load_vmlinux_path(struct dso *dso, struct map *map, 217int dso__load_vmlinux_path(struct dso *dso, struct map *map,
211 symbol_filter_t filter); 218 symbol_filter_t filter);
212int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 219int 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
221int filename__read_build_id(const char *filename, void *bf, size_t size); 228int filename__read_build_id(const char *filename, void *bf, size_t size);
222int sysfs__read_build_id(const char *filename, void *bf, size_t size); 229int sysfs__read_build_id(const char *filename, void *bf, size_t size);
223int kallsyms__parse(const char *filename, void *arg,
224 int (*process_symbol)(void *arg, const char *name,
225 char type, u64 start));
226int modules__parse(const char *filename, void *arg, 230int 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);
240bool symbol_type__is_a(char symbol_type, enum map_type map_type); 244bool symbol_type__is_a(char symbol_type, enum map_type map_type);
241bool symbol__restricted_filename(const char *filename, 245bool symbol__restricted_filename(const char *filename,
242 const char *restricted_filename); 246 const char *restricted_filename);
247bool symbol__is_idle(struct symbol *sym);
243 248
244int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 249int 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);
273int kcore_copy(const char *from_dir, const char *to_dir); 278int kcore_copy(const char *from_dir, const char *to_dir);
274int compare_proc_modules(const char *from, const char *to); 279int compare_proc_modules(const char *from, const char *to);
275 280
281int 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
18enum target_errno { 19enum 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
66static 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)
66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 66int 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
10struct thread { 11struct 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
71static 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 */
14static int filter(const struct dirent *dir) 15static 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
135out_free_namelist: 136out_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
140out_free_closedir: 141out_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
207out_free_namelist: 207out_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
212out_free_threads: 212out_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
264out_free_threads: 263out_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;
14struct perf_top { 14struct 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
31struct 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
44static int get_common_field(struct scripting_context *context, 31static 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
346ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) 346ssize_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
438out: 440out:
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)
38static void process_event_unsupported(union perf_event *event __maybe_unused, 38static 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 */
21static struct trace_event tevent;
22
23int 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
35void trace_event__cleanup(struct trace_event *t)
36{
37 traceevent_unload_plugins(t->plugin_list, t->pevent);
38 pevent_free(t->pevent);
39}
40
41static struct event_format*
42tp_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
62struct event_format*
63trace_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
8struct machine; 7struct machine;
9struct perf_sample; 8struct perf_sample;
10union perf_event; 9union perf_event;
11struct perf_tool; 10struct perf_tool;
12struct thread; 11struct thread;
12struct plugin_list;
13
14struct trace_event {
15 struct pevent *pevent;
16 struct plugin_list *plugin_list;
17};
18
19int trace_event__init(struct trace_event *t);
20void trace_event__cleanup(struct trace_event *t);
21struct event_format*
22trace_event__tp_format(const char *sys, const char *name);
13 23
14int bigendian(void); 24int bigendian(void);
15 25
16struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
17void event_format__print(struct event_format *event, 26void 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);
27void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 36void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
28void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 37void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
29 38
30ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); 39ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
31 40
32struct event_format *trace_find_next_event(struct pevent *pevent, 41struct 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
33extern int 34extern 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
161static 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
178static u64 elf_section_offset(int fd, const char *name) 162static 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
154int readn(int fd, void *buf, size_t n) 160static 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 */
183ssize_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 */
191ssize_t writen(int fd, void *buf, size_t n)
192{
193 return ion(false, fd, buf, n);
169} 194}
170 195
171size_t hex_width(u64 v) 196size_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
442int 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
489const 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
503int 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
520void 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
530void 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
77extern const char *graph_line; 78extern const char *graph_line;
78extern const char *graph_dotted_line; 79extern 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
188static inline int has_extension(const char *filename, const char *ext) 191static 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);
253int strtailcmp(const char *s1, const char *s2); 256int strtailcmp(const char *s1, const char *s2);
254char *strxfrchar(char *s, char from, char to); 257char *strxfrchar(char *s, char from, char to);
255unsigned long convert_unit(unsigned long value, char *unit); 258unsigned long convert_unit(unsigned long value, char *unit);
256int readn(int fd, void *buf, size_t size); 259ssize_t readn(int fd, void *buf, size_t n);
260ssize_t writen(int fd, void *buf, size_t n);
257 261
258struct perf_event_attr; 262struct 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
287static 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
283size_t hex_width(u64 v); 298size_t hex_width(u64 v);
284int hex2u64(const char *ptr, u64 *val); 299int hex2u64(const char *ptr, u64 *val);
285 300
@@ -307,4 +322,11 @@ char *get_srcline(struct dso *dso, unsigned long addr);
307void free_srcline(char *srcline); 322void free_srcline(char *srcline);
308 323
309int filename__read_int(const char *filename, int *value); 324int filename__read_int(const char *filename, int *value);
325int filename__read_str(const char *filename, char **buf, size_t *sizep);
326int perf_event_paranoid(void);
327
328void mem_bswap_64(void *src, int byte_size);
329void mem_bswap_32(void *src, int byte_size);
330
331const 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
44static void perf_read_values__enlarge_threads(struct perf_read_values *values) 44static 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