aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-06-29 05:34:41 -0400
committerIngo Molnar <mingo@kernel.org>2016-06-29 05:34:41 -0400
commitd905768c9e1addfa35d9731dbaa9242e8991f6ac (patch)
treef80cc76eaf80b553799fa93358054fbfb94907e3
parentd4cf1949f9689314aef962eea95df84a8288d097 (diff)
parentebccba3fe0a02f622f80e6be0e8ecb1a9a3ed983 (diff)
Merge tag 'perf-core-for-mingo-20160628' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: - Generate comm, fork and exit events when converting perf.data files to CTF (Wang Nan) Infrastructure changes: - Add libbabeltrace to build-test (Wang Nan) - 'perf record' prep work to support multiple evlists (Wang Nan) - Remove unused hist_entry__annotate function (Ravi Bangoria) - Add more toolchain triplets (Ravi Bangoria) - Update message for slang devel packages on Ubuntu (Neeraj Badlani) - Generalize handling of 'ret' instructions in the annotate TUI (Naveen N. Rao) - Use proper dso name for is_regular_file, fixing device file handling (Jiri Olsa) Build Fixes: - Add missing config.h include, fixing the build with libbabeltrace (Jiri Olsa) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf-data.txt4
-rw-r--r--tools/perf/arch/common.c17
-rw-r--r--tools/perf/builtin-data.c11
-rw-r--r--tools/perf/builtin-record.c105
-rw-r--r--tools/perf/config/Makefile2
-rw-r--r--tools/perf/tests/make2
-rw-r--r--tools/perf/ui/browsers/annotate.c20
-rw-r--r--tools/perf/util/annotate.c15
-rw-r--r--tools/perf/util/annotate.h3
-rw-r--r--tools/perf/util/data-convert-bt.c196
-rw-r--r--tools/perf/util/data-convert-bt.h4
-rw-r--r--tools/perf/util/data-convert.h9
-rw-r--r--tools/perf/util/symbol.c2
13 files changed, 331 insertions, 59 deletions
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
index be8fa1a0a97e..f0796a47dfa3 100644
--- a/tools/perf/Documentation/perf-data.txt
+++ b/tools/perf/Documentation/perf-data.txt
@@ -34,6 +34,10 @@ OPTIONS for 'convert'
34--verbose:: 34--verbose::
35 Be more verbose (show counter open errors, etc). 35 Be more verbose (show counter open errors, etc).
36 36
37--all::
38 Convert all events, including non-sample events (comm, fork, ...), to output.
39 Default is off, only convert samples.
40
37SEE ALSO 41SEE ALSO
38-------- 42--------
39linkperf:perf[1] 43linkperf:perf[1]
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index fa090a9eaa38..ee6966812a5a 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -9,34 +9,44 @@ const char *const arm_triplets[] = {
9 "arm-unknown-linux-", 9 "arm-unknown-linux-",
10 "arm-unknown-linux-gnu-", 10 "arm-unknown-linux-gnu-",
11 "arm-unknown-linux-gnueabi-", 11 "arm-unknown-linux-gnueabi-",
12 "arm-linux-gnu-",
13 "arm-linux-gnueabihf-",
14 "arm-none-eabi-",
12 NULL 15 NULL
13}; 16};
14 17
15const char *const arm64_triplets[] = { 18const char *const arm64_triplets[] = {
16 "aarch64-linux-android-", 19 "aarch64-linux-android-",
20 "aarch64-linux-gnu-",
17 NULL 21 NULL
18}; 22};
19 23
20const char *const powerpc_triplets[] = { 24const char *const powerpc_triplets[] = {
21 "powerpc-unknown-linux-gnu-", 25 "powerpc-unknown-linux-gnu-",
22 "powerpc64-unknown-linux-gnu-", 26 "powerpc64-unknown-linux-gnu-",
27 "powerpc64-linux-gnu-",
28 "powerpc64le-linux-gnu-",
23 NULL 29 NULL
24}; 30};
25 31
26const char *const s390_triplets[] = { 32const char *const s390_triplets[] = {
27 "s390-ibm-linux-", 33 "s390-ibm-linux-",
34 "s390x-linux-gnu-",
28 NULL 35 NULL
29}; 36};
30 37
31const char *const sh_triplets[] = { 38const char *const sh_triplets[] = {
32 "sh-unknown-linux-gnu-", 39 "sh-unknown-linux-gnu-",
33 "sh64-unknown-linux-gnu-", 40 "sh64-unknown-linux-gnu-",
41 "sh-linux-gnu-",
42 "sh64-linux-gnu-",
34 NULL 43 NULL
35}; 44};
36 45
37const char *const sparc_triplets[] = { 46const char *const sparc_triplets[] = {
38 "sparc-unknown-linux-gnu-", 47 "sparc-unknown-linux-gnu-",
39 "sparc64-unknown-linux-gnu-", 48 "sparc64-unknown-linux-gnu-",
49 "sparc64-linux-gnu-",
40 NULL 50 NULL
41}; 51};
42 52
@@ -49,12 +59,19 @@ const char *const x86_triplets[] = {
49 "i386-pc-linux-gnu-", 59 "i386-pc-linux-gnu-",
50 "i686-linux-android-", 60 "i686-linux-android-",
51 "i686-android-linux-", 61 "i686-android-linux-",
62 "x86_64-linux-gnu-",
63 "i586-linux-gnu-",
52 NULL 64 NULL
53}; 65};
54 66
55const char *const mips_triplets[] = { 67const char *const mips_triplets[] = {
56 "mips-unknown-linux-gnu-", 68 "mips-unknown-linux-gnu-",
57 "mipsel-linux-android-", 69 "mipsel-linux-android-",
70 "mips-linux-gnu-",
71 "mips64-linux-gnu-",
72 "mips64el-linux-gnuabi64-",
73 "mips64-linux-gnuabi64-",
74 "mipsel-linux-gnu-",
58 NULL 75 NULL
59}; 76};
60 77
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index b97bc1518b44..7ad6e17ac6b3 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -3,6 +3,7 @@
3#include "perf.h" 3#include "perf.h"
4#include "debug.h" 4#include "debug.h"
5#include <subcmd/parse-options.h> 5#include <subcmd/parse-options.h>
6#include "data-convert.h"
6#include "data-convert-bt.h" 7#include "data-convert-bt.h"
7 8
8typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); 9typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
@@ -53,14 +54,18 @@ static int cmd_data_convert(int argc, const char **argv,
53 const char *prefix __maybe_unused) 54 const char *prefix __maybe_unused)
54{ 55{
55 const char *to_ctf = NULL; 56 const char *to_ctf = NULL;
56 bool force = false; 57 struct perf_data_convert_opts opts = {
58 .force = false,
59 .all = false,
60 };
57 const struct option options[] = { 61 const struct option options[] = {
58 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 62 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
59 OPT_STRING('i', "input", &input_name, "file", "input file name"), 63 OPT_STRING('i', "input", &input_name, "file", "input file name"),
60#ifdef HAVE_LIBBABELTRACE_SUPPORT 64#ifdef HAVE_LIBBABELTRACE_SUPPORT
61 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"), 65 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
62#endif 66#endif
63 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 67 OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"),
68 OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"),
64 OPT_END() 69 OPT_END()
65 }; 70 };
66 71
@@ -78,7 +83,7 @@ static int cmd_data_convert(int argc, const char **argv,
78 83
79 if (to_ctf) { 84 if (to_ctf) {
80#ifdef HAVE_LIBBABELTRACE_SUPPORT 85#ifdef HAVE_LIBBABELTRACE_SUPPORT
81 return bt_convert__perf2ctf(input_name, to_ctf, force); 86 return bt_convert__perf2ctf(input_name, to_ctf, &opts);
82#else 87#else
83 pr_err("The libbabeltrace support is not compiled in.\n"); 88 pr_err("The libbabeltrace support is not compiled in.\n");
84 return -1; 89 return -1;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 81411b14df4c..b2b3b600adf5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -132,9 +132,9 @@ rb_find_range(struct perf_evlist *evlist,
132 return backward_rb_find_range(data, mask, head, start, end); 132 return backward_rb_find_range(data, mask, head, start, end);
133} 133}
134 134
135static int record__mmap_read(struct record *rec, int idx) 135static int record__mmap_read(struct record *rec, struct perf_evlist *evlist, int idx)
136{ 136{
137 struct perf_mmap *md = &rec->evlist->mmap[idx]; 137 struct perf_mmap *md = &evlist->mmap[idx];
138 u64 head = perf_mmap__read_head(md); 138 u64 head = perf_mmap__read_head(md);
139 u64 old = md->prev; 139 u64 old = md->prev;
140 u64 end = head, start = old; 140 u64 end = head, start = old;
@@ -143,7 +143,7 @@ static int record__mmap_read(struct record *rec, int idx)
143 void *buf; 143 void *buf;
144 int rc = 0; 144 int rc = 0;
145 145
146 if (rb_find_range(rec->evlist, data, md->mask, head, 146 if (rb_find_range(evlist, data, md->mask, head,
147 old, &start, &end)) 147 old, &start, &end))
148 return -1; 148 return -1;
149 149
@@ -157,7 +157,7 @@ static int record__mmap_read(struct record *rec, int idx)
157 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 157 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
158 158
159 md->prev = head; 159 md->prev = head;
160 perf_evlist__mmap_consume(rec->evlist, idx); 160 perf_evlist__mmap_consume(evlist, idx);
161 return 0; 161 return 0;
162 } 162 }
163 163
@@ -182,7 +182,7 @@ static int record__mmap_read(struct record *rec, int idx)
182 } 182 }
183 183
184 md->prev = head; 184 md->prev = head;
185 perf_evlist__mmap_consume(rec->evlist, idx); 185 perf_evlist__mmap_consume(evlist, idx);
186out: 186out:
187 return rc; 187 return rc;
188} 188}
@@ -342,6 +342,40 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
342 342
343#endif 343#endif
344 344
345static int record__mmap_evlist(struct record *rec,
346 struct perf_evlist *evlist)
347{
348 struct record_opts *opts = &rec->opts;
349 char msg[512];
350
351 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
352 opts->auxtrace_mmap_pages,
353 opts->auxtrace_snapshot_mode) < 0) {
354 if (errno == EPERM) {
355 pr_err("Permission error mapping pages.\n"
356 "Consider increasing "
357 "/proc/sys/kernel/perf_event_mlock_kb,\n"
358 "or try again with a smaller value of -m/--mmap_pages.\n"
359 "(current value: %u,%u)\n",
360 opts->mmap_pages, opts->auxtrace_mmap_pages);
361 return -errno;
362 } else {
363 pr_err("failed to mmap with %d (%s)\n", errno,
364 strerror_r(errno, msg, sizeof(msg)));
365 if (errno)
366 return -errno;
367 else
368 return -EINVAL;
369 }
370 }
371 return 0;
372}
373
374static int record__mmap(struct record *rec)
375{
376 return record__mmap_evlist(rec, rec->evlist);
377}
378
345static int record__open(struct record *rec) 379static int record__open(struct record *rec)
346{ 380{
347 char msg[512]; 381 char msg[512];
@@ -378,27 +412,9 @@ try_again:
378 goto out; 412 goto out;
379 } 413 }
380 414
381 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 415 rc = record__mmap(rec);
382 opts->auxtrace_mmap_pages, 416 if (rc)
383 opts->auxtrace_snapshot_mode) < 0) {
384 if (errno == EPERM) {
385 pr_err("Permission error mapping pages.\n"
386 "Consider increasing "
387 "/proc/sys/kernel/perf_event_mlock_kb,\n"
388 "or try again with a smaller value of -m/--mmap_pages.\n"
389 "(current value: %u,%u)\n",
390 opts->mmap_pages, opts->auxtrace_mmap_pages);
391 rc = -errno;
392 } else {
393 pr_err("failed to mmap with %d (%s)\n", errno,
394 strerror_r(errno, msg, sizeof(msg)));
395 if (errno)
396 rc = -errno;
397 else
398 rc = -EINVAL;
399 }
400 goto out; 417 goto out;
401 }
402 418
403 session->evlist = evlist; 419 session->evlist = evlist;
404 perf_session__set_id_hdr_size(session); 420 perf_session__set_id_hdr_size(session);
@@ -482,17 +498,20 @@ static struct perf_event_header finished_round_event = {
482 .type = PERF_RECORD_FINISHED_ROUND, 498 .type = PERF_RECORD_FINISHED_ROUND,
483}; 499};
484 500
485static int record__mmap_read_all(struct record *rec) 501static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist)
486{ 502{
487 u64 bytes_written = rec->bytes_written; 503 u64 bytes_written = rec->bytes_written;
488 int i; 504 int i;
489 int rc = 0; 505 int rc = 0;
490 506
491 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 507 if (!evlist)
492 struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 508 return 0;
493 509
494 if (rec->evlist->mmap[i].base) { 510 for (i = 0; i < evlist->nr_mmaps; i++) {
495 if (record__mmap_read(rec, i) != 0) { 511 struct auxtrace_mmap *mm = &evlist->mmap[i].auxtrace_mmap;
512
513 if (evlist->mmap[i].base) {
514 if (record__mmap_read(rec, evlist, i) != 0) {
496 rc = -1; 515 rc = -1;
497 goto out; 516 goto out;
498 } 517 }
@@ -516,6 +535,17 @@ out:
516 return rc; 535 return rc;
517} 536}
518 537
538static int record__mmap_read_all(struct record *rec)
539{
540 int err;
541
542 err = record__mmap_read_evlist(rec, rec->evlist);
543 if (err)
544 return err;
545
546 return err;
547}
548
519static void record__init_features(struct record *rec) 549static void record__init_features(struct record *rec)
520{ 550{
521 struct perf_session *session = rec->session; 551 struct perf_session *session = rec->session;
@@ -656,10 +686,21 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused
656 return 0; 686 return 0;
657} 687}
658 688
689static const struct perf_event_mmap_page *
690perf_evlist__pick_pc(struct perf_evlist *evlist)
691{
692 if (evlist && evlist->mmap && evlist->mmap[0].base)
693 return evlist->mmap[0].base;
694 return NULL;
695}
696
659static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 697static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
660{ 698{
661 if (rec->evlist && rec->evlist->mmap && rec->evlist->mmap[0].base) 699 const struct perf_event_mmap_page *pc;
662 return rec->evlist->mmap[0].base; 700
701 pc = perf_evlist__pick_pc(rec->evlist);
702 if (pc)
703 return pc;
663 return NULL; 704 return NULL;
664} 705}
665 706
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 534c81176f6c..bf1a0a0dd0ad 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -482,7 +482,7 @@ endif
482 482
483ifndef NO_SLANG 483ifndef NO_SLANG
484 ifneq ($(feature-libslang), 1) 484 ifneq ($(feature-libslang), 1)
485 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); 485 msg := $(warning slang not found, disables TUI support. Please install slang-devel, libslang-dev or libslang2-dev);
486 NO_SLANG := 1 486 NO_SLANG := 1
487 else 487 else
488 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 488 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index cac15d93aea6..51966d92fc82 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -81,6 +81,7 @@ make_no_libbionic := NO_LIBBIONIC=1
81make_no_auxtrace := NO_AUXTRACE=1 81make_no_auxtrace := NO_AUXTRACE=1
82make_no_libbpf := NO_LIBBPF=1 82make_no_libbpf := NO_LIBBPF=1
83make_no_libcrypto := NO_LIBCRYPTO=1 83make_no_libcrypto := NO_LIBCRYPTO=1
84make_with_babeltrace:= LIBBABELTRACE=1
84make_tags := tags 85make_tags := tags
85make_cscope := cscope 86make_cscope := cscope
86make_help := help 87make_help := help
@@ -136,6 +137,7 @@ run += make_no_libaudit
136run += make_no_libbionic 137run += make_no_libbionic
137run += make_no_auxtrace 138run += make_no_auxtrace
138run += make_no_libbpf 139run += make_no_libbpf
140run += make_with_babeltrace
139run += make_help 141run += make_help
140run += make_doc 142run += make_doc
141run += make_perf_o 143run += make_perf_o
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 0e106bb97525..29dc6d20364e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -223,16 +223,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
223 } else if (ins__is_call(dl->ins)) { 223 } else if (ins__is_call(dl->ins)) {
224 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 224 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
225 SLsmg_write_char(' '); 225 SLsmg_write_char(' ');
226 } else if (ins__is_ret(dl->ins)) {
227 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
228 SLsmg_write_char(' ');
226 } else { 229 } else {
227 ui_browser__write_nstring(browser, " ", 2); 230 ui_browser__write_nstring(browser, " ", 2);
228 } 231 }
229 } else { 232 } else {
230 if (strcmp(dl->name, "retq")) { 233 ui_browser__write_nstring(browser, " ", 2);
231 ui_browser__write_nstring(browser, " ", 2);
232 } else {
233 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
234 SLsmg_write_char(' ');
235 }
236 } 234 }
237 235
238 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 236 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
@@ -843,14 +841,14 @@ show_help:
843 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 841 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
844 else if (browser->selection->offset == -1) 842 else if (browser->selection->offset == -1)
845 ui_helpline__puts("Actions are only available for assembly lines."); 843 ui_helpline__puts("Actions are only available for assembly lines.");
846 else if (!browser->selection->ins) { 844 else if (!browser->selection->ins)
847 if (strcmp(browser->selection->name, "retq")) 845 goto show_sup_ins;
848 goto show_sup_ins; 846 else if (ins__is_ret(browser->selection->ins))
849 goto out; 847 goto out;
850 } else if (!(annotate_browser__jump(browser) || 848 else if (!(annotate_browser__jump(browser) ||
851 annotate_browser__callq(browser, evsel, hbt))) { 849 annotate_browser__callq(browser, evsel, hbt))) {
852show_sup_ins: 850show_sup_ins:
853 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 851 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
854 } 852 }
855 continue; 853 continue;
856 case 't': 854 case 't':
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7e5a1e8874ce..c385fecb9d32 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -354,6 +354,15 @@ static struct ins_ops nop_ops = {
354 .scnprintf = nop__scnprintf, 354 .scnprintf = nop__scnprintf,
355}; 355};
356 356
357static struct ins_ops ret_ops = {
358 .scnprintf = ins__raw_scnprintf,
359};
360
361bool ins__is_ret(const struct ins *ins)
362{
363 return ins->ops == &ret_ops;
364}
365
357static struct ins instructions[] = { 366static struct ins instructions[] = {
358 { .name = "add", .ops = &mov_ops, }, 367 { .name = "add", .ops = &mov_ops, },
359 { .name = "addl", .ops = &mov_ops, }, 368 { .name = "addl", .ops = &mov_ops, },
@@ -444,6 +453,7 @@ static struct ins instructions[] = {
444 { .name = "xadd", .ops = &mov_ops, }, 453 { .name = "xadd", .ops = &mov_ops, },
445 { .name = "xbeginl", .ops = &jump_ops, }, 454 { .name = "xbeginl", .ops = &jump_ops, },
446 { .name = "xbeginq", .ops = &jump_ops, }, 455 { .name = "xbeginq", .ops = &jump_ops, },
456 { .name = "retq", .ops = &ret_ops, },
447}; 457};
448 458
449static int ins__key_cmp(const void *name, const void *insp) 459static int ins__key_cmp(const void *name, const void *insp)
@@ -1676,11 +1686,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1676 return 0; 1686 return 0;
1677} 1687}
1678 1688
1679int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1680{
1681 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1682}
1683
1684bool ui__has_annotation(void) 1689bool ui__has_annotation(void)
1685{ 1690{
1686 return use_browser == 1 && perf_hpp_list.sym; 1691 return use_browser == 1 && perf_hpp_list.sym;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 9241f8c2b7e1..a23084f54128 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -48,6 +48,7 @@ struct ins {
48 48
49bool ins__is_jump(const struct ins *ins); 49bool ins__is_jump(const struct ins *ins);
50bool ins__is_call(const struct ins *ins); 50bool ins__is_call(const struct ins *ins);
51bool ins__is_ret(const struct ins *ins);
51int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 52int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
52 53
53struct annotation; 54struct annotation;
@@ -156,8 +157,6 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
156 157
157int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 158int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
158 159
159int hist_entry__annotate(struct hist_entry *he, size_t privsize);
160
161int symbol__annotate_init(struct map *map, struct symbol *sym); 160int symbol__annotate_init(struct map *map, struct symbol *sym);
162int symbol__annotate_printf(struct symbol *sym, struct map *map, 161int symbol__annotate_printf(struct symbol *sym, struct map *map,
163 struct perf_evsel *evsel, bool full_paths, 162 struct perf_evsel *evsel, bool full_paths,
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 4b59879391c0..4f979bb27b6c 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -26,6 +26,7 @@
26#include "evlist.h" 26#include "evlist.h"
27#include "evsel.h" 27#include "evsel.h"
28#include "machine.h" 28#include "machine.h"
29#include "config.h"
29 30
30#define pr_N(n, fmt, ...) \ 31#define pr_N(n, fmt, ...) \
31 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 32 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
@@ -68,6 +69,9 @@ struct ctf_writer {
68 }; 69 };
69 struct bt_ctf_field_type *array[6]; 70 struct bt_ctf_field_type *array[6];
70 } data; 71 } data;
72 struct bt_ctf_event_class *comm_class;
73 struct bt_ctf_event_class *exit_class;
74 struct bt_ctf_event_class *fork_class;
71}; 75};
72 76
73struct convert { 77struct convert {
@@ -76,6 +80,7 @@ struct convert {
76 80
77 u64 events_size; 81 u64 events_size;
78 u64 events_count; 82 u64 events_count;
83 u64 non_sample_count;
79 84
80 /* Ordered events configured queue size. */ 85 /* Ordered events configured queue size. */
81 u64 queue_size; 86 u64 queue_size;
@@ -140,6 +145,36 @@ FUNC_VALUE_SET(s64)
140FUNC_VALUE_SET(u64) 145FUNC_VALUE_SET(u64)
141__FUNC_VALUE_SET(u64_hex, u64) 146__FUNC_VALUE_SET(u64_hex, u64)
142 147
148static int string_set_value(struct bt_ctf_field *field, const char *string);
149static __maybe_unused int
150value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
151 const char *name, const char *string)
152{
153 struct bt_ctf_field_type *type = cw->data.string;
154 struct bt_ctf_field *field;
155 int ret = 0;
156
157 field = bt_ctf_field_create(type);
158 if (!field) {
159 pr_err("failed to create a field %s\n", name);
160 return -1;
161 }
162
163 ret = string_set_value(field, string);
164 if (ret) {
165 pr_err("failed to set value %s\n", name);
166 goto err_put_field;
167 }
168
169 ret = bt_ctf_event_set_payload(event, name, field);
170 if (ret)
171 pr_err("failed to set payload %s\n", name);
172
173err_put_field:
174 bt_ctf_field_put(field);
175 return ret;
176}
177
143static struct bt_ctf_field_type* 178static struct bt_ctf_field_type*
144get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 179get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
145{ 180{
@@ -731,6 +766,72 @@ static int process_sample_event(struct perf_tool *tool,
731 return cs ? 0 : -1; 766 return cs ? 0 : -1;
732} 767}
733 768
769#define __NON_SAMPLE_SET_FIELD(_name, _type, _field) \
770do { \
771 ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
772 if (ret) \
773 return -1; \
774} while(0)
775
776#define __FUNC_PROCESS_NON_SAMPLE(_name, body) \
777static int process_##_name##_event(struct perf_tool *tool, \
778 union perf_event *_event, \
779 struct perf_sample *sample, \
780 struct machine *machine) \
781{ \
782 struct convert *c = container_of(tool, struct convert, tool);\
783 struct ctf_writer *cw = &c->writer; \
784 struct bt_ctf_event_class *event_class = cw->_name##_class;\
785 struct bt_ctf_event *event; \
786 struct ctf_stream *cs; \
787 int ret; \
788 \
789 c->non_sample_count++; \
790 c->events_size += _event->header.size; \
791 event = bt_ctf_event_create(event_class); \
792 if (!event) { \
793 pr_err("Failed to create an CTF event\n"); \
794 return -1; \
795 } \
796 \
797 bt_ctf_clock_set_time(cw->clock, sample->time); \
798 body \
799 cs = ctf_stream(cw, 0); \
800 if (cs) { \
801 if (is_flush_needed(cs)) \
802 ctf_stream__flush(cs); \
803 \
804 cs->count++; \
805 bt_ctf_stream_append_event(cs->stream, event); \
806 } \
807 bt_ctf_event_put(event); \
808 \
809 return perf_event__process_##_name(tool, _event, sample, machine);\
810}
811
812__FUNC_PROCESS_NON_SAMPLE(comm,
813 __NON_SAMPLE_SET_FIELD(comm, u32, pid);
814 __NON_SAMPLE_SET_FIELD(comm, u32, tid);
815 __NON_SAMPLE_SET_FIELD(comm, string, comm);
816)
817__FUNC_PROCESS_NON_SAMPLE(fork,
818 __NON_SAMPLE_SET_FIELD(fork, u32, pid);
819 __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
820 __NON_SAMPLE_SET_FIELD(fork, u32, tid);
821 __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
822 __NON_SAMPLE_SET_FIELD(fork, u64, time);
823)
824
825__FUNC_PROCESS_NON_SAMPLE(exit,
826 __NON_SAMPLE_SET_FIELD(fork, u32, pid);
827 __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
828 __NON_SAMPLE_SET_FIELD(fork, u32, tid);
829 __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
830 __NON_SAMPLE_SET_FIELD(fork, u64, time);
831)
832#undef __NON_SAMPLE_SET_FIELD
833#undef __FUNC_PROCESS_NON_SAMPLE
834
734/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ 835/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
735static char *change_name(char *name, char *orig_name, int dup) 836static char *change_name(char *name, char *orig_name, int dup)
736{ 837{
@@ -1005,6 +1106,80 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
1005 return 0; 1106 return 0;
1006} 1107}
1007 1108
1109#define __NON_SAMPLE_ADD_FIELD(t, n) \
1110 do { \
1111 pr2(" field '%s'\n", #n); \
1112 if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
1113 pr_err("Failed to add field '%s';\n", #n);\
1114 return -1; \
1115 } \
1116 } while(0)
1117
1118#define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) \
1119static int add_##_name##_event(struct ctf_writer *cw) \
1120{ \
1121 struct bt_ctf_event_class *event_class; \
1122 int ret; \
1123 \
1124 pr("Adding "#_name" event\n"); \
1125 event_class = bt_ctf_event_class_create("perf_" #_name);\
1126 if (!event_class) \
1127 return -1; \
1128 body \
1129 \
1130 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
1131 if (ret) { \
1132 pr("Failed to add event class '"#_name"' into stream.\n");\
1133 return ret; \
1134 } \
1135 \
1136 cw->_name##_class = event_class; \
1137 bt_ctf_event_class_put(event_class); \
1138 return 0; \
1139}
1140
1141__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
1142 __NON_SAMPLE_ADD_FIELD(u32, pid);
1143 __NON_SAMPLE_ADD_FIELD(u32, tid);
1144 __NON_SAMPLE_ADD_FIELD(string, comm);
1145)
1146
1147__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork,
1148 __NON_SAMPLE_ADD_FIELD(u32, pid);
1149 __NON_SAMPLE_ADD_FIELD(u32, ppid);
1150 __NON_SAMPLE_ADD_FIELD(u32, tid);
1151 __NON_SAMPLE_ADD_FIELD(u32, ptid);
1152 __NON_SAMPLE_ADD_FIELD(u64, time);
1153)
1154
1155__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1156 __NON_SAMPLE_ADD_FIELD(u32, pid);
1157 __NON_SAMPLE_ADD_FIELD(u32, ppid);
1158 __NON_SAMPLE_ADD_FIELD(u32, tid);
1159 __NON_SAMPLE_ADD_FIELD(u32, ptid);
1160 __NON_SAMPLE_ADD_FIELD(u64, time);
1161)
1162
1163#undef __NON_SAMPLE_ADD_FIELD
1164#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1165
1166static int setup_non_sample_events(struct ctf_writer *cw,
1167 struct perf_session *session __maybe_unused)
1168{
1169 int ret;
1170
1171 ret = add_comm_event(cw);
1172 if (ret)
1173 return ret;
1174 ret = add_exit_event(cw);
1175 if (ret)
1176 return ret;
1177 ret = add_fork_event(cw);
1178 if (ret)
1179 return ret;
1180 return 0;
1181}
1182
1008static void cleanup_events(struct perf_session *session) 1183static void cleanup_events(struct perf_session *session)
1009{ 1184{
1010 struct perf_evlist *evlist = session->evlist; 1185 struct perf_evlist *evlist = session->evlist;
@@ -1273,13 +1448,14 @@ static int convert__config(const char *var, const char *value, void *cb)
1273 return 0; 1448 return 0;
1274} 1449}
1275 1450
1276int bt_convert__perf2ctf(const char *input, const char *path, bool force) 1451int bt_convert__perf2ctf(const char *input, const char *path,
1452 struct perf_data_convert_opts *opts)
1277{ 1453{
1278 struct perf_session *session; 1454 struct perf_session *session;
1279 struct perf_data_file file = { 1455 struct perf_data_file file = {
1280 .path = input, 1456 .path = input,
1281 .mode = PERF_DATA_MODE_READ, 1457 .mode = PERF_DATA_MODE_READ,
1282 .force = force, 1458 .force = opts->force,
1283 }; 1459 };
1284 struct convert c = { 1460 struct convert c = {
1285 .tool = { 1461 .tool = {
@@ -1299,6 +1475,12 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1299 struct ctf_writer *cw = &c.writer; 1475 struct ctf_writer *cw = &c.writer;
1300 int err = -1; 1476 int err = -1;
1301 1477
1478 if (opts->all) {
1479 c.tool.comm = process_comm_event;
1480 c.tool.exit = process_exit_event;
1481 c.tool.fork = process_fork_event;
1482 }
1483
1302 perf_config(convert__config, &c); 1484 perf_config(convert__config, &c);
1303 1485
1304 /* CTF writer */ 1486 /* CTF writer */
@@ -1323,6 +1505,9 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1323 if (setup_events(cw, session)) 1505 if (setup_events(cw, session))
1324 goto free_session; 1506 goto free_session;
1325 1507
1508 if (opts->all && setup_non_sample_events(cw, session))
1509 goto free_session;
1510
1326 if (setup_streams(cw, session)) 1511 if (setup_streams(cw, session))
1327 goto free_session; 1512 goto free_session;
1328 1513
@@ -1337,10 +1522,15 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1337 file.path, path); 1522 file.path, path);
1338 1523
1339 fprintf(stderr, 1524 fprintf(stderr,
1340 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n", 1525 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1341 (double) c.events_size / 1024.0 / 1024.0, 1526 (double) c.events_size / 1024.0 / 1024.0,
1342 c.events_count); 1527 c.events_count);
1343 1528
1529 if (!c.non_sample_count)
1530 fprintf(stderr, ") ]\n");
1531 else
1532 fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
1533
1344 cleanup_events(session); 1534 cleanup_events(session);
1345 perf_session__delete(session); 1535 perf_session__delete(session);
1346 ctf_writer__cleanup(cw); 1536 ctf_writer__cleanup(cw);
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
index 4c204342a9d8..9a3b587f76c1 100644
--- a/tools/perf/util/data-convert-bt.h
+++ b/tools/perf/util/data-convert-bt.h
@@ -1,8 +1,10 @@
1#ifndef __DATA_CONVERT_BT_H 1#ifndef __DATA_CONVERT_BT_H
2#define __DATA_CONVERT_BT_H 2#define __DATA_CONVERT_BT_H
3#include "data-convert.h"
3#ifdef HAVE_LIBBABELTRACE_SUPPORT 4#ifdef HAVE_LIBBABELTRACE_SUPPORT
4 5
5int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, bool force); 6int bt_convert__perf2ctf(const char *input_name, const char *to_ctf,
7 struct perf_data_convert_opts *opts);
6 8
7#endif /* HAVE_LIBBABELTRACE_SUPPORT */ 9#endif /* HAVE_LIBBABELTRACE_SUPPORT */
8#endif /* __DATA_CONVERT_BT_H */ 10#endif /* __DATA_CONVERT_BT_H */
diff --git a/tools/perf/util/data-convert.h b/tools/perf/util/data-convert.h
new file mode 100644
index 000000000000..5314962fe95b
--- /dev/null
+++ b/tools/perf/util/data-convert.h
@@ -0,0 +1,9 @@
1#ifndef __DATA_CONVERT_H
2#define __DATA_CONVERT_H
3
4struct perf_data_convert_opts {
5 bool force;
6 bool all;
7};
8
9#endif /* __DATA_CONVERT_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b044f1a32d16..37e8d20ae03e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1430,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1430 * Read the build id if possible. This is required for 1430 * Read the build id if possible. This is required for
1431 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1431 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
1432 */ 1432 */
1433 if (is_regular_file(name) && 1433 if (is_regular_file(dso->long_name) &&
1434 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1434 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
1435 dso__set_build_id(dso, build_id); 1435 dso__set_build_id(dso, build_id);
1436 1436